diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index e7c7a27fb..719998c1d 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - target: ['cig_wf188', 'cig_wf194c', 'cig_wf160d.yml', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_ecs4100-12ph', 'edgecore_ecw5211', 'linksys_e8450', 'linksys_ea8300', 'tplink_cpe210_v3', 'tplink_ex227', 'tplink_ex447', 'zyxel_gs1900-10hp'] + target: ['cig_wf188', 'cig_wf194c', 'cig_wf160d.yml', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_ecs4100-12ph', 'edgecore_ecw5211', 'linksys_e8450', 'linksys_ea8300', 'mikrotik_rb91x', 'tplink_cpe210_v3', 'tplink_ex227', 'tplink_ex447', 'zyxel_gs1900-10hp'] steps: - uses: actions/checkout@v2 diff --git a/backports/0009-include-set-kernel-version.mk.patch b/backports/0009-include-set-kernel-version.mk.patch index 41ee36e55..5d2bda583 100644 --- a/backports/0009-include-set-kernel-version.mk.patch +++ b/backports/0009-include-set-kernel-version.mk.patch @@ -1,26 +1,28 @@ -From 0e4596cd23310f6aacc88093edfed5bfda79e27f Mon Sep 17 00:00:00 2001 +From 3b896a540de03ca8dfd5596881f9ec6dc15d72c9 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 7 Apr 2021 10:46:26 +0200 -Subject: [PATCH 9/9] include: set kernel-version.mk +Subject: [PATCH 01/32] include: set kernel-version.mk Signed-off-by: John Crispin --- - include/kernel-version.mk | 4 ++++ - 1 file changed, 4 insertions(+) + include/kernel-version.mk | 6 ++++++ + 1 file changed, 6 insertions(+) diff --git a/include/kernel-version.mk b/include/kernel-version.mk -index 52e5c11d75..f6f4a14779 100644 +index 52e5c11d75..547f57fa11 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk -@@ -6,9 +6,13 @@ ifdef CONFIG_TESTING_KERNEL +@@ -6,9 +6,15 @@ ifdef CONFIG_TESTING_KERNEL KERNEL_PATCHVER:=$(KERNEL_TESTING_PATCHVER) endif +LINUX_VERSION-4.4 = .60 ++LINUX_VERSION-4.14 = .193 LINUX_VERSION-5.4 = .111 +LINUX_VERSION-5.10 = .27 +LINUX_KERNEL_HASH-4.4.60 = 2cd8df6f1ac6a5329c5a286ec9b5956215977221a1b731597ed169fff74a9659 ++LINUX_KERNEL_HASH-4.14.193 = 0b0fb41d4430e1a42738b341cbfd2f41951aa5cd02acabbd53f076119c8b9f03 LINUX_KERNEL_HASH-5.4.111 = 21626132658dc34cb41b7aa7b80ecf83751890a71ac1a63d77aea9d488271a03 +LINUX_KERNEL_HASH-5.10.27 = d99dc9662951299c53a0a8d8c8d0a72a16ff861d20e927c0f9b14f63282d69d9 diff --git a/backports/0010-ar71xx-forward-port-target-to-get-routerboard-suppor.patch b/backports/0010-ar71xx-forward-port-target-to-get-routerboard-suppor.patch new file mode 100644 index 000000000..5e55aa44a --- /dev/null +++ b/backports/0010-ar71xx-forward-port-target-to-get-routerboard-suppor.patch @@ -0,0 +1,137757 @@ +From b6a89df399cae510f531473e04b5fd938b811ed7 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 20 Apr 2021 11:13:20 +0200 +Subject: [PATCH 02/32] ar71xx: forward port target to get routerboard support + +This is only a 1 month interim until the new nand driver for ath79 is ready + +Signed-off-by: John Crispin +--- + config/Config-images.in | 1 + + package/kernel/linux/modules/usb.mk | 2 +- + package/kernel/mac80211/ath.mk | 9 +- + target/linux/ar71xx/Makefile | 24 + + .../ar71xx/base-files/etc/board.d/01_leds | 1130 ++++ + .../ar71xx/base-files/etc/board.d/02_network | 711 ++ + .../base-files/etc/board.d/03_gpio_switches | 42 + + target/linux/ar71xx/base-files/etc/diag.sh | 599 ++ + .../etc/hotplug.d/firmware/10-ath9k-eeprom | 178 + + .../etc/hotplug.d/firmware/11-ath10k-caldata | 195 + + .../etc/hotplug.d/ieee80211/10_fix_wifi_mac | 24 + + .../etc/hotplug.d/net/10-ar922x-led-fix | 52 + + target/linux/ar71xx/base-files/etc/inittab | 3 + + .../uci-defaults/03_network-switchX-migration | 108 + + .../uci-defaults/03_network-vlan-migration | 13 + + .../etc/uci-defaults/04_led_migration | 84 + + .../etc/uci-defaults/09_fix-checksum | 28 + + .../etc/uci-defaults/09_fix-seama-header | 17 + + target/linux/ar71xx/base-files/lib/ar71xx.sh | 1589 +++++ + .../lib/preinit/01_preinit_do_ar71xx.sh | 9 + + .../lib/preinit/05_set_iface_mac_ar71xx | 60 + + .../lib/preinit/05_set_preinit_iface_ar71xx | 57 + + .../base-files/lib/preinit/82_patch_ath10k | 50 + + .../ar71xx/base-files/lib/upgrade/allnet.sh | 155 + + .../ar71xx/base-files/lib/upgrade/dir825.sh | 165 + + .../base-files/lib/upgrade/merakinand.sh | 165 + + .../ar71xx/base-files/lib/upgrade/openmesh.sh | 232 + + .../ar71xx/base-files/lib/upgrade/platform.sh | 915 +++ + target/linux/ar71xx/config-4.14 | 477 ++ + .../files/arch/mips/ath79/Kconfig.openwrt | 2458 +++++++ + .../ar71xx/files/arch/mips/ath79/Makefile | 290 + + .../files/arch/mips/ath79/dev-ap9x-pci.c | 173 + + .../files/arch/mips/ath79/dev-ap9x-pci.h | 55 + + .../ar71xx/files/arch/mips/ath79/dev-dsa.c | 36 + + .../ar71xx/files/arch/mips/ath79/dev-dsa.h | 21 + + .../ar71xx/files/arch/mips/ath79/dev-eth.c | 1262 ++++ + .../ar71xx/files/arch/mips/ath79/dev-eth.h | 55 + + .../ar71xx/files/arch/mips/ath79/dev-m25p80.c | 101 + + .../ar71xx/files/arch/mips/ath79/dev-m25p80.h | 17 + + .../ar71xx/files/arch/mips/ath79/dev-nfc.c | 141 + + .../ar71xx/files/arch/mips/ath79/dev-nfc.h | 34 + + .../ar71xx/files/arch/mips/ath79/mach-a60.c | 181 + + .../files/arch/mips/ath79/mach-alfa-ap120c.c | 147 + + .../files/arch/mips/ath79/mach-alfa-ap96.c | 132 + + .../files/arch/mips/ath79/mach-alfa-nx.c | 113 + + .../files/arch/mips/ath79/mach-all0258n.c | 88 + + .../files/arch/mips/ath79/mach-all0315n.c | 85 + + .../files/arch/mips/ath79/mach-antminer-s1.c | 98 + + .../files/arch/mips/ath79/mach-antminer-s3.c | 103 + + .../files/arch/mips/ath79/mach-antrouter-r1.c | 98 + + .../files/arch/mips/ath79/mach-ap121f.c | 103 + + .../ar71xx/files/arch/mips/ath79/mach-ap132.c | 189 + + .../ar71xx/files/arch/mips/ath79/mach-ap143.c | 142 + + .../ar71xx/files/arch/mips/ath79/mach-ap147.c | 125 + + .../ar71xx/files/arch/mips/ath79/mach-ap152.c | 140 + + .../files/arch/mips/ath79/mach-ap531b0.c | 112 + + .../ar71xx/files/arch/mips/ath79/mach-ap90q.c | 201 + + .../files/arch/mips/ath79/mach-ap91-5g.c | 118 + + .../ar71xx/files/arch/mips/ath79/mach-ap96.c | 142 + + .../arch/mips/ath79/mach-archer-c25-v1.c | 227 + + .../arch/mips/ath79/mach-archer-c59-v1.c | 342 + + .../arch/mips/ath79/mach-archer-c60-v1.c | 225 + + .../files/arch/mips/ath79/mach-archer-c7-v4.c | 260 + + .../files/arch/mips/ath79/mach-archer-c7-v5.c | 207 + + .../files/arch/mips/ath79/mach-archer-c7.c | 349 + + .../files/arch/mips/ath79/mach-arduino-yun.c | 156 + + .../files/arch/mips/ath79/mach-aw-nr580.c | 107 + + .../files/arch/mips/ath79/mach-bhr-4grv2.c | 171 + + .../arch/mips/ath79/mach-bhu-bxu2000n2-a.c | 120 + + .../ar71xx/files/arch/mips/ath79/mach-bsb.c | 83 + + .../ar71xx/files/arch/mips/ath79/mach-c55.c | 132 + + .../ar71xx/files/arch/mips/ath79/mach-c60.c | 265 + + .../files/arch/mips/ath79/mach-cap324.c | 133 + + .../files/arch/mips/ath79/mach-cap4200ag.c | 131 + + .../files/arch/mips/ath79/mach-carambola2.c | 105 + + .../files/arch/mips/ath79/mach-cf-e316n-v2.c | 765 +++ + .../files/arch/mips/ath79/mach-cpe510.c | 281 + + .../files/arch/mips/ath79/mach-cpe870.c | 152 + + .../files/arch/mips/ath79/mach-cr3000.c | 168 + + .../files/arch/mips/ath79/mach-cr5000.c | 179 + + .../files/arch/mips/ath79/mach-dap-1330-a1.c | 146 + + .../files/arch/mips/ath79/mach-dap-2695-a1.c | 191 + + .../files/arch/mips/ath79/mach-dgl-5500-a1.c | 150 + + .../files/arch/mips/ath79/mach-dhp-1565-a1.c | 170 + + .../files/arch/mips/ath79/mach-dir-505-a1.c | 116 + + .../files/arch/mips/ath79/mach-dir-600-a1.c | 162 + + .../files/arch/mips/ath79/mach-dir-615-c1.c | 135 + + .../files/arch/mips/ath79/mach-dir-615-i1.c | 133 + + .../files/arch/mips/ath79/mach-dir-825-b1.c | 191 + + .../files/arch/mips/ath79/mach-dir-825-c1.c | 241 + + .../files/arch/mips/ath79/mach-dir-869-a1.c | 175 + + .../files/arch/mips/ath79/mach-dlan-hotspot.c | 117 + + .../arch/mips/ath79/mach-dlan-pro-1200-ac.c | 190 + + .../arch/mips/ath79/mach-dlan-pro-500-wp.c | 203 + + .../arch/mips/ath79/mach-domywifi-dw33d.c | 192 + + .../ar71xx/files/arch/mips/ath79/mach-dr344.c | 224 + + .../ar71xx/files/arch/mips/ath79/mach-dr531.c | 155 + + .../files/arch/mips/ath79/mach-dragino2.c | 136 + + .../files/arch/mips/ath79/mach-e1700ac-v2.c | 145 + + .../files/arch/mips/ath79/mach-e2100l.c | 126 + + .../files/arch/mips/ath79/mach-e558-v2.c | 170 + + .../files/arch/mips/ath79/mach-e600g-v2.c | 184 + + .../files/arch/mips/ath79/mach-e750a-v4.c | 122 + + .../files/arch/mips/ath79/mach-e750g-v8.c | 151 + + .../files/arch/mips/ath79/mach-eap120.c | 126 + + .../files/arch/mips/ath79/mach-eap300v2.c | 101 + + .../files/arch/mips/ath79/mach-eap7660d.c | 181 + + .../files/arch/mips/ath79/mach-el-m150.c | 112 + + .../files/arch/mips/ath79/mach-el-mini.c | 86 + + .../files/arch/mips/ath79/mach-ens202ext.c | 124 + + .../files/arch/mips/ath79/mach-epg5000.c | 177 + + .../files/arch/mips/ath79/mach-esr1750.c | 176 + + .../files/arch/mips/ath79/mach-esr900.c | 200 + + .../files/arch/mips/ath79/mach-ew-balin.c | 110 + + .../files/arch/mips/ath79/mach-ew-dorin.c | 138 + + .../files/arch/mips/ath79/mach-f9k1115v2.c | 189 + + .../files/arch/mips/ath79/mach-fritz300e.c | 132 + + .../files/arch/mips/ath79/mach-fritz4020.c | 242 + + .../files/arch/mips/ath79/mach-fritz450e.c | 179 + + .../files/arch/mips/ath79/mach-gl-ar150.c | 125 + + .../files/arch/mips/ath79/mach-gl-ar300.c | 103 + + .../files/arch/mips/ath79/mach-gl-ar300m.c | 158 + + .../files/arch/mips/ath79/mach-gl-ar750.c | 146 + + .../files/arch/mips/ath79/mach-gl-ar750s.c | 193 + + .../files/arch/mips/ath79/mach-gl-domino.c | 136 + + .../files/arch/mips/ath79/mach-gl-inet.c | 104 + + .../files/arch/mips/ath79/mach-gl-mifi.c | 114 + + .../files/arch/mips/ath79/mach-gl-usb150.c | 87 + + .../arch/mips/ath79/mach-gs-minibox-v32.c | 121 + + .../files/arch/mips/ath79/mach-gs-oolite-v1.c | 143 + + .../arch/mips/ath79/mach-gs-oolite-v5-2.c | 111 + + .../files/arch/mips/ath79/mach-hiveap-121.c | 153 + + .../arch/mips/ath79/mach-hiwifi-hc6361.c | 115 + + .../files/arch/mips/ath79/mach-hornet-ub.c | 142 + + .../files/arch/mips/ath79/mach-ja76pf.c | 190 + + .../files/arch/mips/ath79/mach-jwap003.c | 95 + + .../files/arch/mips/ath79/mach-jwap230.c | 158 + + .../ar71xx/files/arch/mips/ath79/mach-koala.c | 161 + + .../files/arch/mips/ath79/mach-lan-turtle.c | 178 + + .../ar71xx/files/arch/mips/ath79/mach-lima.c | 86 + + .../files/arch/mips/ath79/mach-mc-mac1200r.c | 155 + + .../ar71xx/files/arch/mips/ath79/mach-mr12.c | 114 + + .../ar71xx/files/arch/mips/ath79/mach-mr16.c | 118 + + .../files/arch/mips/ath79/mach-mr1750.c | 171 + + .../ar71xx/files/arch/mips/ath79/mach-mr18.c | 286 + + .../ar71xx/files/arch/mips/ath79/mach-mr600.c | 177 + + .../ar71xx/files/arch/mips/ath79/mach-mr900.c | 181 + + .../files/arch/mips/ath79/mach-mynet-n600.c | 202 + + .../files/arch/mips/ath79/mach-mynet-n750.c | 226 + + .../files/arch/mips/ath79/mach-mynet-rext.c | 208 + + .../files/arch/mips/ath79/mach-mzk-w04nu.c | 124 + + .../files/arch/mips/ath79/mach-mzk-w300nh.c | 115 + + .../ar71xx/files/arch/mips/ath79/mach-n5q.c | 132 + + .../files/arch/mips/ath79/mach-nbg460n.c | 220 + + .../files/arch/mips/ath79/mach-nbg6716.c | 385 ++ + .../ar71xx/files/arch/mips/ath79/mach-om2p.c | 320 + + .../ar71xx/files/arch/mips/ath79/mach-om5p.c | 218 + + .../files/arch/mips/ath79/mach-om5pac.c | 193 + + .../files/arch/mips/ath79/mach-om5pacv2.c | 215 + + .../files/arch/mips/ath79/mach-omy-g1.c | 123 + + .../files/arch/mips/ath79/mach-omy-x1.c | 106 + + .../files/arch/mips/ath79/mach-onion-omega.c | 84 + + .../ar71xx/files/arch/mips/ath79/mach-pb42.c | 83 + + .../files/arch/mips/ath79/mach-pqi-air-pen.c | 99 + + .../files/arch/mips/ath79/mach-qihoo-c301.c | 166 + + .../ar71xx/files/arch/mips/ath79/mach-r36a.c | 140 + + .../ar71xx/files/arch/mips/ath79/mach-r602n.c | 213 + + .../ar71xx/files/arch/mips/ath79/mach-r6100.c | 146 + + .../files/arch/mips/ath79/mach-rambutan.c | 92 + + .../files/arch/mips/ath79/mach-rb2011.c | 406 ++ + .../ar71xx/files/arch/mips/ath79/mach-rb4xx.c | 465 ++ + .../ar71xx/files/arch/mips/ath79/mach-rb750.c | 349 + + .../ar71xx/files/arch/mips/ath79/mach-rb91x.c | 348 + + .../ar71xx/files/arch/mips/ath79/mach-rb922.c | 361 + + .../ar71xx/files/arch/mips/ath79/mach-rb95x.c | 327 + + .../ar71xx/files/arch/mips/ath79/mach-rbspi.c | 1262 ++++ + .../files/arch/mips/ath79/mach-rbsxtlite.c | 302 + + .../ar71xx/files/arch/mips/ath79/mach-re450.c | 239 + + .../files/arch/mips/ath79/mach-rme-eg200.c | 99 + + .../files/arch/mips/ath79/mach-rut9xx.c | 191 + + .../files/arch/mips/ath79/mach-rw2458n.c | 91 + + .../files/arch/mips/ath79/mach-sc1750.c | 145 + + .../files/arch/mips/ath79/mach-sc300m.c | 132 + + .../ar71xx/files/arch/mips/ath79/mach-sc450.c | 149 + + .../files/arch/mips/ath79/mach-smart-300.c | 135 + + .../files/arch/mips/ath79/mach-som9331.c | 125 + + .../files/arch/mips/ath79/mach-sr3200.c | 187 + + .../ar71xx/files/arch/mips/ath79/mach-t830.c | 127 + + .../mips/ath79/mach-tellstick-znet-lite.c | 129 + + .../files/arch/mips/ath79/mach-tew-632brp.c | 111 + + .../files/arch/mips/ath79/mach-tew-673gru.c | 198 + + .../files/arch/mips/ath79/mach-tew-712br.c | 153 + + .../files/arch/mips/ath79/mach-tew-732br.c | 127 + + .../files/arch/mips/ath79/mach-tew-823dru.c | 181 + + .../files/arch/mips/ath79/mach-tl-mr11u.c | 183 + + .../files/arch/mips/ath79/mach-tl-mr13u.c | 107 + + .../files/arch/mips/ath79/mach-tl-mr3020.c | 126 + + .../files/arch/mips/ath79/mach-tl-mr3x20.c | 147 + + .../files/arch/mips/ath79/mach-tl-mr6400.c | 151 + + .../arch/mips/ath79/mach-tl-wa701nd-v2.c | 116 + + .../arch/mips/ath79/mach-tl-wa7210n-v2.c | 125 + + .../arch/mips/ath79/mach-tl-wa801nd-v3.c | 137 + + .../arch/mips/ath79/mach-tl-wa830re-v2.c | 132 + + .../arch/mips/ath79/mach-tl-wa901nd-v2.c | 104 + + .../arch/mips/ath79/mach-tl-wa901nd-v4.c | 115 + + .../files/arch/mips/ath79/mach-tl-wa901nd.c | 127 + + .../files/arch/mips/ath79/mach-tl-wax50re.c | 445 ++ + .../arch/mips/ath79/mach-tl-wdr3320-v2.c | 146 + + .../files/arch/mips/ath79/mach-tl-wdr3500.c | 169 + + .../files/arch/mips/ath79/mach-tl-wdr4300.c | 206 + + .../arch/mips/ath79/mach-tl-wdr6500-v2.c | 142 + + .../files/arch/mips/ath79/mach-tl-wpa8630.c | 172 + + .../arch/mips/ath79/mach-tl-wr1041n-v2.c | 157 + + .../arch/mips/ath79/mach-tl-wr1043nd-v2.c | 215 + + .../arch/mips/ath79/mach-tl-wr1043nd-v4.c | 283 + + .../files/arch/mips/ath79/mach-tl-wr1043nd.c | 141 + + .../files/arch/mips/ath79/mach-tl-wr2543n.c | 150 + + .../files/arch/mips/ath79/mach-tl-wr703n.c | 118 + + .../files/arch/mips/ath79/mach-tl-wr720n-v3.c | 108 + + .../arch/mips/ath79/mach-tl-wr741nd-v4.c | 187 + + .../files/arch/mips/ath79/mach-tl-wr741nd.c | 130 + + .../files/arch/mips/ath79/mach-tl-wr802n.c | 117 + + .../files/arch/mips/ath79/mach-tl-wr810n.c | 149 + + .../files/arch/mips/ath79/mach-tl-wr841n-v8.c | 286 + + .../files/arch/mips/ath79/mach-tl-wr841n-v9.c | 457 ++ + .../files/arch/mips/ath79/mach-tl-wr841n.c | 140 + + .../arch/mips/ath79/mach-tl-wr902ac-v1.c | 145 + + .../files/arch/mips/ath79/mach-tl-wr940n-v4.c | 184 + + .../arch/mips/ath79/mach-tl-wr941nd-v6.c | 149 + + .../files/arch/mips/ath79/mach-tl-wr941nd.c | 121 + + .../files/arch/mips/ath79/mach-tl-wr942n-v1.c | 279 + + .../files/arch/mips/ath79/mach-ts-d084.c | 86 + + .../files/arch/mips/ath79/mach-tube2h.c | 129 + + .../files/arch/mips/ath79/mach-ubnt-unifiac.c | 179 + + .../files/arch/mips/ath79/mach-ubnt-xm.c | 781 +++ + .../ar71xx/files/arch/mips/ath79/mach-ubnt.c | 205 + + .../files/arch/mips/ath79/mach-wam250.c | 122 + + .../ar71xx/files/arch/mips/ath79/mach-weio.c | 140 + + .../files/arch/mips/ath79/mach-whr-hp-g300n.c | 155 + + .../files/arch/mips/ath79/mach-wi2a-ac200i.c | 217 + + .../mips/ath79/mach-wifi-pineapple-nano.c | 107 + + .../files/arch/mips/ath79/mach-wlae-ag300n.c | 114 + + .../files/arch/mips/ath79/mach-wlr8100.c | 195 + + .../files/arch/mips/ath79/mach-wndap360.c | 105 + + .../files/arch/mips/ath79/mach-wndr3700.c | 172 + + .../files/arch/mips/ath79/mach-wndr4300.c | 215 + + .../files/arch/mips/ath79/mach-wnr2000-v3.c | 637 ++ + .../files/arch/mips/ath79/mach-wnr2000-v4.c | 214 + + .../files/arch/mips/ath79/mach-wnr2000.c | 102 + + .../files/arch/mips/ath79/mach-wnr2200.c | 246 + + .../ar71xx/files/arch/mips/ath79/mach-wp543.c | 109 + + .../ar71xx/files/arch/mips/ath79/mach-wpe72.c | 97 + + .../files/arch/mips/ath79/mach-wpj342.c | 178 + + .../files/arch/mips/ath79/mach-wpj344.c | 169 + + .../files/arch/mips/ath79/mach-wpj531.c | 143 + + .../files/arch/mips/ath79/mach-wpj558.c | 170 + + .../files/arch/mips/ath79/mach-wpj563.c | 150 + + .../files/arch/mips/ath79/mach-wrt160nl.c | 126 + + .../files/arch/mips/ath79/mach-wrt400n.c | 161 + + .../files/arch/mips/ath79/mach-wrtnode2q.c | 126 + + .../files/arch/mips/ath79/mach-wzr-450hp2.c | 221 + + .../arch/mips/ath79/mach-wzr-hp-ag300h.c | 202 + + .../arch/mips/ath79/mach-wzr-hp-g300nh.c | 279 + + .../arch/mips/ath79/mach-wzr-hp-g300nh2.c | 174 + + .../files/arch/mips/ath79/mach-wzr-hp-g450h.c | 169 + + .../ar71xx/files/arch/mips/ath79/mach-z1.c | 164 + + .../files/arch/mips/ath79/mach-zbt-we1526.c | 153 + + .../files/arch/mips/ath79/mach-zcn-1523h.c | 154 + + .../ar71xx/files/arch/mips/ath79/machtypes.h | 387 ++ + .../ar71xx/files/arch/mips/ath79/nvram.c | 85 + + .../ar71xx/files/arch/mips/ath79/nvram.h | 19 + + .../files/arch/mips/ath79/pci-ath9k-fixup.c | 126 + + .../files/arch/mips/ath79/pci-ath9k-fixup.h | 6 + + .../ar71xx/files/arch/mips/ath79/routerboot.c | 354 + + .../ar71xx/files/arch/mips/ath79/routerboot.h | 89 + + .../mips/include/asm/fw/myloader/myloader.h | 34 + + .../include/asm/mach-ath79/ag71xx_platform.h | 65 + + .../mips/include/asm/mach-ath79/mach-rb750.h | 84 + + .../mips/include/asm/mach-ath79/rb4xx_cpld.h | 43 + + .../ar71xx/files/drivers/gpio/gpio-latch.c | 220 + + .../files/drivers/gpio/gpio-nxp-74hc153.c | 243 + + .../ar71xx/files/drivers/leds/leds-nu801.c | 396 ++ + .../ar71xx/files/drivers/leds/leds-rb750.c | 144 + + .../files/drivers/leds/leds-wndr3700-usb.c | 76 + + .../ar71xx/files/drivers/mtd/cybertan_part.c | 206 + + .../files/drivers/mtd/nand/ar934x_nfc.c | 1591 +++++ + .../files/drivers/mtd/nand/rb4xx_nand.c | 396 ++ + .../files/drivers/mtd/nand/rb750_nand.c | 440 ++ + .../files/drivers/mtd/nand/rb91x_nand.c | 464 ++ + .../ar71xx/files/drivers/mtd/tplinkpart.c | 235 + + .../ar71xx/files/drivers/net/dsa/mv88e6063.c | 307 + + .../net/ethernet/atheros/ag71xx/Kconfig | 33 + + .../net/ethernet/atheros/ag71xx/Makefile | 15 + + .../net/ethernet/atheros/ag71xx/ag71xx.h | 508 ++ + .../ethernet/atheros/ag71xx/ag71xx_ar7240.c | 1386 ++++ + .../ethernet/atheros/ag71xx/ag71xx_ar8216.c | 44 + + .../ethernet/atheros/ag71xx/ag71xx_debugfs.c | 285 + + .../ethernet/atheros/ag71xx/ag71xx_ethtool.c | 120 + + .../net/ethernet/atheros/ag71xx/ag71xx_main.c | 1494 +++++ + .../net/ethernet/atheros/ag71xx/ag71xx_mdio.c | 320 + + .../net/ethernet/atheros/ag71xx/ag71xx_phy.c | 261 + + .../ar71xx/files/drivers/spi/spi-rb4xx-cpld.c | 347 + + .../ar71xx/files/drivers/spi/spi-rb4xx.c | 430 ++ + .../ar71xx/files/drivers/spi/spi-vsc7385.c | 621 ++ + .../ar71xx/files/include/linux/leds-nu801.h | 38 + + .../ar71xx/files/include/linux/nxp_74hc153.h | 24 + + .../files/include/linux/platform/ar934x_nfc.h | 39 + + .../include/linux/platform_data/gpio-latch.h | 14 + + .../include/linux/platform_data/rb91x_nand.h | 16 + + .../ar71xx/files/include/linux/spi/vsc7385.h | 19 + + target/linux/ar71xx/generic/config-default | 227 + + .../ar71xx/generic/profiles/00-default.mk | 18 + + target/linux/ar71xx/generic/target.mk | 10 + + target/linux/ar71xx/image/Makefile | 69 + + target/linux/ar71xx/image/common-tp-link.mk | 108 + + .../ar71xx/image/generic-legacy-devices.mk | 423 ++ + target/linux/ar71xx/image/generic-tp-link.mk | 544 ++ + target/linux/ar71xx/image/generic-ubnt.mk | 319 + + target/linux/ar71xx/image/generic.mk | 1352 ++++ + target/linux/ar71xx/image/legacy.mk | 1059 +++ + .../linux/ar71xx/image/lzma-loader/Makefile | 70 + + .../ar71xx/image/lzma-loader/src/LzmaDecode.c | 584 ++ + .../ar71xx/image/lzma-loader/src/LzmaDecode.h | 113 + + .../ar71xx/image/lzma-loader/src/LzmaTypes.h | 45 + + .../ar71xx/image/lzma-loader/src/Makefile | 108 + + .../image/lzma-loader/src/ar71xx_regs.h | 725 +++ + .../ar71xx/image/lzma-loader/src/board.c | 56 + + .../ar71xx/image/lzma-loader/src/cache.c | 43 + + .../ar71xx/image/lzma-loader/src/cache.h | 17 + + .../ar71xx/image/lzma-loader/src/cacheops.h | 85 + + .../ar71xx/image/lzma-loader/src/config.h | 31 + + .../ar71xx/image/lzma-loader/src/cp0regdef.h | 39 + + .../linux/ar71xx/image/lzma-loader/src/head.S | 134 + + .../ar71xx/image/lzma-loader/src/loader.c | 264 + + .../ar71xx/image/lzma-loader/src/loader.lds | 34 + + .../ar71xx/image/lzma-loader/src/loader2.lds | 10 + + .../image/lzma-loader/src/lzma-data.lds | 8 + + .../ar71xx/image/lzma-loader/src/printf.c | 350 + + .../ar71xx/image/lzma-loader/src/printf.h | 18 + + target/linux/ar71xx/image/mikrotik.mk | 61 + + target/linux/ar71xx/image/nand.mk | 137 + + .../linux/ar71xx/image/tiny-legacy-devices.mk | 161 + + target/linux/ar71xx/image/tiny-senao.mk | 28 + + target/linux/ar71xx/image/tiny-tp-link.mk | 695 ++ + target/linux/ar71xx/image/tiny.mk | 31 + + target/linux/ar71xx/image/ubinize-nbg6716.ini | 24 + + .../linux/ar71xx/image/ubinize-wndr4300.ini | 26 + + target/linux/ar71xx/mikrotik/config-default | 79 + + .../ar71xx/mikrotik/profiles/00-default.mk | 18 + + target/linux/ar71xx/mikrotik/target.mk | 11 + + target/linux/ar71xx/modules.mk | 69 + + target/linux/ar71xx/nand/config-default | 70 + + .../linux/ar71xx/nand/profiles/00-default.mk | 18 + + target/linux/ar71xx/nand/target.mk | 9 + + .../ar71xx/patches-4.14/001-spi-cs-gpio.patch | 20 + + .../002-add_back_gpio_function_select.patch | 92 + + .../004-register_gpio_driver_earlier.patch | 18 + + ...Avoid-using-unitialized-reg-variable.patch | 42 + + ...h79-do-AR724x-PCIe-root-complex-init.patch | 113 + + ...200-MIPS-ath79-fix-ar933x-wmac-reset.patch | 30 + + .../201-ar913x_wmac_external_reset.patch | 31 + + .../202-MIPS-ath79-ar934x-wmac-revision.patch | 11 + + .../220-add_cpu_feature_overrides.patch | 28 + + ...0-MIPS-add-MIPS_MACHINE_NONAME-macro.patch | 21 + + .../310-lib-add-rle-decompression.patch | 124 + + ...otentially-missed-IRQ-handling-durin.patch | 52 + + .../401-mtd-physmap-add-lock-unlock.patch | 94 + + .../402-mtd-SST39VF6401B-support.patch | 29 + + .../404-mtd-cybertan-trx-parser.patch | 25 + + .../405-mtd-tp-link-partition-parser.patch | 25 + + ...o-pass-probe-types-via-platform-data.patch | 34 + + .../408-mtd-redboot_partition_scan.patch | 44 + + .../409-mtd-rb4xx_nand_driver.patch | 21 + + .../410-mtd-rb750-nand-driver.patch | 21 + + ...mtd-cfi_cmdset_0002-force-word-write.patch | 61 + + .../413-mtd-ar934x-nand-driver.patch | 25 + + .../414-mtd-rb91x-nand-driver.patch | 23 + + .../420-net-ar71xx_mac_driver.patch | 28 + + .../423-dsa-add-88e6063-driver.patch | 27 + + .../430-drivers-link-spi-before-mtd.patch | 12 + + .../432-spi-rb4xx-spi-driver.patch | 25 + + .../433-spi-rb4xx-cpld-driver.patch | 26 + + .../patches-4.14/435-spi-vsc7385_driver.patch | 24 + + .../440-leds-wndr3700-usb-led-driver.patch | 26 + + .../441-leds-rb750-led-driver.patch | 23 + + ...to-use-OPEN_-DRAIN-SOURCE-flags-with.patch | 45 + + ...50-gpio-nxp-74hc153-gpio-chip-driver.patch | 25 + + ...x164-improve-platform-device-support.patch | 119 + + .../452-gpio-add-gpio-latch-driver.patch | 22 + + .../461-spi-ath79-add-fast-flash-read.patch | 60 + + ...ath79-swizzle-pci-address-for-ar71xx.patch | 111 + + ...490-usb-ehci-add-quirks-for-qca-socs.patch | 103 + + .../patches-4.14/500-MIPS-fw-myloader.patch | 22 + + ...-mac-argument-to-ath79_register_wmac.patch | 70 + + ...IPS-ath79-add-ath79_device_reset_get.patch | 42 + + ...ath79-add-ath79_gpio_function_select.patch | 39 + + ...6-MIPS-ath79-prom-parse-redboot-args.patch | 42 + + ...MIPS-ath79-prom-add-myloader-support.patch | 55 + + ...S-ath79-prom-image-command-line-hack.patch | 73 + + ...PS-ath79-process-board-kernel-option.patch | 11 + + ...S-ath79-init-gpio-pin-of-wmac-device.patch | 14 + + .../520-MIPS-ath79-enable-UART-function.patch | 18 + + ...S-ath79-enable-UART-for-early_serial.patch | 61 + + ...dd-ath79_wmac_register_simple-helper.patch | 21 + + .../523-MIPS-ath79-OTP-support.patch | 192 + + ...add-ath79_wmac_disable_25ghz-helpers.patch | 31 + + ...525-MIPS-ath79-enable-qca-usb-quirks.patch | 101 + + ...MIPS-ath79-add-more-register-defines.patch | 455 ++ + .../602-MIPS-ath79-add-openwrt-stuff.patch | 49 + + .../603-MIPS-ath79-ap121-fixes.patch | 149 + + .../patches-4.14/604-MIPS-ath79-no-of.patch | 70 + + .../605-MIPS-ath79-db120-fixes.patch | 204 + + .../606-MIPS-ath79-pb44-fixes.patch | 144 + + .../607-MIPS-ath79-ubnt-xm-fixes.patch | 14 + + ...8-MIPS-ath79-ubnt-xm-add-more-boards.patch | 20 + + .../609-MIPS-ath79-ap136-fixes.patch | 300 + + .../611-MIPS-ath79-wdt-timeout.patch | 25 + + .../612-MIPS-ath79-set-buffalo-txgain.patch | 24 + + ...ath79_wmac_setup_ext_lna_gpio-helper.patch | 76 + + ...PS-ath79-add-support-for-QCA953x-SoC.patch | 696 ++ + ...PS-ath79-add-support-for-QCA956x-SoC.patch | 717 ++ + ...ore-register-defines-for-QCA956x-SoC.patch | 38 + + ...0-MIPS-ath79-fix-chained-irq-disable.patch | 106 + + ...1-MIPS-ath79-wmac-enable-set-led-pin.patch | 24 + + ...MIPS-ath79-gpio-enable-set-direction.patch | 32 + + ...40-MIPS-ath79-add-QCA955x-wmac-reset.patch | 82 + + .../700-MIPS-ath79-add-openwrt-Kconfig.patch | 11 + + ...MIPS-ath79-add-routerboard-detection.patch | 35 + + ...h79-fixup-routerboot-board-parameter.patch | 43 + + ...d-gpio-func-register-for-QCA955x-SoC.patch | 38 + + ...0-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch | 44 + + ...1-MIPS-ath79-add-PCI-for-QCA9556-SoC.patch | 12 + + .../818-MIPS-ath79-add-nu801-led-driver.patch | 26 + + ...-MIPS-ath79-add_gpio_function2_setup.patch | 67 + + ...support-for-boot-console-with-arbitr.patch | 54 + + .../900-mdio_bitbang_ignore_ta_value.patch | 32 + + ...-prevent-rescheduling-during-command.patch | 61 + + .../902-at803x-add-reset-gpio-pdata.patch | 68 + + ...at803x-add-sgmii-aneg-override-pdata.patch | 38 + + .../910-unaligned_access_hacks.patch | 942 +++ + ...usb-chipidea-AR933x-platform-support.patch | 124 + + ...ore-register-defines-for-QCA956x-SoC.patch | 194 + + .../patches-4.14/930-chipidea-pullup.patch | 72 + + .../940-qca955x-add-more-registers.patch | 42 + + .../950-add-boardinfo-platform-data.patch | 67 + + .../952-qca955x-enable-ddr-wb-flush.patch | 49 + + .../953-qca955x-pci-reset-fixes.patch | 120 + + ...x-fix-potential-missing-irq-dispatch.patch | 27 + + .../patches-4.14/999-backport-fixes.patch | 191 + + target/linux/ar71xx/tiny/config-default | 76 + + .../linux/ar71xx/tiny/profiles/00-default.mk | 11 + + target/linux/ar71xx/tiny/target.mk | 10 + + ...dcode-path-to-awk-in-scripts-ld-vers.patch | 30 + + .../011-kbuild-export-SUBARCH.patch | 23 + + ...-for-controlling-warnings-to-linux-c.patch | 142 + + ...te-alias-warning-for-SYSCALL_DEFINEx.patch | 88 + + .../020-backport_netfilter_rtcache.patch | 558 ++ + ...tcp-allow-drivers-to-tweak-TSQ-logic.patch | 85 + + ...ption-fix-dwm-158-3g-modem-interface.patch | 42 + + ...port-for-host-mode-external-vbus-sup.patch | 109 + + ...wc2_vbus_supply_init-fix-error-check.patch | 55 + + ...ding-master-MTD-out-of-mtd_add_devic.patch | 74 + + ...rid-of-the-mtd_add_device_partitions.patch | 93 + + ...dd-of_match_table-parser-matching-fo.patch | 200 + + ...t-parser-to-fixed-partitions-as-it-f.patch | 74 + + ...of_match_table-with-fixed-partitions.patch | 44 + + ...ding-registering-partitions-to-the-p.patch | 168 + + ...-improve-handling-TRX-partition-size.patch | 70 + + ...add-of_match_table-with-a-new-DT-bin.patch | 39 + + ...add-of_match_table-with-the-new-DT-b.patch | 37 + + ...se-DT-info-for-parsing-partitions-wi.patch | 102 + + ...inal-flags-for-every-struct-mtd_info.patch | 58 + + ...ulating-partition-boundaries-when-ch.patch | 55 + + ...ying-block-address-non-regular-inode.patch | 69 + + ...-master-mode-for-BCM54210E-and-B5021.patch | 50 + + ...-support-new-device-flag-for-setting.patch | 54 + + ...-direct-pointer-to-the-struct-device.patch | 199 + + ...002-bcma-use-dev_-printing-functions.patch | 36 + + ...le-working-over-slow-can_sleep-GPIOs.patch | 84 + + ...ridge-add-support-for-port-isolation.patch | 145 + + ...ddress-assignment-via-ifconfig-ioctl.patch | 79 + + ...s3xxx-use-actual-size-reads-for-PCIe.patch | 46 + + ...net-qmi_wwan-add-Wistron-Neweb-D19Q1.patch | 54 + + ...acket.h-include-its-headers-directly.patch | 36 + + ...dv-Remove-usage-of-BIT-x-in-packet.h.patch | 72 + + ...e-kernel-fixed-width-types-in-packet.patch | 386 ++ + ...-adv-Convert-packet.h-to-uapi-header.patch | 1665 +++++ + ...tor-Parse-batman-adv-unicast-headers.patch | 108 + + ...add-defines-for-arp-decnet-max-hooks.patch | 67 + + ...ake-nf_unregister_net_hooks-simple-w.patch | 91 + + ...emove-synchronize_net-call-if-nfqueu.patch | 116 + + ...filter-core-free-hooks-with-call_rcu.patch | 132 + + ...e-size-of-hook-entry-point-locations.patch | 200 + + ...e-hook-array-sizes-to-what-is-needed.patch | 95 + + ...allocate-space-for-decnet-hooks-unle.patch | 67 + + ...allocate-space-for-arp-bridge-hooks-.patch | 165 + + ...ass-hook-number-family-and-device-to.patch | 98 + + ...etfilter-core-add-nf_remove_net_hook.patch | 44 + + ...ass-family-as-parameter-to-nf_remove.patch | 51 + + ...upport-for-NFPROTO_INET-hook-registr.patch | 129 + + ...les-explicit-nft_set_pktinfo-call-fr.patch | 291 + + ...nly-allow-one-nat-hook-per-hook-poin.patch | 146 + + ...les_inet-don-t-use-multihook-infrast.patch | 161 + + ...les-remove-multihook-chains-and-fami.patch | 390 ++ + ...hecksum-indirection-to-struct-nf_ipv.patch | 171 + + ...hecksum_partial-indirection-to-struc.patch | 204 + + ...-saveroute-indirection-in-struct-nf_.patch | 232 + + ...oute-indirection-to-struct-nf_ipv6_o.patch | 349 + + ...eroute-indirection-to-struct-nf_ipv6.patch | 223 + + ...-route_key_size-field-in-struct-nf_a.patch | 94 + + ...-struct-nf_afinfo-and-its-helper-fun.patch | 173 + + ...f_tables_arp-don-t-set-forward-chain.patch | 20 + + ...les-remove-hooks-from-family-definit.patch | 233 + + ...-defensive-check-on-malformed-packet.patch | 302 + + ...v4.16-netfilter-meta-secpath-support.patch | 101 + + ...ack-move-nf_ct_netns_-get-put-to-cor.patch | 142 + + ...conntrack-add-IPS_OFFLOAD-status-bit.patch | 169 + + ...bles-add-flow-table-netlink-frontend.patch | 1079 +++ + ...dd-generic-flow-table-infrastructure.patch | 586 ++ + ...etfilter-flow-table-support-for-IPv4.patch | 334 + + ...etfilter-flow-table-support-for-IPv6.patch | 354 + + ...able-support-for-the-mixed-IPv4-IPv6.patch | 141 + + ...er-nf_tables-flow-offload-expression.patch | 332 + + ...les-remove-nhooks-field-from-struct-.patch | 113 + + ...les-fix-a-typo-in-nf_tables_getflowt.patch | 22 + + ...rove-flow-table-Kconfig-dependencies.patch | 106 + + ...les-remove-flag-field-from-struct-nf.patch | 59 + + ...les-no-need-for-struct-nft_af_info-t.patch | 80 + + ...les-remove-struct-nft_af_info-parame.patch | 60 + + ...les-fix-potential-NULL-ptr-deref-in-.patch | 30 + + ...les-add-single-table-list-for-all-fa.patch | 1450 +++++ + ...tfilter-exit_net-cleanup-check-added.patch | 100 + + ...nf_tables-get-rid-of-pernet-families.patch | 598 ++ + ...les-get-rid-of-struct-nft_af_info-ab.patch | 1204 ++++ + ...ow_offload-wait-for-garbage-collecto.patch | 47 + + ...ow_offload-no-need-to-flush-entries-.patch | 29 + + ...ow_offload-move-flowtable-cleanup-ro.patch | 97 + + ...tfilter-nf_tables-fix-flowtable-free.patch | 140 + + ...ow_offload-handle-netdevice-events-f.patch | 96 + + ...les-allocate-handle-and-delete-objec.patch | 468 ++ + ...w_offload-fix-use-after-free-and-a-r.patch | 95 + + ...ble-infrastructure-depends-on-NETFIL.patch | 73 + + ...-netfilter-remove-duplicated-include.patch | 29 + + ...w_table-use-IP_CT_DIR_-values-for-FL.patch | 35 + + ...ow_table-clean-up-flow_offload_alloc.patch | 118 + + ...ipv6-make-ip6_dst_mtu_forward-inline.patch | 80 + + ...w_table-cache-mtu-in-struct-flow_off.patch | 145 + + ...w_table-rename-nf_flow_table.c-to-nf.patch | 952 +++ + ...w_table-move-ipv4-offload-hook-code-.patch | 522 ++ + ...w_table-move-ip-header-check-out-of-.patch | 32 + + ...w_table-move-ipv6-offload-hook-code-.patch | 483 ++ + ...w_table-relax-mixed-ipv4-ipv6-flowta.patch | 23 + + ...w_table-move-init-code-to-nf_flow_ta.patch | 298 + + ...w_table-fix-priv-pointer-for-netdev-.patch | 22 + + ...w_table-track-flow-tables-in-nf_flow.patch | 114 + + ...w_table-make-flow_offload_dead-inlin.patch | 38 + + ...w_table-add-a-new-flow-state-for-tea.patch | 83 + + ...w_table-in-flow_offload_lookup-skip-.patch | 36 + + ...w_table-add-support-for-sending-flow.patch | 99 + + ...w_table-tear-down-TCP-flows-if-RST-o.patch | 81 + + ...w_table-fix-checksum-when-handling-D.patch | 19 + + ...low_offload-Fix-reverse-route-lookup.patch | 39 + + ...w_table-add-missing-condition-for-TC.patch | 48 + + ...w_table-fix-offloading-connections-w.patch | 23 + + ...ter-nf_flow_table-attach-dst-to-skbs.patch | 49 + + ...w_table-fix-offloaded-connection-tim.patch | 110 + + ...w_table-fix-up-ct-state-of-flows-aft.patch | 24 + + ...ow_offload-fix-interaction-with-vrf-.patch | 86 + + ...et-sched-Introduce-act_ctinfo-action.patch | 640 ++ + ...s-trigger-Introduce-a-NETDEV-trigger.patch | 588 ++ + ...dev-fix-refcnt-leak-on-interface-ren.patch | 69 + + ...dev-fix-handling-on-interface-rename.patch | 49 + + ...ix-calculating-partition-end-address.patch | 28 + + ...enable-CONFIG_MMC_SDHCI_IO_ACCESSORS.patch | 23 + + ...fault-compression-selection-in-ubifs.patch | 37 + + ...-dmi-Add-access-to-the-SKU-ID-string.patch | 57 + + ...y-serial-exar-generalize-rs485-setup.patch | 75 + + target/linux/generic/config-4.14 | 5793 +++++++++++++++++ + .../generic/hack-4.14/204-module_strip.patch | 208 + + .../hack-4.14/207-disable-modorder.patch | 44 + + .../210-darwin_scripts_include.patch | 3065 +++++++++ + .../211-host_tools_portability.patch | 40 + + .../hack-4.14/212-byteshift_portability.patch | 65 + + .../hack-4.14/214-spidev_h_portability.patch | 24 + + .../generic/hack-4.14/220-gc_sections.patch | 258 + + .../hack-4.14/221-module_exports.patch | 101 + + .../hack-4.14/230-openwrt_lzma_options.patch | 71 + + .../hack-4.14/250-netfilter_depends.patch | 27 + + .../generic/hack-4.14/251-sound_kconfig.patch | 197 + + .../hack-4.14/259-regmap_dynamic.patch | 105 + + .../260-crypto_test_dependencies.patch | 60 + + .../generic/hack-4.14/280-rfkill-stubs.patch | 84 + + ...cache-use-more-efficient-cache-blast.patch | 66 + + .../301-mips_image_cmdline_hack.patch | 38 + + .../321-powerpc_crtsavres_prereq.patch | 38 + + .../400-mt29f_spinand-fix-memleak.patch | 90 + + .../generic/hack-4.14/531-debloat_lzma.patch | 1040 +++ + .../640-bridge-only-accept-EAP-locally.patch | 82 + + ...lter-connmark-introduce-set-dscpmark.patch | 124 + + .../hack-4.14/647-netfilter-flow-acct.patch | 70 + + .../650-netfilter-add-xt_OFFLOAD-target.patch | 553 ++ + .../hack-4.14/651-wireless_mesh_header.patch | 24 + + .../hack-4.14/660-fq_codel_defaults.patch | 27 + + .../661-use_fq_codel_by_default.patch | 94 + + .../hack-4.14/662-remove_pfifo_fast.patch | 159 + + .../700-swconfig_switch_drivers.patch | 140 + + .../702-phy_add_aneg_done_function.patch | 27 + + .../generic/hack-4.14/721-phy_packets.patch | 176 + + .../hack-4.14/773-bgmac-add-srab-switch.patch | 98 + + .../hack-4.14/901-debloat_sock_diag.patch | 136 + + .../generic/hack-4.14/902-debloat_proc.patch | 405 ++ + .../hack-4.14/904-debloat_dma_buf.patch | 64 + + .../hack-4.14/910-kobject_uevent.patch | 32 + + .../911-kobject_add_broadcast_uevent.patch | 76 + + ...ays-create-console-node-in-initramfs.patch | 40 + + .../generic/hack-4.14/930-crashlog.patch | 338 + + ...problem-with-platfom-data-in-w1-gpio.patch | 38 + + ...s-negative-stack-offsets-on-stack-tr.patch | 57 + + ...f-ath79-Fix-perfcount-IRQ-assignment.patch | 110 + + .../pending-4.14/110-ehci_hcd_ignore_oc.patch | 79 + + ...e_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 82 + + ...0-add-linux-spidev-compatible-si3210.patch | 18 + + ..._value_cansleep-for-setting-chipsele.patch | 20 + + ...ame2-and-add-RENAME_WHITEOUT-support.patch | 62 + + ...41-jffs2-add-RENAME_EXCHANGE-support.patch | 73 + + ...ge_allow_receiption_on_disabled_port.patch | 47 + + ...-generic-parsing-of-linux-part-probe.patch | 172 + + ...nefficient-copy-of-unaligned-buffers.patch | 50 + + ...et-phy-at803x-add-support-for-AT8032.patch | 73 + + ...ng-comment-related-to-link-detection.patch | 43 + + .../pending-4.14/201-extra_optimization.patch | 28 + + .../203-kallsyms_uncompressed.patch | 119 + + .../205-backtrace_module_info.patch | 45 + + .../pending-4.14/220-optimize_inlining.patch | 165 + + ...e-filenames-from-deps_initramfs-list.patch | 46 + + ...able_wilink_platform_without_drivers.patch | 20 + + .../270-platform-mikrotik-build-bits.patch | 31 + + .../300-mips_expose_boot_raw.patch | 40 + + .../302-mips_no_branch_likely.patch | 22 + + .../pending-4.14/304-mips_disable_fpu.patch | 137 + + .../pending-4.14/305-mips_module_reloc.patch | 371 ++ + .../306-mips_mem_functions_performance.patch | 106 + + .../307-mips_highmem_offset.patch | 19 + + .../pending-4.14/308-mips32r2_tune.patch | 22 + + ...CPU-option-reporting-to-proc-cpuinfo.patch | 140 + + .../310-arm_module_unresolved_weak_sym.patch | 22 + + ...t-command-line-parameters-from-users.patch | 274 + + .../332-arc-add-OWRTDTB-section.patch | 84 + + ...able-unaligned-access-in-kernel-mode.patch | 24 + + ...IPS-mm-remove-mips_dma_mapping_error.patch | 32 + + ...ove-no-op-dma_map_ops-where-possible.patch | 140 + + ...ernel-XZ-compression-option-on-PPC_8.patch | 24 + + .../400-mtd-add-rootfs-split-support.patch | 108 + + ...for-different-partition-parser-types.patch | 142 + + ...arsers-for-rootfs-and-firmware-split.patch | 44 + + .../403-mtd-hook-mtdsplit-to-Kbuild.patch | 32 + + .../404-mtd-add-more-helper-functions.patch | 76 + + .../411-mtd-partial_eraseblock_write.patch | 153 + + .../412-mtd-partial_eraseblock_unlock.patch | 40 + + ...t-add-of_match_table-with-DT-binding.patch | 31 + + .../pending-4.14/420-mtd-redboot_space.patch | 41 + + ...30-mtd-add-myloader-partition-parser.patch | 229 + + ...check-for-bad-blocks-when-calculatin.patch | 68 + + ...bcm47xxpart-detect-T_Meter-partition.patch | 37 + + ...mtd-add-routerbootpart-parser-config.patch | 36 + + .../pending-4.14/440-block2mtd_init.patch | 116 + + .../pending-4.14/441-block2mtd_probe.patch | 47 + + ...-fallback-from-spi_flash_read-to-reg.patch | 36 + + ...w-NOR-driver-to-write-fewer-bytes-th.patch | 36 + + ...mtd-cfi_cmdset_0002-no-erase_suspend.patch | 25 + + ...et_0002-add-buffer-write-cmd-timeout.patch | 17 + + ...25p80-mx-disable-software-protection.patch | 18 + + ...or-fix-Spansion-regressions-aliased-.patch | 37 + + ...ort-limiting-4K-sectors-support-base.patch | 56 + + ...pi-nor-Add-Winbond-w25q128jv-support.patch | 34 + + .../476-mtd-spi-nor-add-eon-en25q128.patch | 18 + + .../477-mtd-add-spi-nor-add-mx25u3235f.patch | 18 + + ...support-for-XM25QH64A-and-XM25QH128A.patch | 30 + + .../479-mtd-spi-nor-add-eon-en25qh32.patch | 10 + + .../479-mtd-spi-nor-add-eon-en25qh64.patch | 10 + + .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 42 + + .../480-mtd-set-rootfs-to-be-root-dev.patch | 38 + + ...r-add-support-for-Gigadevice-GD25D05.patch | 24 + + ...mtd-device-named-ubi-or-data-on-boot.patch | 97 + + ...to-create-ubiblock-device-for-rootfs.patch | 66 + + ...ting-ubi0-rootfs-in-init-do_mounts.c.patch | 51 + + ...ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 34 + + .../494-mtd-ubi-add-EOF-marker-support.patch | 60 + + ...-mtd-core-add-get_mtd_device_by_node.patch | 75 + + ...-add-bindings-for-mtd-concat-devices.patch | 52 + + ...cat-add-dt-driver-for-concat-devices.patch | 216 + + .../530-jffs2_make_lzma_available.patch | 5180 +++++++++++++++ + .../pending-4.14/532-jffs2_eofdetect.patch | 65 + + .../600-netfilter_conntrack_flush.patch | 95 + + ...etfilter_match_bypass_default_checks.patch | 110 + + ...netfilter_match_bypass_default_table.patch | 111 + + ...netfilter_match_reduce_memory_access.patch | 22 + + ...-netfilter_optional_tcp_window_check.patch | 44 + + ...del-do-not-defer-queue-length-update.patch | 86 + + .../pending-4.14/630-packet_socket_type.patch | 138 + + ...w_table-add-hardware-offload-support.patch | 565 ++ + ...w_table-support-hw-offload-through-v.patch | 306 + + ...-support-hardware-flow-table-offload.patch | 60 + + ...-support-hardware-flow-table-offload.patch | 61 + + ...-support-hardware-flow-table-offload.patch | 125 + + ...w_table-rework-hardware-offload-time.patch | 37 + + ...low_table-rework-private-driver-data.patch | 25 + + .../pending-4.14/655-increase_skb_pad.patch | 20 + + ...Add-support-for-MAP-E-FMRs-mesh-mode.patch | 500 ++ + ...ng-with-source-address-failed-policy.patch | 255 + + ...nes-for-_POLICY_FAILED-until-all-cod.patch | 50 + + ...T-skip-GRO-for-foreign-MAC-addresses.patch | 152 + + .../681-NET-add-of_get_mac_address_mtd.patch | 133 + + ...dd-support-for-threaded-NAPI-polling.patch | 339 + + ...detach-callback-to-struct-phy_driver.patch | 38 + + ...-at803x-allow-to-configure-via-pdata.patch | 142 + + ...net-phy-at803x-fix-at8033-sgmii-mode.patch | 51 + + .../810-pci_disable_common_quirks.patch | 60 + + .../811-pci_disable_usb_common_quirks.patch | 115 + + .../pending-4.14/834-ledtrig-libata.patch | 149 + + .../pending-4.14/920-mangle_bootargs.patch | 71 + + tools/Makefile | 2 +- + 722 files changed, 131914 insertions(+), 6 deletions(-) + create mode 100644 target/linux/ar71xx/Makefile + create mode 100755 target/linux/ar71xx/base-files/etc/board.d/01_leds + create mode 100755 target/linux/ar71xx/base-files/etc/board.d/02_network + create mode 100755 target/linux/ar71xx/base-files/etc/board.d/03_gpio_switches + create mode 100644 target/linux/ar71xx/base-files/etc/diag.sh + create mode 100644 target/linux/ar71xx/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom + create mode 100644 target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata + create mode 100644 target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac + create mode 100644 target/linux/ar71xx/base-files/etc/hotplug.d/net/10-ar922x-led-fix + create mode 100644 target/linux/ar71xx/base-files/etc/inittab + create mode 100644 target/linux/ar71xx/base-files/etc/uci-defaults/03_network-switchX-migration + create mode 100644 target/linux/ar71xx/base-files/etc/uci-defaults/03_network-vlan-migration + create mode 100644 target/linux/ar71xx/base-files/etc/uci-defaults/04_led_migration + create mode 100644 target/linux/ar71xx/base-files/etc/uci-defaults/09_fix-checksum + create mode 100644 target/linux/ar71xx/base-files/etc/uci-defaults/09_fix-seama-header + create mode 100755 target/linux/ar71xx/base-files/lib/ar71xx.sh + create mode 100644 target/linux/ar71xx/base-files/lib/preinit/01_preinit_do_ar71xx.sh + create mode 100644 target/linux/ar71xx/base-files/lib/preinit/05_set_iface_mac_ar71xx + create mode 100644 target/linux/ar71xx/base-files/lib/preinit/05_set_preinit_iface_ar71xx + create mode 100644 target/linux/ar71xx/base-files/lib/preinit/82_patch_ath10k + create mode 100644 target/linux/ar71xx/base-files/lib/upgrade/allnet.sh + create mode 100644 target/linux/ar71xx/base-files/lib/upgrade/dir825.sh + create mode 100644 target/linux/ar71xx/base-files/lib/upgrade/merakinand.sh + create mode 100644 target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh + create mode 100755 target/linux/ar71xx/base-files/lib/upgrade/platform.sh + create mode 100644 target/linux/ar71xx/config-4.14 + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/Makefile + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-dsa.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-dsa.h + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.h + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.h + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-a60.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-ap120c.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-ap96.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-nx.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-all0258n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-all0315n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-antminer-s1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-antminer-s3.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-antrouter-r1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap121f.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap132.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap143.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap147.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap152.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap531b0.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap90q.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap91-5g.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ap96.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c25-v1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v5.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-arduino-yun.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-aw-nr580.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-bhr-4grv2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-bhu-bxu2000n2-a.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-bsb.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-c55.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-c60.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-cap324.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-cap4200ag.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-carambola2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-cf-e316n-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-cpe870.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-cr3000.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-cr5000.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dap-1330-a1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dap-2695-a1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dgl-5500-a1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dhp-1565-a1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dir-505-a1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dir-600-a1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-c1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-i1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-b1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-c1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dir-869-a1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-hotspot.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-pro-1200-ac.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-pro-500-wp.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-domywifi-dw33d.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dr344.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dr531.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-dragino2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-e1700ac-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-e2100l.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-e558-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-e600g-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-e750a-v4.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-e750g-v8.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-eap120.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-eap300v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-eap7660d.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-el-m150.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-el-mini.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ens202ext.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-epg5000.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-esr1750.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-esr900.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ew-balin.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ew-dorin.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-f9k1115v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-fritz300e.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-fritz4020.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-fritz450e.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar150.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300m.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750s.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-domino.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-inet.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-mifi.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gl-usb150.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gs-minibox-v32.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gs-oolite-v1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-gs-oolite-v5-2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-hiveap-121.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-hiwifi-hc6361.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-hornet-ub.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ja76pf.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-jwap003.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-jwap230.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-koala.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-lan-turtle.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-lima.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mc-mac1200r.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mr12.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mr16.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mr18.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mr600.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n600.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n750.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mzk-w04nu.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-mzk-w300nh.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-n5q.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-nbg460n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-nbg6716.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-om2p.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-om5p.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-om5pac.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-om5pacv2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-omy-g1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-omy-x1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-onion-omega.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-pb42.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-pqi-air-pen.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-qihoo-c301.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-r36a.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-r602n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-r6100.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rambutan.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rb4xx.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rb91x.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rb922.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rbsxtlite.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-re450.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rme-eg200.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rut9xx.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-rw2458n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-sc1750.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-sc300m.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-sc450.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-smart-300.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-som9331.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-sr3200.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-t830.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tellstick-znet-lite.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tew-632brp.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tew-673gru.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tew-712br.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tew-732br.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tew-823dru.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr11u.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr13u.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3020.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr6400.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa701nd-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa7210n-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa801nd-v3.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa830re-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v4.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wax50re.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3320-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3500.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr6500-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wpa8630.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1041n-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v4.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr2543n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr703n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr720n-v3.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd-v4.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr802n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr810n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v9.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr902ac-v1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr940n-v4.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr941nd-v6.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr941nd.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr942n-v1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ts-d084.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-tube2h.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-xm.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wam250.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-weio.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-whr-hp-g300n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wi2a-ac200i.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wifi-pineapple-nano.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wlae-ag300n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wlr8100.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wndap360.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wndr3700.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wndr4300.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v3.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v4.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2200.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wp543.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wpe72.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wpj342.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wpj344.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wpj531.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wpj558.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wpj563.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wrt160nl.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wrt400n.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wrtnode2q.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-450hp2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-ag300h.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh2.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g450h.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-z1.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-zbt-we1526.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/mach-zcn-1523h.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/machtypes.h + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/nvram.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/nvram.h + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.h + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/routerboot.c + create mode 100644 target/linux/ar71xx/files/arch/mips/ath79/routerboot.h + create mode 100644 target/linux/ar71xx/files/arch/mips/include/asm/fw/myloader/myloader.h + create mode 100644 target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h + create mode 100644 target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/mach-rb750.h + create mode 100644 target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/rb4xx_cpld.h + create mode 100644 target/linux/ar71xx/files/drivers/gpio/gpio-latch.c + create mode 100644 target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c + create mode 100644 target/linux/ar71xx/files/drivers/leds/leds-nu801.c + create mode 100644 target/linux/ar71xx/files/drivers/leds/leds-rb750.c + create mode 100644 target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c + create mode 100644 target/linux/ar71xx/files/drivers/mtd/cybertan_part.c + create mode 100644 target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c + create mode 100644 target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c + create mode 100644 target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c + create mode 100644 target/linux/ar71xx/files/drivers/mtd/nand/rb91x_nand.c + create mode 100644 target/linux/ar71xx/files/drivers/mtd/tplinkpart.c + create mode 100644 target/linux/ar71xx/files/drivers/net/dsa/mv88e6063.c + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/Kconfig + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/Makefile + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar8216.c + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c + create mode 100644 target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c + create mode 100644 target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c + create mode 100644 target/linux/ar71xx/files/drivers/spi/spi-rb4xx.c + create mode 100644 target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c + create mode 100644 target/linux/ar71xx/files/include/linux/leds-nu801.h + create mode 100644 target/linux/ar71xx/files/include/linux/nxp_74hc153.h + create mode 100644 target/linux/ar71xx/files/include/linux/platform/ar934x_nfc.h + create mode 100644 target/linux/ar71xx/files/include/linux/platform_data/gpio-latch.h + create mode 100644 target/linux/ar71xx/files/include/linux/platform_data/rb91x_nand.h + create mode 100644 target/linux/ar71xx/files/include/linux/spi/vsc7385.h + create mode 100644 target/linux/ar71xx/generic/config-default + create mode 100644 target/linux/ar71xx/generic/profiles/00-default.mk + create mode 100644 target/linux/ar71xx/generic/target.mk + create mode 100644 target/linux/ar71xx/image/Makefile + create mode 100644 target/linux/ar71xx/image/common-tp-link.mk + create mode 100644 target/linux/ar71xx/image/generic-legacy-devices.mk + create mode 100644 target/linux/ar71xx/image/generic-tp-link.mk + create mode 100644 target/linux/ar71xx/image/generic-ubnt.mk + create mode 100644 target/linux/ar71xx/image/generic.mk + create mode 100644 target/linux/ar71xx/image/legacy.mk + create mode 100644 target/linux/ar71xx/image/lzma-loader/Makefile + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/LzmaDecode.c + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/LzmaDecode.h + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/LzmaTypes.h + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/Makefile + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/ar71xx_regs.h + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/board.c + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/cache.c + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/cache.h + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/cacheops.h + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/config.h + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/cp0regdef.h + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/head.S + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/loader.c + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/loader.lds + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/loader2.lds + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/lzma-data.lds + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/printf.c + create mode 100644 target/linux/ar71xx/image/lzma-loader/src/printf.h + create mode 100644 target/linux/ar71xx/image/mikrotik.mk + create mode 100644 target/linux/ar71xx/image/nand.mk + create mode 100644 target/linux/ar71xx/image/tiny-legacy-devices.mk + create mode 100644 target/linux/ar71xx/image/tiny-senao.mk + create mode 100644 target/linux/ar71xx/image/tiny-tp-link.mk + create mode 100644 target/linux/ar71xx/image/tiny.mk + create mode 100644 target/linux/ar71xx/image/ubinize-nbg6716.ini + create mode 100644 target/linux/ar71xx/image/ubinize-wndr4300.ini + create mode 100644 target/linux/ar71xx/mikrotik/config-default + create mode 100644 target/linux/ar71xx/mikrotik/profiles/00-default.mk + create mode 100644 target/linux/ar71xx/mikrotik/target.mk + create mode 100644 target/linux/ar71xx/modules.mk + create mode 100644 target/linux/ar71xx/nand/config-default + create mode 100644 target/linux/ar71xx/nand/profiles/00-default.mk + create mode 100644 target/linux/ar71xx/nand/target.mk + create mode 100644 target/linux/ar71xx/patches-4.14/001-spi-cs-gpio.patch + create mode 100644 target/linux/ar71xx/patches-4.14/002-add_back_gpio_function_select.patch + create mode 100644 target/linux/ar71xx/patches-4.14/004-register_gpio_driver_earlier.patch + create mode 100644 target/linux/ar71xx/patches-4.14/100-MIPS-ath79-Avoid-using-unitialized-reg-variable.patch + create mode 100644 target/linux/ar71xx/patches-4.14/106-02-MIPS-ath79-do-AR724x-PCIe-root-complex-init.patch + create mode 100644 target/linux/ar71xx/patches-4.14/200-MIPS-ath79-fix-ar933x-wmac-reset.patch + create mode 100644 target/linux/ar71xx/patches-4.14/201-ar913x_wmac_external_reset.patch + create mode 100644 target/linux/ar71xx/patches-4.14/202-MIPS-ath79-ar934x-wmac-revision.patch + create mode 100644 target/linux/ar71xx/patches-4.14/220-add_cpu_feature_overrides.patch + create mode 100644 target/linux/ar71xx/patches-4.14/300-MIPS-add-MIPS_MACHINE_NONAME-macro.patch + create mode 100644 target/linux/ar71xx/patches-4.14/310-lib-add-rle-decompression.patch + create mode 100644 target/linux/ar71xx/patches-4.14/343-MIPS-ath79-Fix-potentially-missed-IRQ-handling-durin.patch + create mode 100644 target/linux/ar71xx/patches-4.14/401-mtd-physmap-add-lock-unlock.patch + create mode 100644 target/linux/ar71xx/patches-4.14/402-mtd-SST39VF6401B-support.patch + create mode 100644 target/linux/ar71xx/patches-4.14/404-mtd-cybertan-trx-parser.patch + create mode 100644 target/linux/ar71xx/patches-4.14/405-mtd-tp-link-partition-parser.patch + create mode 100644 target/linux/ar71xx/patches-4.14/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch + create mode 100644 target/linux/ar71xx/patches-4.14/408-mtd-redboot_partition_scan.patch + create mode 100644 target/linux/ar71xx/patches-4.14/409-mtd-rb4xx_nand_driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/410-mtd-rb750-nand-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/411-mtd-cfi_cmdset_0002-force-word-write.patch + create mode 100644 target/linux/ar71xx/patches-4.14/413-mtd-ar934x-nand-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/414-mtd-rb91x-nand-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/420-net-ar71xx_mac_driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/423-dsa-add-88e6063-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/430-drivers-link-spi-before-mtd.patch + create mode 100644 target/linux/ar71xx/patches-4.14/432-spi-rb4xx-spi-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/433-spi-rb4xx-cpld-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/435-spi-vsc7385_driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/440-leds-wndr3700-usb-led-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/441-leds-rb750-led-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/442-leds-gpio-allow-to-use-OPEN_-DRAIN-SOURCE-flags-with.patch + create mode 100644 target/linux/ar71xx/patches-4.14/450-gpio-nxp-74hc153-gpio-chip-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/451-gpio-74x164-improve-platform-device-support.patch + create mode 100644 target/linux/ar71xx/patches-4.14/452-gpio-add-gpio-latch-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/461-spi-ath79-add-fast-flash-read.patch + create mode 100644 target/linux/ar71xx/patches-4.14/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch + create mode 100644 target/linux/ar71xx/patches-4.14/490-usb-ehci-add-quirks-for-qca-socs.patch + create mode 100644 target/linux/ar71xx/patches-4.14/500-MIPS-fw-myloader.patch + create mode 100644 target/linux/ar71xx/patches-4.14/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch + create mode 100644 target/linux/ar71xx/patches-4.14/504-MIPS-ath79-add-ath79_device_reset_get.patch + create mode 100644 target/linux/ar71xx/patches-4.14/505-MIPS-ath79-add-ath79_gpio_function_select.patch + create mode 100644 target/linux/ar71xx/patches-4.14/506-MIPS-ath79-prom-parse-redboot-args.patch + create mode 100644 target/linux/ar71xx/patches-4.14/507-MIPS-ath79-prom-add-myloader-support.patch + create mode 100644 target/linux/ar71xx/patches-4.14/508-MIPS-ath79-prom-image-command-line-hack.patch + create mode 100644 target/linux/ar71xx/patches-4.14/509-MIPS-ath79-process-board-kernel-option.patch + create mode 100644 target/linux/ar71xx/patches-4.14/510-MIPS-ath79-init-gpio-pin-of-wmac-device.patch + create mode 100644 target/linux/ar71xx/patches-4.14/520-MIPS-ath79-enable-UART-function.patch + create mode 100644 target/linux/ar71xx/patches-4.14/521-MIPS-ath79-enable-UART-for-early_serial.patch + create mode 100644 target/linux/ar71xx/patches-4.14/522-MIPS-ath79-add-ath79_wmac_register_simple-helper.patch + create mode 100644 target/linux/ar71xx/patches-4.14/523-MIPS-ath79-OTP-support.patch + create mode 100644 target/linux/ar71xx/patches-4.14/524-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch + create mode 100644 target/linux/ar71xx/patches-4.14/525-MIPS-ath79-enable-qca-usb-quirks.patch + create mode 100644 target/linux/ar71xx/patches-4.14/601-MIPS-ath79-add-more-register-defines.patch + create mode 100644 target/linux/ar71xx/patches-4.14/602-MIPS-ath79-add-openwrt-stuff.patch + create mode 100644 target/linux/ar71xx/patches-4.14/603-MIPS-ath79-ap121-fixes.patch + create mode 100644 target/linux/ar71xx/patches-4.14/604-MIPS-ath79-no-of.patch + create mode 100644 target/linux/ar71xx/patches-4.14/605-MIPS-ath79-db120-fixes.patch + create mode 100644 target/linux/ar71xx/patches-4.14/606-MIPS-ath79-pb44-fixes.patch + create mode 100644 target/linux/ar71xx/patches-4.14/607-MIPS-ath79-ubnt-xm-fixes.patch + create mode 100644 target/linux/ar71xx/patches-4.14/608-MIPS-ath79-ubnt-xm-add-more-boards.patch + create mode 100644 target/linux/ar71xx/patches-4.14/609-MIPS-ath79-ap136-fixes.patch + create mode 100644 target/linux/ar71xx/patches-4.14/611-MIPS-ath79-wdt-timeout.patch + create mode 100644 target/linux/ar71xx/patches-4.14/612-MIPS-ath79-set-buffalo-txgain.patch + create mode 100644 target/linux/ar71xx/patches-4.14/613-MIPS-ath79-add-ath79_wmac_setup_ext_lna_gpio-helper.patch + create mode 100644 target/linux/ar71xx/patches-4.14/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch + create mode 100644 target/linux/ar71xx/patches-4.14/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch + create mode 100644 target/linux/ar71xx/patches-4.14/622-MIPS-ath79-add-more-register-defines-for-QCA956x-SoC.patch + create mode 100644 target/linux/ar71xx/patches-4.14/630-MIPS-ath79-fix-chained-irq-disable.patch + create mode 100644 target/linux/ar71xx/patches-4.14/631-MIPS-ath79-wmac-enable-set-led-pin.patch + create mode 100644 target/linux/ar71xx/patches-4.14/632-MIPS-ath79-gpio-enable-set-direction.patch + create mode 100644 target/linux/ar71xx/patches-4.14/640-MIPS-ath79-add-QCA955x-wmac-reset.patch + create mode 100644 target/linux/ar71xx/patches-4.14/700-MIPS-ath79-add-openwrt-Kconfig.patch + create mode 100644 target/linux/ar71xx/patches-4.14/701-MIPS-ath79-add-routerboard-detection.patch + create mode 100644 target/linux/ar71xx/patches-4.14/702-MIPS-ath79-fixup-routerboot-board-parameter.patch + create mode 100644 target/linux/ar71xx/patches-4.14/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch + create mode 100644 target/linux/ar71xx/patches-4.14/740-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch + create mode 100644 target/linux/ar71xx/patches-4.14/741-MIPS-ath79-add-PCI-for-QCA9556-SoC.patch + create mode 100644 target/linux/ar71xx/patches-4.14/818-MIPS-ath79-add-nu801-led-driver.patch + create mode 100644 target/linux/ar71xx/patches-4.14/820-MIPS-ath79-add_gpio_function2_setup.patch + create mode 100644 target/linux/ar71xx/patches-4.14/821-serial-core-add-support-for-boot-console-with-arbitr.patch + create mode 100644 target/linux/ar71xx/patches-4.14/900-mdio_bitbang_ignore_ta_value.patch + create mode 100644 target/linux/ar71xx/patches-4.14/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch + create mode 100644 target/linux/ar71xx/patches-4.14/902-at803x-add-reset-gpio-pdata.patch + create mode 100644 target/linux/ar71xx/patches-4.14/903-at803x-add-sgmii-aneg-override-pdata.patch + create mode 100644 target/linux/ar71xx/patches-4.14/910-unaligned_access_hacks.patch + create mode 100644 target/linux/ar71xx/patches-4.14/920-usb-chipidea-AR933x-platform-support.patch + create mode 100644 target/linux/ar71xx/patches-4.14/921-MIPS-ath79-add-even-more-register-defines-for-QCA956x-SoC.patch + create mode 100644 target/linux/ar71xx/patches-4.14/930-chipidea-pullup.patch + create mode 100644 target/linux/ar71xx/patches-4.14/940-qca955x-add-more-registers.patch + create mode 100644 target/linux/ar71xx/patches-4.14/950-add-boardinfo-platform-data.patch + create mode 100644 target/linux/ar71xx/patches-4.14/952-qca955x-enable-ddr-wb-flush.patch + create mode 100644 target/linux/ar71xx/patches-4.14/953-qca955x-pci-reset-fixes.patch + create mode 100644 target/linux/ar71xx/patches-4.14/955-qca953x-fix-potential-missing-irq-dispatch.patch + create mode 100644 target/linux/ar71xx/patches-4.14/999-backport-fixes.patch + create mode 100644 target/linux/ar71xx/tiny/config-default + create mode 100644 target/linux/ar71xx/tiny/profiles/00-default.mk + create mode 100644 target/linux/ar71xx/tiny/target.mk + create mode 100644 target/linux/generic/backport-4.14/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch + create mode 100644 target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch + create mode 100644 target/linux/generic/backport-4.14/012-kbuild-add-macro-for-controlling-warnings-to-linux-c.patch + create mode 100644 target/linux/generic/backport-4.14/013-disable-Wattribute-alias-warning-for-SYSCALL_DEFINEx.patch + create mode 100644 target/linux/generic/backport-4.14/020-backport_netfilter_rtcache.patch + create mode 100644 target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch + create mode 100644 target/linux/generic/backport-4.14/030-USB-serial-option-fix-dwm-158-3g-modem-interface.patch + create mode 100644 target/linux/generic/backport-4.14/030-v4.17-0001-usb-dwc2-add-support-for-host-mode-external-vbus-sup.patch + create mode 100644 target/linux/generic/backport-4.14/030-v4.17-0002-usb-dwc2-dwc2_vbus_supply_init-fix-error-check.patch + create mode 100644 target/linux/generic/backport-4.14/040-v4.17-0001-mtd-move-code-adding-master-MTD-out-of-mtd_add_devic.patch + create mode 100644 target/linux/generic/backport-4.14/040-v4.17-0002-mtd-get-rid-of-the-mtd_add_device_partitions.patch + create mode 100644 target/linux/generic/backport-4.14/041-v4.17-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch + create mode 100644 target/linux/generic/backport-4.14/041-v4.17-0002-mtd-rename-ofpart-parser-to-fixed-partitions-as-it-f.patch + create mode 100644 target/linux/generic/backport-4.14/041-v4.17-0003-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch + create mode 100644 target/linux/generic/backport-4.14/042-v4.18-0001-mtd-move-code-adding-registering-partitions-to-the-p.patch + create mode 100644 target/linux/generic/backport-4.14/043-v4.18-mtd-bcm47xxpart-improve-handling-TRX-partition-size.patch + create mode 100644 target/linux/generic/backport-4.14/044-v4.18-mtd-bcm47xxpart-add-of_match_table-with-a-new-DT-bin.patch + create mode 100644 target/linux/generic/backport-4.14/045-v4.19-mtd-parsers-trx-add-of_match_table-with-the-new-DT-b.patch + create mode 100644 target/linux/generic/backport-4.14/046-v4.19-mtd-partitions-use-DT-info-for-parsing-partitions-wi.patch + create mode 100644 target/linux/generic/backport-4.14/047-v4.21-mtd-keep-original-flags-for-every-struct-mtd_info.patch + create mode 100644 target/linux/generic/backport-4.14/048-v4.21-mtd-improve-calculating-partition-boundaries-when-ch.patch + create mode 100644 target/linux/generic/backport-4.14/050-v4.19-f2fs-skip-verifying-block-address-non-regular-inode.patch + create mode 100644 target/linux/generic/backport-4.14/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch + create mode 100644 target/linux/generic/backport-4.14/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch + create mode 100644 target/linux/generic/backport-4.14/080-v5.1-0001-bcma-keep-a-direct-pointer-to-the-struct-device.patch + create mode 100644 target/linux/generic/backport-4.14/080-v5.1-0002-bcma-use-dev_-printing-functions.patch + create mode 100644 target/linux/generic/backport-4.14/085-v4.16-0001-i2c-gpio-Enable-working-over-slow-can_sleep-GPIOs.patch + create mode 100644 target/linux/generic/backport-4.14/090-net-bridge-add-support-for-port-isolation.patch + create mode 100644 target/linux/generic/backport-4.14/095-Allow-class-e-address-assignment-via-ifconfig-ioctl.patch + create mode 100644 target/linux/generic/backport-4.14/101-arm-cns3xxx-use-actual-size-reads-for-PCIe.patch + create mode 100644 target/linux/generic/backport-4.14/183-net-qmi_wwan-add-Wistron-Neweb-D19Q1.patch + create mode 100644 target/linux/generic/backport-4.14/270-batman-adv-Let-packet.h-include-its-headers-directly.patch + create mode 100644 target/linux/generic/backport-4.14/271-batman-adv-Remove-usage-of-BIT-x-in-packet.h.patch + create mode 100644 target/linux/generic/backport-4.14/272-batman-adv-Remove-kernel-fixed-width-types-in-packet.patch + create mode 100644 target/linux/generic/backport-4.14/273-batman-adv-Convert-packet.h-to-uapi-header.patch + create mode 100644 target/linux/generic/backport-4.14/274-flow_dissector-Parse-batman-adv-unicast-headers.patch + create mode 100644 target/linux/generic/backport-4.14/289-v4.16-netfilter-add-defines-for-arp-decnet-max-hooks.patch + create mode 100644 target/linux/generic/backport-4.14/290-v4.16-netfilter-core-make-nf_unregister_net_hooks-simple-w.patch + create mode 100644 target/linux/generic/backport-4.14/291-v4.16-netfilter-core-remove-synchronize_net-call-if-nfqueu.patch + create mode 100644 target/linux/generic/backport-4.14/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch + create mode 100644 target/linux/generic/backport-4.14/293-v4.16-netfilter-reduce-size-of-hook-entry-point-locations.patch + create mode 100644 target/linux/generic/backport-4.14/294-v4.16-netfilter-reduce-hook-array-sizes-to-what-is-needed.patch + create mode 100644 target/linux/generic/backport-4.14/295-v4.16-netfilter-don-t-allocate-space-for-decnet-hooks-unle.patch + create mode 100644 target/linux/generic/backport-4.14/296-v4.16-netfilter-don-t-allocate-space-for-arp-bridge-hooks-.patch + create mode 100644 target/linux/generic/backport-4.14/297-v4.16-netfilter-core-pass-hook-number-family-and-device-to.patch + create mode 100644 target/linux/generic/backport-4.14/298-v4.16-netfilter-core-add-nf_remove_net_hook.patch + create mode 100644 target/linux/generic/backport-4.14/298-v4.16-netfilter-core-pass-family-as-parameter-to-nf_remove.patch + create mode 100644 target/linux/generic/backport-4.14/299-v4.16-netfilter-core-support-for-NFPROTO_INET-hook-registr.patch + create mode 100644 target/linux/generic/backport-4.14/300-v4.16-netfilter-nf_tables-explicit-nft_set_pktinfo-call-fr.patch + create mode 100644 target/linux/generic/backport-4.14/301-v4.16-netfilter-core-only-allow-one-nat-hook-per-hook-poin.patch + create mode 100644 target/linux/generic/backport-4.14/302-v4.16-netfilter-nf_tables_inet-don-t-use-multihook-infrast.patch + create mode 100644 target/linux/generic/backport-4.14/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch + create mode 100644 target/linux/generic/backport-4.14/304-v4.16-netfilter-move-checksum-indirection-to-struct-nf_ipv.patch + create mode 100644 target/linux/generic/backport-4.14/305-v4.16-netfilter-move-checksum_partial-indirection-to-struc.patch + create mode 100644 target/linux/generic/backport-4.14/306-v4.16-netfilter-remove-saveroute-indirection-in-struct-nf_.patch + create mode 100644 target/linux/generic/backport-4.14/307-v4.16-netfilter-move-route-indirection-to-struct-nf_ipv6_o.patch + create mode 100644 target/linux/generic/backport-4.14/308-v4.16-netfilter-move-reroute-indirection-to-struct-nf_ipv6.patch + create mode 100644 target/linux/generic/backport-4.14/309-v4.16-netfilter-remove-route_key_size-field-in-struct-nf_a.patch + create mode 100644 target/linux/generic/backport-4.14/310-v4.16-netfilter-remove-struct-nf_afinfo-and-its-helper-fun.patch + create mode 100644 target/linux/generic/backport-4.14/311-v4.16-netfilter-nf_tables_arp-don-t-set-forward-chain.patch + create mode 100644 target/linux/generic/backport-4.14/312-v4.16-netfilter-nf_tables-remove-hooks-from-family-definit.patch + create mode 100644 target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch + create mode 100644 target/linux/generic/backport-4.14/314-v4.16-netfilter-meta-secpath-support.patch + create mode 100644 target/linux/generic/backport-4.14/315-v4.15-netfilter-conntrack-move-nf_ct_netns_-get-put-to-cor.patch + create mode 100644 target/linux/generic/backport-4.14/320-v4.16-netfilter-nf_conntrack-add-IPS_OFFLOAD-status-bit.patch + create mode 100644 target/linux/generic/backport-4.14/321-v4.16-netfilter-nf_tables-add-flow-table-netlink-frontend.patch + create mode 100644 target/linux/generic/backport-4.14/322-v4.16-netfilter-add-generic-flow-table-infrastructure.patch + create mode 100644 target/linux/generic/backport-4.14/323-v4.16-netfilter-flow-table-support-for-IPv4.patch + create mode 100644 target/linux/generic/backport-4.14/324-v4.16-netfilter-flow-table-support-for-IPv6.patch + create mode 100644 target/linux/generic/backport-4.14/325-v4.16-netfilter-flow-table-support-for-the-mixed-IPv4-IPv6.patch + create mode 100644 target/linux/generic/backport-4.14/326-v4.16-netfilter-nf_tables-flow-offload-expression.patch + create mode 100644 target/linux/generic/backport-4.14/327-v4.16-netfilter-nf_tables-remove-nhooks-field-from-struct-.patch + create mode 100644 target/linux/generic/backport-4.14/328-v4.16-netfilter-nf_tables-fix-a-typo-in-nf_tables_getflowt.patch + create mode 100644 target/linux/generic/backport-4.14/329-v4.16-netfilter-improve-flow-table-Kconfig-dependencies.patch + create mode 100644 target/linux/generic/backport-4.14/330-v4.16-netfilter-nf_tables-remove-flag-field-from-struct-nf.patch + create mode 100644 target/linux/generic/backport-4.14/331-v4.16-netfilter-nf_tables-no-need-for-struct-nft_af_info-t.patch + create mode 100644 target/linux/generic/backport-4.14/332-v4.16-netfilter-nf_tables-remove-struct-nft_af_info-parame.patch + create mode 100644 target/linux/generic/backport-4.14/334-v4.15-netfilter-nf_tables-fix-potential-NULL-ptr-deref-in-.patch + create mode 100644 target/linux/generic/backport-4.14/335-v4.16-netfilter-nf_tables-add-single-table-list-for-all-fa.patch + create mode 100644 target/linux/generic/backport-4.14/336-v4.15-netfilter-exit_net-cleanup-check-added.patch + create mode 100644 target/linux/generic/backport-4.14/337-v4.16-netfilter-nf_tables-get-rid-of-pernet-families.patch + create mode 100644 target/linux/generic/backport-4.14/338-v4.16-netfilter-nf_tables-get-rid-of-struct-nft_af_info-ab.patch + create mode 100644 target/linux/generic/backport-4.14/339-v4.16-netfilter-nft_flow_offload-wait-for-garbage-collecto.patch + create mode 100644 target/linux/generic/backport-4.14/340-v4.16-netfilter-nft_flow_offload-no-need-to-flush-entries-.patch + create mode 100644 target/linux/generic/backport-4.14/341-v4.16-netfilter-nft_flow_offload-move-flowtable-cleanup-ro.patch + create mode 100644 target/linux/generic/backport-4.14/342-v4.16-netfilter-nf_tables-fix-flowtable-free.patch + create mode 100644 target/linux/generic/backport-4.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch + create mode 100644 target/linux/generic/backport-4.14/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch + create mode 100644 target/linux/generic/backport-4.14/345-v4.16-netfilter-nf_flow_offload-fix-use-after-free-and-a-r.patch + create mode 100644 target/linux/generic/backport-4.14/346-v4.16-netfilter-flowtable-infrastructure-depends-on-NETFIL.patch + create mode 100644 target/linux/generic/backport-4.14/347-v4.16-netfilter-remove-duplicated-include.patch + create mode 100644 target/linux/generic/backport-4.14/348-v4.18-netfilter-nf_flow_table-use-IP_CT_DIR_-values-for-FL.patch + create mode 100644 target/linux/generic/backport-4.14/349-v4.18-netfilter-nf_flow_table-clean-up-flow_offload_alloc.patch + create mode 100644 target/linux/generic/backport-4.14/350-v4.18-ipv6-make-ip6_dst_mtu_forward-inline.patch + create mode 100644 target/linux/generic/backport-4.14/351-v4.18-netfilter-nf_flow_table-cache-mtu-in-struct-flow_off.patch + create mode 100644 target/linux/generic/backport-4.14/352-v4.18-netfilter-nf_flow_table-rename-nf_flow_table.c-to-nf.patch + create mode 100644 target/linux/generic/backport-4.14/353-v4.18-netfilter-nf_flow_table-move-ipv4-offload-hook-code-.patch + create mode 100644 target/linux/generic/backport-4.14/354-v4.18-netfilter-nf_flow_table-move-ip-header-check-out-of-.patch + create mode 100644 target/linux/generic/backport-4.14/355-v4.18-netfilter-nf_flow_table-move-ipv6-offload-hook-code-.patch + create mode 100644 target/linux/generic/backport-4.14/356-v4.18-netfilter-nf_flow_table-relax-mixed-ipv4-ipv6-flowta.patch + create mode 100644 target/linux/generic/backport-4.14/357-v4.18-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch + create mode 100644 target/linux/generic/backport-4.14/358-v4.18-netfilter-nf_flow_table-fix-priv-pointer-for-netdev-.patch + create mode 100644 target/linux/generic/backport-4.14/359-v4.18-netfilter-nf_flow_table-track-flow-tables-in-nf_flow.patch + create mode 100644 target/linux/generic/backport-4.14/360-v4.18-netfilter-nf_flow_table-make-flow_offload_dead-inlin.patch + create mode 100644 target/linux/generic/backport-4.14/361-v4.18-netfilter-nf_flow_table-add-a-new-flow-state-for-tea.patch + create mode 100644 target/linux/generic/backport-4.14/362-v4.18-netfilter-nf_flow_table-in-flow_offload_lookup-skip-.patch + create mode 100644 target/linux/generic/backport-4.14/363-v4.18-netfilter-nf_flow_table-add-support-for-sending-flow.patch + create mode 100644 target/linux/generic/backport-4.14/364-v4.18-netfilter-nf_flow_table-tear-down-TCP-flows-if-RST-o.patch + create mode 100644 target/linux/generic/backport-4.14/365-v4.16-netfilter-nf_flow_table-fix-checksum-when-handling-D.patch + create mode 100644 target/linux/generic/backport-4.14/366-netfilter-nft_flow_offload-Fix-reverse-route-lookup.patch + create mode 100644 target/linux/generic/backport-4.14/367-v4.18-netfilter-nf_flow_table-add-missing-condition-for-TC.patch + create mode 100644 target/linux/generic/backport-4.14/368-v4.18-netfilter-nf_flow_table-fix-offloading-connections-w.patch + create mode 100644 target/linux/generic/backport-4.14/369-v4.18-netfilter-nf_flow_table-attach-dst-to-skbs.patch + create mode 100644 target/linux/generic/backport-4.14/370-netfilter-nf_flow_table-fix-offloaded-connection-tim.patch + create mode 100644 target/linux/generic/backport-4.14/371-netfilter-nf_flow_table-fix-up-ct-state-of-flows-aft.patch + create mode 100644 target/linux/generic/backport-4.14/372-netfilter-nft_flow_offload-fix-interaction-with-vrf-.patch + create mode 100644 target/linux/generic/backport-4.14/380-v5.3-net-sched-Introduce-act_ctinfo-action.patch + create mode 100644 target/linux/generic/backport-4.14/400-v4.16-leds-trigger-Introduce-a-NETDEV-trigger.patch + create mode 100644 target/linux/generic/backport-4.14/401-v5.2-leds-trigger-netdev-fix-refcnt-leak-on-interface-ren.patch + create mode 100644 target/linux/generic/backport-4.14/402-leds-trigger-netdev-fix-handling-on-interface-rename.patch + create mode 100644 target/linux/generic/backport-4.14/410-mtd-fix-calculating-partition-end-address.patch + create mode 100644 target/linux/generic/backport-4.14/420-enable-CONFIG_MMC_SDHCI_IO_ACCESSORS.patch + create mode 100644 target/linux/generic/backport-4.14/500-v4.20-ubifs-Fix-default-compression-selection-in-ubifs.patch + create mode 100644 target/linux/generic/backport-4.14/900-v4.18-firmware-dmi-Add-access-to-the-SKU-ID-string.patch + create mode 100644 target/linux/generic/backport-4.14/950-tty-serial-exar-generalize-rs485-setup.patch + create mode 100644 target/linux/generic/config-4.14 + create mode 100644 target/linux/generic/hack-4.14/204-module_strip.patch + create mode 100644 target/linux/generic/hack-4.14/207-disable-modorder.patch + create mode 100644 target/linux/generic/hack-4.14/210-darwin_scripts_include.patch + create mode 100644 target/linux/generic/hack-4.14/211-host_tools_portability.patch + create mode 100644 target/linux/generic/hack-4.14/212-byteshift_portability.patch + create mode 100644 target/linux/generic/hack-4.14/214-spidev_h_portability.patch + create mode 100644 target/linux/generic/hack-4.14/220-gc_sections.patch + create mode 100644 target/linux/generic/hack-4.14/221-module_exports.patch + create mode 100644 target/linux/generic/hack-4.14/230-openwrt_lzma_options.patch + create mode 100644 target/linux/generic/hack-4.14/250-netfilter_depends.patch + create mode 100644 target/linux/generic/hack-4.14/251-sound_kconfig.patch + create mode 100644 target/linux/generic/hack-4.14/259-regmap_dynamic.patch + create mode 100644 target/linux/generic/hack-4.14/260-crypto_test_dependencies.patch + create mode 100644 target/linux/generic/hack-4.14/280-rfkill-stubs.patch + create mode 100644 target/linux/generic/hack-4.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch + create mode 100644 target/linux/generic/hack-4.14/301-mips_image_cmdline_hack.patch + create mode 100644 target/linux/generic/hack-4.14/321-powerpc_crtsavres_prereq.patch + create mode 100644 target/linux/generic/hack-4.14/400-mt29f_spinand-fix-memleak.patch + create mode 100644 target/linux/generic/hack-4.14/531-debloat_lzma.patch + create mode 100644 target/linux/generic/hack-4.14/640-bridge-only-accept-EAP-locally.patch + create mode 100644 target/linux/generic/hack-4.14/645-netfilter-connmark-introduce-set-dscpmark.patch + create mode 100644 target/linux/generic/hack-4.14/647-netfilter-flow-acct.patch + create mode 100644 target/linux/generic/hack-4.14/650-netfilter-add-xt_OFFLOAD-target.patch + create mode 100644 target/linux/generic/hack-4.14/651-wireless_mesh_header.patch + create mode 100644 target/linux/generic/hack-4.14/660-fq_codel_defaults.patch + create mode 100644 target/linux/generic/hack-4.14/661-use_fq_codel_by_default.patch + create mode 100644 target/linux/generic/hack-4.14/662-remove_pfifo_fast.patch + create mode 100644 target/linux/generic/hack-4.14/700-swconfig_switch_drivers.patch + create mode 100644 target/linux/generic/hack-4.14/702-phy_add_aneg_done_function.patch + create mode 100644 target/linux/generic/hack-4.14/721-phy_packets.patch + create mode 100644 target/linux/generic/hack-4.14/773-bgmac-add-srab-switch.patch + create mode 100644 target/linux/generic/hack-4.14/901-debloat_sock_diag.patch + create mode 100644 target/linux/generic/hack-4.14/902-debloat_proc.patch + create mode 100644 target/linux/generic/hack-4.14/904-debloat_dma_buf.patch + create mode 100644 target/linux/generic/hack-4.14/910-kobject_uevent.patch + create mode 100644 target/linux/generic/hack-4.14/911-kobject_add_broadcast_uevent.patch + create mode 100644 target/linux/generic/hack-4.14/921-always-create-console-node-in-initramfs.patch + create mode 100644 target/linux/generic/hack-4.14/930-crashlog.patch + create mode 100644 target/linux/generic/pending-4.14/0931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch + create mode 100644 target/linux/generic/pending-4.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch + create mode 100644 target/linux/generic/pending-4.14/103-MIPS-perf-ath79-Fix-perfcount-IRQ-assignment.patch + create mode 100644 target/linux/generic/pending-4.14/110-ehci_hcd_ignore_oc.patch + create mode 100644 target/linux/generic/pending-4.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch + create mode 100644 target/linux/generic/pending-4.14/130-add-linux-spidev-compatible-si3210.patch + create mode 100644 target/linux/generic/pending-4.14/131-spi-use-gpio_set_value_cansleep-for-setting-chipsele.patch + create mode 100644 target/linux/generic/pending-4.14/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch + create mode 100644 target/linux/generic/pending-4.14/141-jffs2-add-RENAME_EXCHANGE-support.patch + create mode 100644 target/linux/generic/pending-4.14/150-bridge_allow_receiption_on_disabled_port.patch + create mode 100644 target/linux/generic/pending-4.14/161-mtd-part-add-generic-parsing-of-linux-part-probe.patch + create mode 100644 target/linux/generic/pending-4.14/171-usb-dwc2-Fix-inefficient-copy-of-unaligned-buffers.patch + create mode 100644 target/linux/generic/pending-4.14/180-net-phy-at803x-add-support-for-AT8032.patch + create mode 100644 target/linux/generic/pending-4.14/190-2-5-e1000e-Fix-wrong-comment-related-to-link-detection.patch + create mode 100644 target/linux/generic/pending-4.14/201-extra_optimization.patch + create mode 100644 target/linux/generic/pending-4.14/203-kallsyms_uncompressed.patch + create mode 100644 target/linux/generic/pending-4.14/205-backtrace_module_info.patch + create mode 100644 target/linux/generic/pending-4.14/220-optimize_inlining.patch + create mode 100644 target/linux/generic/pending-4.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch + create mode 100644 target/linux/generic/pending-4.14/261-enable_wilink_platform_without_drivers.patch + create mode 100644 target/linux/generic/pending-4.14/270-platform-mikrotik-build-bits.patch + create mode 100644 target/linux/generic/pending-4.14/300-mips_expose_boot_raw.patch + create mode 100644 target/linux/generic/pending-4.14/302-mips_no_branch_likely.patch + create mode 100644 target/linux/generic/pending-4.14/304-mips_disable_fpu.patch + create mode 100644 target/linux/generic/pending-4.14/305-mips_module_reloc.patch + create mode 100644 target/linux/generic/pending-4.14/306-mips_mem_functions_performance.patch + create mode 100644 target/linux/generic/pending-4.14/307-mips_highmem_offset.patch + create mode 100644 target/linux/generic/pending-4.14/308-mips32r2_tune.patch + create mode 100644 target/linux/generic/pending-4.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch + create mode 100644 target/linux/generic/pending-4.14/310-arm_module_unresolved_weak_sym.patch + create mode 100644 target/linux/generic/pending-4.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch + create mode 100644 target/linux/generic/pending-4.14/332-arc-add-OWRTDTB-section.patch + create mode 100644 target/linux/generic/pending-4.14/333-arc-enable-unaligned-access-in-kernel-mode.patch + create mode 100644 target/linux/generic/pending-4.14/340-MIPS-mm-remove-mips_dma_mapping_error.patch + create mode 100644 target/linux/generic/pending-4.14/341-MIPS-mm-remove-no-op-dma_map_ops-where-possible.patch + create mode 100644 target/linux/generic/pending-4.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch + create mode 100644 target/linux/generic/pending-4.14/400-mtd-add-rootfs-split-support.patch + create mode 100644 target/linux/generic/pending-4.14/401-mtd-add-support-for-different-partition-parser-types.patch + create mode 100644 target/linux/generic/pending-4.14/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch + create mode 100644 target/linux/generic/pending-4.14/403-mtd-hook-mtdsplit-to-Kbuild.patch + create mode 100644 target/linux/generic/pending-4.14/404-mtd-add-more-helper-functions.patch + create mode 100644 target/linux/generic/pending-4.14/411-mtd-partial_eraseblock_write.patch + create mode 100644 target/linux/generic/pending-4.14/412-mtd-partial_eraseblock_unlock.patch + create mode 100644 target/linux/generic/pending-4.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch + create mode 100644 target/linux/generic/pending-4.14/420-mtd-redboot_space.patch + create mode 100644 target/linux/generic/pending-4.14/430-mtd-add-myloader-partition-parser.patch + create mode 100644 target/linux/generic/pending-4.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch + create mode 100644 target/linux/generic/pending-4.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch + create mode 100644 target/linux/generic/pending-4.14/435-mtd-add-routerbootpart-parser-config.patch + create mode 100644 target/linux/generic/pending-4.14/440-block2mtd_init.patch + create mode 100644 target/linux/generic/pending-4.14/441-block2mtd_probe.patch + create mode 100644 target/linux/generic/pending-4.14/450-mtd-m25p80-allow-fallback-from-spi_flash_read-to-reg.patch + create mode 100644 target/linux/generic/pending-4.14/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch + create mode 100644 target/linux/generic/pending-4.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch + create mode 100644 target/linux/generic/pending-4.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch + create mode 100644 target/linux/generic/pending-4.14/465-m25p80-mx-disable-software-protection.patch + create mode 100644 target/linux/generic/pending-4.14/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch + create mode 100644 target/linux/generic/pending-4.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch + create mode 100644 target/linux/generic/pending-4.14/475-mtd-spi-nor-Add-Winbond-w25q128jv-support.patch + create mode 100644 target/linux/generic/pending-4.14/476-mtd-spi-nor-add-eon-en25q128.patch + create mode 100644 target/linux/generic/pending-4.14/477-mtd-add-spi-nor-add-mx25u3235f.patch + create mode 100644 target/linux/generic/pending-4.14/478-mtd-spi-nor-Add-support-for-XM25QH64A-and-XM25QH128A.patch + create mode 100644 target/linux/generic/pending-4.14/479-mtd-spi-nor-add-eon-en25qh32.patch + create mode 100644 target/linux/generic/pending-4.14/479-mtd-spi-nor-add-eon-en25qh64.patch + create mode 100644 target/linux/generic/pending-4.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch + create mode 100644 target/linux/generic/pending-4.14/480-mtd-set-rootfs-to-be-root-dev.patch + create mode 100644 target/linux/generic/pending-4.14/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch + create mode 100644 target/linux/generic/pending-4.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch + create mode 100644 target/linux/generic/pending-4.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch + create mode 100644 target/linux/generic/pending-4.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch + create mode 100644 target/linux/generic/pending-4.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch + create mode 100644 target/linux/generic/pending-4.14/494-mtd-ubi-add-EOF-marker-support.patch + create mode 100644 target/linux/generic/pending-4.14/495-mtd-core-add-get_mtd_device_by_node.patch + create mode 100644 target/linux/generic/pending-4.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch + create mode 100644 target/linux/generic/pending-4.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch + create mode 100644 target/linux/generic/pending-4.14/530-jffs2_make_lzma_available.patch + create mode 100644 target/linux/generic/pending-4.14/532-jffs2_eofdetect.patch + create mode 100644 target/linux/generic/pending-4.14/600-netfilter_conntrack_flush.patch + create mode 100644 target/linux/generic/pending-4.14/610-netfilter_match_bypass_default_checks.patch + create mode 100644 target/linux/generic/pending-4.14/611-netfilter_match_bypass_default_table.patch + create mode 100644 target/linux/generic/pending-4.14/612-netfilter_match_reduce_memory_access.patch + create mode 100644 target/linux/generic/pending-4.14/613-netfilter_optional_tcp_window_check.patch + create mode 100644 target/linux/generic/pending-4.14/620-net_sched-codel-do-not-defer-queue-length-update.patch + create mode 100644 target/linux/generic/pending-4.14/630-packet_socket_type.patch + create mode 100644 target/linux/generic/pending-4.14/640-netfilter-nf_flow_table-add-hardware-offload-support.patch + create mode 100644 target/linux/generic/pending-4.14/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch + create mode 100644 target/linux/generic/pending-4.14/642-net-8021q-support-hardware-flow-table-offload.patch + create mode 100644 target/linux/generic/pending-4.14/643-net-bridge-support-hardware-flow-table-offload.patch + create mode 100644 target/linux/generic/pending-4.14/644-net-pppoe-support-hardware-flow-table-offload.patch + create mode 100644 target/linux/generic/pending-4.14/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch + create mode 100644 target/linux/generic/pending-4.14/646-netfilter-nf_flow_table-rework-private-driver-data.patch + create mode 100644 target/linux/generic/pending-4.14/655-increase_skb_pad.patch + create mode 100644 target/linux/generic/pending-4.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch + create mode 100644 target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch + create mode 100644 target/linux/generic/pending-4.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch + create mode 100644 target/linux/generic/pending-4.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch + create mode 100644 target/linux/generic/pending-4.14/681-NET-add-of_get_mac_address_mtd.patch + create mode 100644 target/linux/generic/pending-4.14/690-net-add-support-for-threaded-NAPI-polling.patch + create mode 100644 target/linux/generic/pending-4.14/703-phy-add-detach-callback-to-struct-phy_driver.patch + create mode 100644 target/linux/generic/pending-4.14/734-net-phy-at803x-allow-to-configure-via-pdata.patch + create mode 100644 target/linux/generic/pending-4.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch + create mode 100644 target/linux/generic/pending-4.14/810-pci_disable_common_quirks.patch + create mode 100644 target/linux/generic/pending-4.14/811-pci_disable_usb_common_quirks.patch + create mode 100644 target/linux/generic/pending-4.14/834-ledtrig-libata.patch + create mode 100644 target/linux/generic/pending-4.14/920-mangle_bootargs.patch + +diff --git a/config/Config-images.in b/config/Config-images.in +index 2921cd5bca..b869ccae70 100644 +--- a/config/Config-images.in ++++ b/config/Config-images.in +@@ -13,6 +13,7 @@ menu "Target Images" + choice + prompt "Compression" + default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_apm821xx ++ default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ar71xx + default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ath79_mikrotik + default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_lantiq + default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_mpc85xx +diff --git a/package/kernel/linux/modules/usb.mk b/package/kernel/linux/modules/usb.mk +index 3dd20a0696..d3752c22b4 100644 +--- a/package/kernel/linux/modules/usb.mk ++++ b/package/kernel/linux/modules/usb.mk +@@ -1590,7 +1590,7 @@ $(eval $(call KernelPackage,usbip-server)) + + define KernelPackage/usb-chipidea + TITLE:=Host and device support for Chipidea controllers +- DEPENDS:=+USB_GADGET_SUPPORT:kmod-usb-gadget @TARGET_ath79 +kmod-usb-ehci +kmod-usb-phy-nop ++ DEPENDS:=+USB_GADGET_SUPPORT:kmod-usb-gadget @TARGET_ar71xx||TARGET_ath79 +kmod-usb-ehci +kmod-usb-phy-nop + KCONFIG:= \ + CONFIG_EXTCON \ + CONFIG_USB_CHIPIDEA \ +diff --git a/package/kernel/mac80211/ath.mk b/package/kernel/mac80211/ath.mk +index 24abb910ff..f209c95ba8 100644 +--- a/package/kernel/mac80211/ath.mk ++++ b/package/kernel/mac80211/ath.mk +@@ -42,6 +42,7 @@ 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_ar71xx) += ATH9K_AHB + config-$(CONFIG_TARGET_ath79) += ATH9K_AHB + config-$(CONFIG_TARGET_ipq40xx) += ATH10K_AHB + config-$(CONFIG_PCI) += ATH9K_PCI +@@ -125,7 +126,7 @@ endef + define KernelPackage/ath + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros common driver part +- DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79||TARGET_ath25 +kmod-mac80211 ++ DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx||TARGET_ath79||TARGET_ath25 +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath.ko + MENU:=1 + endef +@@ -190,7 +191,7 @@ define KernelPackage/ath9k-common + 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 ++ DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx||TARGET_ath79 +kmod-ath +@DRIVER_11N_SUPPORT + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko +@@ -200,7 +201,7 @@ 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 ++ DEPENDS+= @PCI_SUPPORT||TARGET_ar71xx||TARGET_ath79 +kmod-ath9k-common + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k.ko + AUTOLOAD:=$(call AutoProbe,ath9k) +@@ -230,7 +231,7 @@ define KernelPackage/ath9k/config + + config ATH9K_UBNTHSR + bool "Support for Ubiquiti UniFi Outdoor+ access point" +- depends on PACKAGE_kmod-ath9k && TARGET_ath79 ++ depends on PACKAGE_kmod-ath9k && (TARGET_ar71xx_generic||TARGET_ath79) + default y + + endef +diff --git a/target/linux/ar71xx/Makefile b/target/linux/ar71xx/Makefile +new file mode 100644 +index 0000000000..aa53b49735 +--- /dev/null ++++ b/target/linux/ar71xx/Makefile +@@ -0,0 +1,24 @@ ++# ++# Copyright (C) 2008-2011 OpenWrt.org ++# ++# This is free software, licensed under the GNU General Public License v2. ++# See /LICENSE for more information. ++# ++include $(TOPDIR)/rules.mk ++ ++ARCH:=mips ++BOARD:=ar71xx ++BOARDNAME:=Atheros AR7xxx/AR9xxx ++FEATURES:=usbgadget source-only ++CPU_TYPE:=24kc ++SUBTARGETS:=generic tiny nand mikrotik ++ ++KERNEL_PATCHVER:=4.14 ++ ++include $(INCLUDE_DIR)/target.mk ++ ++DEFAULT_PACKAGES += \ ++ kmod-gpio-button-hotplug swconfig \ ++ kmod-ath9k uboot-envtools ++ ++$(eval $(call BuildTarget)) +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +new file mode 100755 +index 0000000000..54727a6e52 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -0,0 +1,1130 @@ ++#!/bin/sh ++# ++# Copyright (C) 2011 OpenWrt.org ++# ++ ++. /lib/functions/uci-defaults.sh ++ ++board_config_update ++ ++board=$(board_name) ++ ++case "$board" in ++a40) ++ ucidef_set_led_default "status-red" "Status (red)" "a40:red:status" "0" ++ ucidef_set_led_default "status-blue" "Status (blue)" "a40:blue:status" "0" ++ ;; ++a60) ++ ucidef_set_led_default "status-red" "Status (red)" "a60:red:status" "0" ++ ucidef_set_led_default "status-blue" "Status (blue)" "a60:blue:status" "0" ++ ;; ++airgateway|\ ++airgatewaypro) ++ ucidef_set_led_wlan "wlan" "WLAN" "ubnt:blue:wlan" "phy0tpt" ++ ;; ++alfa-nx) ++ ucidef_set_led_netdev "wan" "WAN" "alfa:green:led_2" "eth0" ++ ucidef_set_led_netdev "lan" "LAN" "alfa:green:led_3" "eth1" ++ ;; ++all0258n|\ ++all0315n) ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "$board:red:rssilow" "wlan0" "1" "40" "0" "6" ++ ucidef_set_led_rssi "rssimedium" "RSSIMEDIUM" "$board:yellow:rssimedium" "wlan0" "30" "80" "-29" "5" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "$board:green:rssihigh" "wlan0" "70" "100" "-69" "8" ++ ;; ++antminer-s1|\ ++antminer-s3) ++ ucidef_set_led_default "sys" "SYS" "$board:green:sys" "0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ++ case "$board" in ++ antminer-s3) ++ ucidef_set_led_default "lan" "LAN" "$board:yellow:lan" "0" ++ ;; ++ esac ++ ;; ++antrouter-r1) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ucidef_set_led_default "btc" "BTC" "$board:green:btc" "0" ++ ;; ++ap121f) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; ++ap147-010) ++ ucidef_set_led_netdev "wan" "WAN" "ap147:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "ap147:green:lan1" "switch0" "0x10" ++ ucidef_set_led_switch "lan2" "LAN2" "ap147:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "ap147:green:lan3" "switch0" "0x04" ++ ucidef_set_led_switch "lan4" "LAN4" "ap147:green:lan4" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan2g" "WLAN 2.4 GHz" "ap147:green:wlan-2g" "phy0tpt" ++ ;; ++ap90q|\ ++cpe505n|\ ++cpe830|\ ++cpe870|\ ++dr531|\ ++e600g-v2|\ ++e600gac-v2|\ ++e750a-v4) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth1" ++ ++ case "$board" in ++ ap90q) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; ++ cpe505n) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:blue:wlan" "phy0tpt" ++ ;; ++ cpe830|\ ++ cpe870) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "$board:green:link1" "wlan0" "1" "100" "0" "13" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "$board:green:link2" "wlan0" "26" "100" "-25" "13" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "$board:green:link3" "wlan0" "51" "100" "-50" "13" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "$board:green:link4" "wlan0" "76" "100" "-75" "13" ++ ;; ++ esac ++ ;; ++ap531b0|\ ++gl-usb150|\ ++sc1750|\ ++sc450) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; ++ap91-5g|\ ++n5q) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "signal1" "SIGNAL1" "$board:red:signal1" "wlan0" "1" "100" ++ ucidef_set_led_rssi "signal2" "SIGNAL2" "$board:orange:signal2" "wlan0" "25" "100" ++ ucidef_set_led_rssi "signal3" "SIGNAL3" "$board:green:signal3" "wlan0" "50" "100" ++ ucidef_set_led_rssi "signal4" "SIGNAL4" "$board:green:signal4" "wlan0" "75" "100" ++ ++ case "$board" in ++ n5q) ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; ++ esac ++ ;; ++archer-c25-v1) ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" ++ ucidef_set_led_switch "lan1" "LAN1" "$board:green:lan1" "switch0" "0x10" ++ ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x04" ++ ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x02" ++ ;; ++archer-c5|\ ++archer-c7) ++ ucidef_set_led_usbport "usb1" "USB1" "tp-link:green:usb1" "usb1-port1" ++ ucidef_set_led_usbport "usb2" "USB2" "tp-link:green:usb2" "usb2-port1" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "tp-link:green:wlan5g" "phy0tpt" ++ ;; ++archer-c58-v1|\ ++archer-c59-v1|\ ++archer-c59-v2|\ ++archer-c60-v1|\ ++archer-c60-v2) ++ ucidef_set_led_switch "lan" "LAN" "$board:green:lan" "switch0" "0x1E" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" ++ ++ case "$board" in ++ archer-c59-v1|\ ++ archer-c59-v2) ++ ucidef_set_led_usbport "usb" "USB" "$board:green:usb" "usb1-port1" ++ ;; ++ esac ++ ;; ++archer-c7-v4|\ ++archer-c7-v5) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" ++ ucidef_set_led_switch "wan" "WAN" "$board:green:wan" "switch0" "0x02" ++ ucidef_set_led_switch "lan1" "LAN1" "$board:green:lan4" "switch0" "0x04" ++ ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan3" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan2" "switch0" "0x10" ++ ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan1" "switch0" "0x20" ++ ++ case "$board" in ++ archer-c7-v4) ++ ucidef_set_led_usbport "usb1" "USB1" "$board:green:usb1" "usb1-port1" ++ ucidef_set_led_usbport "usb2" "USB2" "$board:green:usb2" "usb2-port1" ++ ;; ++ esac ++ ++ case "$board" in ++ archer-c7-v5) ++ ucidef_set_led_usbport "usb" "USB" "$board:green:usb" "usb1-port1" ++ ;; ++ esac ++ ;; ++arduino-yun) ++ ucidef_set_led_wlan "wlan" "WLAN" "arduino:blue:wlan" "phy0tpt" ++ ucidef_set_led_usbport "usb" "USB" "arduino:white:usb" "1-1-port1" ++ ;; ++bhr-4grv2) ++ ucidef_set_led_default "power" "POWER" "buffalo:green:power" "1" ++ ucidef_set_led_default "diag" "DIAG" "buffalo:red:diag" "0" ++ ;; ++bsb) ++ ucidef_set_led_default "sys" "SYS" "$board:red:sys" "1" ++ ;; ++bullet-m|\ ++bullet-m-xw|\ ++loco-m-xw|\ ++nanostation-m|\ ++nanostation-m-xw|\ ++rocket-m|\ ++rocket-m-xw) ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "ubnt:red:link1" "wlan0" "1" "100" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "ubnt:orange:link2" "wlan0" "26" "100" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "ubnt:green:link3" "wlan0" "51" "100" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "ubnt:green:link4" "wlan0" "76" "100" ++ ;; ++bxu2000n-2-a1) ++ ucidef_set_led_wlan "wlan" "WLAN" "bhu:green:wlan" "phy0tpt" ++ ;; ++cap324) ++ ucidef_set_led_netdev "lan" "LAN" "pcs:green:lan" "eth0" ++ ucidef_set_led_wlan "wlan_amber" "WLAN_AMBER" "pcs:amber:wlan" "phy0tpt" ++ ucidef_set_led_wlan "wlan_green" "WLAN_GREEN" "pcs:green:wlan" "phy1tpt" ++ ;; ++c-55) ++ ucidef_set_led_netdev "lan_green" "LAN_GREEN" "$board:green:lan" "eth0" ++ ucidef_set_led_wlan "wlan_amber" "WLAN_AMBER" "$board:amber:wlan" "phy0tpt" ++ ucidef_set_led_wlan "wlan_green" "WLAN_GREEN" "$board:green:wlan" "phy1tpt" ++ ;; ++c-60) ++ ucidef_set_led_wlan "wlan1_green" "WLAN1_GREEN" "$board:green:wlan1" "phy0tpt" ++ ucidef_set_led_wlan "wlan2_green" "WLAN2_GREEN" "$board:green:wlan2" "phy1tpt" ++ ;; ++cap4200ag) ++ ucidef_set_led_default "lan_green" "LAN_GREEN" "senao:green:lan" "1" ++ ucidef_set_led_wlan "wlan_amber" "WLAN_AMBER" "senao:amber:wlan" "phy0tpt" ++ ucidef_set_led_wlan "wlan_green" "WLAN_GREEN" "senao:green:wlan" "phy1tpt" ++ ;; ++carambola2) ++ ucidef_set_led_netdev "lan" "LAN" "$board:orange:eth0" "eth0" ++ ucidef_set_led_netdev "wan" "WAN" "$board:orange:eth1" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; ++cf-e316n-v2) ++ ucidef_set_led_netdev "lan" "LAN" "$board:blue:lan" "eth0" ++ ucidef_set_led_netdev "wan" "WAN" "$board:blue:wan" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:blue:wlan" "phy0tpt" ++ ;; ++cf-e320n-v2) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ucidef_set_led_netdev "wan" "WAN" "$board:red:wan" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:blue:wlan" "phy0tpt" ++ ;; ++cf-e355ac-v1|\ ++cf-e355ac-v2|\ ++cf-e375ac|\ ++cf-e380ac-v1|\ ++cf-e380ac-v2|\ ++cf-e385ac) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:blue:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:red:wlan5g" "phy0tpt" ++ ++ case "$board" in ++ cf-e375ac|\ ++ cf-e385ac) ++ ucidef_set_led_switch "lan" "LAN" "$board:green:lan" "switch0" "0x04" ++ ;; ++ *) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ;; ++ esac ++ ;; ++cf-e520n|\ ++cf-e530n) ++ ucidef_set_led_netdev "wan" "WAN" "$board:blue:wan" "eth1" ++ ;; ++cpe210|\ ++cpe210-v2|\ ++cpe210-v3|\ ++cpe510|\ ++cpe510-v2|\ ++wbs210|\ ++wbs510) ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:green:link1" "wlan0" "1" "100" "0" "13" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:green:link2" "wlan0" "26" "100" "-25" "13" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:link3" "wlan0" "51" "100" "-50" "13" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:link4" "wlan0" "76" "100" "-75" "13" ++ ++ case "$board" in ++ cpe210-v2|\ ++ cpe210-v3|\ ++ cpe510-v2) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan0" "eth0" ++ ;; ++ *) ++ ucidef_set_led_switch "lan0" "LAN0" "tp-link:green:lan0" "switch0" "0x20" ++ ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10" ++ ;; ++ esac ++ ;; ++cr3000) ++ ucidef_set_led_netdev "wan" "WAN" "pcs:blue:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "pcs:blue:lan1" "switch0" "0x04" ++ ucidef_set_led_switch "lan2" "LAN2" "pcs:blue:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "pcs:blue:lan3" "switch0" "0x10" ++ ucidef_set_led_switch "lan4" "LAN4" "pcs:blue:lan4" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "pcs:blue:wlan" "phy0tpt" ++ ;; ++cr5000) ++ ucidef_set_led_wlan "wlan" "WLAN" "pcs:blue:wlan" "phy0tpt" ++ ucidef_set_led_usbport "usb" "USB" "pcs:white:wps" "usb1-port1" ++ ;; ++db120) ++ ucidef_set_led_usbport "usb" "USB" "$board:green:usb" "usb1-port1" ++ ;; ++dr344) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" ++ ;; ++dragino2) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:red:wlan" "phy0tpt" ++ ucidef_set_led_netdev "lan" "LAN" "$board:red:lan" "eth0" ++ ucidef_set_led_netdev "wan" "WAN" "$board:red:wan" "eth1" ++ ;; ++dw33d) ++ ucidef_set_led_usbport "mmc" "MMC" "$board:blue:mmc" "usb1-port1" ++ ucidef_set_led_usbport "usb" "USB" "$board:blue:usb" "usb2-port1" ++ ucidef_set_led_netdev "internet" "INTERNET" "$board:blue:internet" "eth0" ++ ucidef_set_led_wlan "wlan2g" "WLAN-2.4G" "$board:blue:wlan-2g" "phy1tpt" ++ ;; ++eap300v2) ++ ucidef_set_led_netdev "lan" "LAN" "engenius:blue:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "engenius:blue:wlan" "phy0tpt" ++ ;; ++ens202ext) ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "engenius:amber:wlan1" "wlan0" "1" "100" "0" "13" ++ ucidef_set_led_rssi "rssimedium" "RSSIMEDIUM" "engenius:red:wlan2" "wlan0" "25" "100" "-39" "13" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "engenius:amber:wlan3" "wlan0" "50" "100" "-59" "13" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "engenius:green:wlan4" "wlan0" "75" "100" "-79" "13" ++ ;; ++f9k1115v2) ++ ucidef_set_led_usbport "usb2" "USB2" "belkin:green:usb2" "usb1-port1" ++ ;; ++fritz300e) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "$board:green:rssi0" "wlan0" "1" "100" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "$board:green:rssi1" "wlan0" "20" "100" ++ ucidef_set_led_rssi "rssimedium" "RSSIMEDIUM" "$board:green:rssi2" "wlan0" "40" "100" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "$board:green:rssi3" "wlan0" "60" "100" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "$board:green:rssi4" "wlan0" "80" "100" ++ ;; ++dap-1330-a1) ++ ucidef_set_rssimon "wlan0" "2000000" "2" ++ ucidef_set_led_rssi "wifi-low" "wifi-low" "d-link:red:wifi" "wlan0" "1" "29" ++ ucidef_set_led_rssi "wifi-medium" "wifi-medium" "d-link:green:wifi" "wlan0" "30" "100" ++ ucidef_set_led_rssi "wifi-high" "wifi-high" "d-link:green:signal1" "wlan0" "50" "100" ++ ucidef_set_led_rssi "wifi-max" "wifi-max" "d-link:green:signal2" "wlan0" "70" "100" ++ ;; ++dap-2695-a1) ++ ucidef_set_led_default "power" "POWER" "d-link:green:power" "1" ++ ucidef_set_led_default "diag" "DIAG" "d-link:red:power" "0" ++ ucidef_set_led_wlan "wlan2g" "WLAN 2.4 GHz" "d-link:green:wlan2g" "phy1tpt" ++ ;; ++dhp-1565-a1) ++ ucidef_set_led_switch "wan" "WAN" "d-link:green:planet" "switch0" "0x20" ++ ;; ++dir-600-a1|\ ++dir-615-e1|\ ++dir-615-e4|\ ++ebr-2310-c1) ++ ucidef_set_led_netdev "wan" "WAN" "d-link:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "d-link:green:lan1" "switch0" "0x02" ++ ucidef_set_led_switch "lan2" "LAN2" "d-link:green:lan2" "switch0" "0x04" ++ ucidef_set_led_switch "lan3" "LAN3" "d-link:green:lan3" "switch0" "0x08" ++ ucidef_set_led_switch "lan4" "LAN4" "d-link:green:lan4" "switch0" "0x10" ++ ;; ++dir-615-c1) ++ ucidef_set_led_netdev "wan" "WAN" "d-link:green:wan" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "d-link:green:wlan" "phy0tpt" ++ ;; ++dir-825-b1|\ ++dir-825-c1) ++ ucidef_set_led_usbport "usb" "USB" "d-link:blue:usb" "usb1-port1" ++ ++ case "$board" in ++ dir-825-c1) ++ ucidef_set_led_wlan "wlan2g" "WLAN 2.4 GHz" "d-link:blue:wlan2g" "phy0tpt" ++ ;; ++ esac ++ ;; ++dir-615-i1) ++ ucidef_set_led_default "power" "POWER" "d-link:green:power" "1" ++ ucidef_set_led_default "diag" "DIAG" "d-link:amber:power" "0" ++ ucidef_set_led_default "wps" "WPS" "d-link:blue:wps" "0" ++ ucidef_set_led_netdev "wan" "WAN" "d-link:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "d-link:green:wlan" "phy0tpt" ++ ;; ++dlan-hotspot) ++ ucidef_set_led_wlan "wlan" "WLAN" "devolo:green:wifi" "phy0tpt" ++ ;; ++dlan-pro-500-wp) ++ ucidef_set_led_default "power" "System Power" "devolo:green:status" "1" ++ ucidef_set_led_netdev "lan" "Ethernet Activity" "devolo:green:eth" "br-lan" ++ ucidef_set_led_wlan "wlan2g" "WLAN 2.4 GHz" "devolo:green:wlan-2g" "phy0tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN 5 GHz" "devolo:blue:wlan-5g" "none" ++ ;; ++dlan-pro-1200-ac) ++ ucidef_set_led_wlan "wlan" "WLAN" "devolo:status:wlan" "phy0radio" ++ ucidef_set_led_gpio "plcw" "dLAN" "devolo:status:dlan" "17" "0" ++ ucidef_set_led_gpio "plcr" "dLAN" "devolo:error:dlan" "16" "0" ++ ;; ++e1700ac-v2) ++ ucidef_set_led_usbport "usb" "USB" "$board:green:usb" "usb1-port1" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:green:wlan2g" "phy1tpt" ++ ;; ++e558-v2|\ ++e750g-v8) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; ++esr900) ++ ucidef_set_led_wlan "wlan2g" "WLAN 2.4 GHz" "engenius:blue:wlan-2g" "phy0tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN 5 GHz" "engenius:blue:wlan-5g" "phy1tpt" ++ ;; ++esr1750|\ ++epg5000) ++ ucidef_set_led_wlan "wlan2g" "WLAN 2.4 GHz" "$board:blue:wlan-2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN 5 GHz" "$board:blue:wlan-5g" "phy0tpt" ++ ;; ++fritz4020) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; ++fritz450e) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; ++gl-ar300m) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:red:wlan" "phy0tpt" ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" ++ ;; ++gl-ar750) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:white:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:white:wlan5g" "phy0tpt" ++ ;; ++gl-ar750s) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" ++ ;; ++gl-mifi) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" ++ ucidef_set_led_netdev "3gnet" "3GNET" "$board:green:net" "3g-wan" ++ ;; ++gl-ar150) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:orange:wlan" "phy0tpt" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" ++ ;; ++gl-ar300) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:wlan" "phy0tpt" ++ ;; ++gl-domino|\ ++sc300m|\ ++wrt160nl) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:blue:wlan" "phy0tpt" ++ ;; ++gl-inet) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:red:wlan" "phy0tpt" ++ ;; ++hiwifi-hc6361) ++ ucidef_set_led_netdev "inet" "INET" "hiwifi:blue:internet" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "hiwifi:blue:wlan-2p4" "phy0tpt" ++ ;; ++hornet-ub|\ ++hornet-ub-x2) ++ ucidef_set_led_netdev "lan" "LAN" "alfa:blue:lan" "eth0" ++ ucidef_set_led_netdev "wan" "WAN" "alfa:blue:wan" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "alfa:blue:wlan" "phy0tpt" ++ ucidef_set_led_usbport "usb" "USB" "alfa:blue:usb" "usb1-port1" ++ ;; ++koala) ++ ucidef_set_led_default "power" "POWER" "$board:green:power" "1" ++ ucidef_set_led_wlan "wlan2g" "WLAN 2.4GHz" "$board:yellow:wlan2" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN 5GHz" "$board:red:wlan58" "phy0tpt" ++ ;; ++lan-turtle) ++ ucidef_set_led_netdev "wan" "WAN" "$board:orange:system" "eth1" ++ ;; ++lbe-m5) ++ ucidef_set_led_netdev "lan" "LAN" "ubnt:green:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "ubnt:green:wlan" "phy0tpt" ++ ;; ++mc-mac1200r) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "mercury:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "mercury:green:wlan5g" "phy0tpt" ++ ;; ++mr12|\ ++mr16) ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan1" "WLAN1" "$board:green:wifi1" "phy0assoc" ++ ucidef_set_led_wlan "wlan2" "WLAN2" "$board:green:wifi2" "phy0assoc" ++ ucidef_set_led_wlan "wlan3" "WLAN3" "$board:green:wifi3" "phy0assoc" ++ ucidef_set_led_wlan "wlan4" "WLAN4" "$board:green:wifi4" "phy0tpt" ++ ;; ++mr18) ++ ucidef_set_led_netdev "wlan0" "WLAN0" "$board:blue:tricolor0" "wlan0" ++ ;; ++mr600) ++ ucidef_set_led_wlan "wlan58" "WLAN58" "$board:green:wlan58" "phy0tpt" ++ ucidef_set_led_default "wps" "WPS" "mr600:blue:wps" "0" ++ ;; ++mr600v2) ++ ucidef_set_led_default "wlan24-red" "WLAN 2.4GHz (red)" "mr600:red:wlan24" "0" ++ ucidef_set_led_default "wlan24-yellow" "WLAN 2.4GHz (yellow)" "mr600:yellow:wlan24" "0" ++ ucidef_set_led_wlan "wlan24-green" "WLAN 4GHz (green)" "mr600:green:wlan24" "phy1tpt" ++ ucidef_set_led_default "wlan5-red" "WLAN 5GHz (red)" "mr600:red:wlan58" "0" ++ ucidef_set_led_default "wlan5-yellow" "WLAN 5GHz (yellow)" "mr600:yellow:wlan58" "0" ++ ucidef_set_led_wlan "wlan5-green" "WLAN 5GHz (green)" "mr600:green:wlan58" "phy0tpt" ++ ;; ++mr1750|\ ++mr1750v2) ++ ucidef_set_led_netdev "lan" "LAN" "mr1750:blue:wan" "eth0" ++ ucidef_set_led_wlan "wlan58" "WLAN58" "mr1750:blue:wlan58" "phy0tpt" ++ ucidef_set_led_wlan "wlan24" "WLAN24" "mr1750:blue:wlan24" "phy1tpt" ++ ucidef_set_led_default "status-red" "Status (red)" "mr1750:red:wifi" "0" ++ ucidef_set_led_default "status-green" "Status (green)" "mr1750:green:wifi" "0" ++ ;; ++mr900|\ ++mr900v2) ++ ucidef_set_led_netdev "lan" "LAN" "mr900:blue:wan" "eth0" ++ ucidef_set_led_wlan "wlan24" "WLAN24" "mr900:blue:wlan24" "phy0tpt" ++ ucidef_set_led_wlan "wlan58" "WLAN58" "mr900:blue:wlan58" "phy1tpt" ++ ucidef_set_led_default "status-red" "Status (red)" "mr900:red:wifi" "0" ++ ucidef_set_led_default "status-green" "Status (green)" "mr900:green:wifi" "0" ++ ;; ++mynet-n600) ++ ucidef_set_led_netdev "wan" "WAN" "wd:blue:internet" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "wd:green:lan1" "switch0" "0x02" ++ ucidef_set_led_switch "lan2" "LAN2" "wd:green:lan2" "switch0" "0x10" ++ ucidef_set_led_switch "lan3" "LAN3" "wd:green:lan3" "switch0" "0x08" ++ ucidef_set_led_switch "lan4" "LAN4" "wd:green:lan4" "switch0" "0x04" ++ ;; ++mynet-rext) ++ ucidef_set_led_netdev "lan" "LAN" "wd:blue:ethernet" "eth0" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "wd:blue:quality1" "wlan0" "1" "40" "0" "6" ++ ucidef_set_led_rssi "rssimedium" "RSSIMEDIUM" "wd:blue:quality2" "wlan0" "30" "80" "-29" "5" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "wd:blue:quality3" "wlan0" "70" "100" "-69" "8" ++ ucidef_set_led_wlan "wlan" "WLAN" "wd:blue:wireless" "phy0tpt" ++ ;; ++mzk-w04u) ++ ucidef_set_led_usbport "usb" "USB" "planex:green:usb" "usb1-port1" ++ ;; ++mzk-w300nh) ++ ucidef_set_led_wlan "wlan" "WLAN" "planex:green:wlan" "phy0tpt" ++ ;; ++nbg460n_550n_550nh) ++ ucidef_set_led_wlan "wlan" "WLAN" "nbg460n:green:wlan" "phy0tpt" ++ ;; ++nbg6616) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wifi2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5" "WLAN5" "$board:green:wifi5g" "phy0tpt" ++ ucidef_set_led_usbport "usb1" "USB1" "$board:green:usb1" "usb1-port1" ++ ucidef_set_led_usbport "usb2" "USB2" "$board:green:usb2" "usb2-port1" ++ ;; ++nbg6716) ++ ucidef_set_led_netdev "wan" "WAN" "$board:white:internet" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:white:wifi2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5" "WLAN5" "$board:white:wifi5g" "phy0tpt" ++ ucidef_set_led_usbport "usb1" "USB1" "$board:white:usb1" "usb1-port1" ++ ucidef_set_led_usbport "usb2" "USB2" "$board:white:usb2" "usb2-port1" ++ ;; ++om2p|\ ++om2p-hs|\ ++om2p-hsv2|\ ++om2p-hsv3|\ ++om2p-hsv4|\ ++om2p-lc|\ ++om2pv2|\ ++om2pv4) ++ ucidef_set_led_netdev "port1" "port1" "om2p:blue:wan" "eth0" ++ ucidef_set_led_netdev "port2" "port2" "om2p:blue:lan" "eth1" ++ ucidef_set_led_default "wlan-red" "WLAN (red)" "om2p:red:wifi" "0" ++ ucidef_set_led_default "wlan-yellow" "WLAN (yellow)" "om2p:yellow:wifi" "0" ++ ucidef_set_led_default "wlan-green" "WLAN (green)" "om2p:green:wifi" "0" ++ ;; ++om5p|\ ++om5p-an) ++ ucidef_set_led_netdev "port1" "port1" "om5p:blue:wan" "eth0" ++ ucidef_set_led_netdev "port2" "port2" "om5p:blue:lan" "eth1" ++ ucidef_set_led_default "wlan-red" "WLAN (red)" "om5p:red:wifi" "0" ++ ucidef_set_led_default "wlan-yellow" "WLAN (yellow)" "om5p:yellow:wifi" "0" ++ ucidef_set_led_default "wlan-green" "WLAN (green)" "om5p:green:wifi" "0" ++ ;; ++om5p-ac) ++ ucidef_set_led_netdev "port1" "port1" "om5pac:blue:lan" "eth0" ++ ucidef_set_led_netdev "port2" "port2" "om5pac:blue:wan" "eth1" ++ ucidef_set_led_default "wlan-red" "WLAN (red)" "om5pac:red:wifi" "0" ++ ucidef_set_led_default "wlan-yellow" "WLAN (yellow)" "om5pac:yellow:wifi" "0" ++ ucidef_set_led_default "wlan-green" "WLAN (green)" "om5pac:green:wifi" "0" ++ ;; ++om5p-acv2) ++ ucidef_set_led_default "wlan-red" "WLAN (red)" "om5pac:red:wifi" "0" ++ ucidef_set_led_default "wlan-yellow" "WLAN (yellow)" "om5pac:yellow:wifi" "0" ++ ucidef_set_led_default "wlan-green" "WLAN (green)" "om5pac:green:wifi" "0" ++ ;; ++omy-g1) ++ ucidef_set_led_wlan "wlan" "WLAN" "omy:green:wlan" "phy0tpt" ++ ucidef_set_led_netdev "wan" "WAN" "omy:green:wan" "eth0" ++ ucidef_set_led_netdev "lan" "LAN" "omy:green:lan" "eth1" ++ ;; ++omy-x1) ++ ucidef_set_led_default "power" "POWER" "omy:green:power" "1" ++ ucidef_set_led_default "wan" "WAN" "omy:green:wan" "eth0" ++ ;; ++pqi-air-pen) ++ ucidef_set_led_wlan "wlan" "WLAN" "pqi-air-pen:blue:wlan" "phy0tpt" ++ ucidef_set_led_default "wps" "WPS" "pqi-air-pen:blue:wps" "0" ++ ;; ++qihoo-c301) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "qihoo:red:status" "phy1tpt" ++ ;; ++r36a) ++ ucidef_set_led_netdev "lan" "LAN" "$board:blue:lan" "eth0" ++ ucidef_set_led_usbport "usb" "USB" "$board:blue:usb" "usb1-port1" ++ ucidef_set_led_netdev "wan" "WAN" "$board:blue:wan" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:blue:wlan" "phy0tpt" ++ ;; ++r602n|\ ++t830|\ ++zbt-we1526) ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "$board:green:lan1" "switch0" "0x10" ++ ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x04" ++ ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ++ case "$board" in ++ t830) ++ ucidef_set_led_usbport "usb" "USB" "$board:green:usb" "usb1-port1" ++ ;; ++ esac ++ ;; ++r6100) ++ ucidef_set_led_netdev "wan" "WAN (green)" "netgear:green:wan" "eth0" ++ ucidef_set_led_usbport "usb" "USB" "netgear:blue:usb" "usb1-port1" ++ ucidef_set_led_wlan "wlan" "WLAN" "netgear:blue:wlan" "phy1tpt" ++ ;; ++rb-750) ++ ucidef_set_led_default "act" "act" "rb750:green:act" "1" ++ ucidef_set_led_netdev "port1" "port1" "rb750:green:port1" "eth1" ++ ucidef_set_led_switch "port2" "port2" "rb750:green:port2" "switch0" "0x10" ++ ucidef_set_led_switch "port3" "port3" "rb750:green:port3" "switch0" "0x08" ++ ucidef_set_led_switch "port4" "port4" "rb750:green:port4" "switch0" "0x04" ++ ucidef_set_led_switch "port5" "port5" "rb750:green:port5" "switch0" "0x02" ++ ;; ++rb-750-r2|\ ++rb-750p-pbr2|\ ++rb-750up-r2) ++ ucidef_set_led_timer "user" "USER" "rb:green:user" "1000" "1000" ++ ucidef_set_led_netdev "port1" "port1" "rb:green:port1" "eth0" ++ ucidef_set_led_switch "port2" "port2" "rb:green:port2" "switch0" "0x10" ++ ucidef_set_led_switch "port3" "port2" "rb:green:port3" "switch0" "0x08" ++ ucidef_set_led_switch "port4" "port3" "rb:green:port4" "switch0" "0x04" ++ ucidef_set_led_switch "port5" "port5" "rb:green:port5" "switch0" "0x02" ++ ;; ++rb-911-2hn|\ ++rb-911-5hn) ++ ucidef_set_led_netdev "eth" "ETH" "rb:green:eth" "eth0" ++ ;; ++rb-931-2nd|\ ++rb-941-2nd) ++ ucidef_set_led_timer "user" "USR/ACT" "rb:green:user" "1000" "1000" ++ ;; ++rb-951ui-2nd|\ ++rb-952ui-5ac2nd) ++ ucidef_set_led_timer "user" "USER" "rb:green:user" "1000" "1000" ++ ucidef_set_led_netdev "port1" "port1" "rb:green:port1" "eth0" ++ ucidef_set_led_switch "port2" "port2" "rb:green:port2" "switch0" "0x10" ++ ucidef_set_led_switch "port3" "port2" "rb:green:port3" "switch0" "0x08" ++ ucidef_set_led_switch "port4" "port3" "rb:green:port4" "switch0" "0x04" ++ ucidef_set_led_switch "port5" "port5" "rb:green:port5" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "rb:blue:wlan" "phy0tpt" ++ ;; ++rb-962uigs-5hact2hnt) ++ ucidef_set_led_timer "user" "USER/SFP" "rb:green:user" "1000" "1000" ++ ;; ++rb-2011il|\ ++rb-2011ils|\ ++rb-2011l|\ ++rb-2011uas|\ ++rb-2011uas-2hnd|\ ++rb-2011uias|\ ++rb-2011uias-2hnd|\ ++rb-2011uias-2hnd-r2) ++ ucidef_set_led_switch "eth6" "ETH6" "rb:green:eth6" "switch1" "0x20" ++ ucidef_set_led_switch "eth7" "ETH7" "rb:green:eth7" "switch1" "0x10" ++ ucidef_set_led_switch "eth8" "ETH8" "rb:green:eth8" "switch1" "0x08" ++ ucidef_set_led_switch "eth9" "ETH9" "rb:green:eth9" "switch1" "0x04" ++ ucidef_set_led_switch "eth10" "ETH10" "rb:green:eth10" "switch1" "0x02" ++ ;; ++rb-lhg-5nd) ++ ucidef_set_led_netdev "lan" "LAN" "rb:green:eth" "eth0" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "rb:green:rssi0" "wlan0" "1" "100" "0" "13" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "rb:green:rssi1" "wlan0" "20" "100" "-19" "13" ++ ucidef_set_led_rssi "rssimedium" "RSSIMEDIUM" "rb:green:rssi2" "wlan0" "40" "100" "-39" "13" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "rb:green:rssi3" "wlan0" "60" "100" "-59" "13" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "rb:green:rssi4" "wlan0" "80" "100" "-79" "13" ++ ;; ++rb-map-2nd) ++ ucidef_set_led_switch "eth1" "WAN" "rb:green:eth1" "switch0" "0x02" ++ ucidef_set_led_switch "eth2" "LAN" "rb:green:eth2" "switch0" "0x04" ++ ucidef_set_led_gpio "poe" "POE" "rb:red:poe_out" "14" "0" ++ ucidef_set_led_wlan "wlan" "WLAN" "rb:green:wlan" "phy0tpt" ++ ;; ++rb-mapl-2nd) ++ ucidef_set_led_default "power" "POWER" "rb:green:power" "1" ++ ucidef_set_led_netdev "lan" "LAN" "rb:green:eth" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "rb:green:wlan" "phy0tpt" ++ ;; ++rb-wap-2nd) ++ ucidef_set_led_timer "user" "USER" "rb:green:user" "1000" "1000" ++ ucidef_set_led_wlan "wlan" "WLAN" "rb:green:wlan" "phy0tpt" ++ ;; ++rb-wapr-2nd) ++ ucidef_set_led_wlan "wlan" "WLAN" "rb:green:user" "phy0tpt" ++ ;; ++re355|\ ++re450) ++ ucidef_set_led_netdev "lan_data" "LAN Data" "$board:green:lan_data" "eth0" "tx rx" ++ ucidef_set_led_netdev "lan_link" "LAN Link" "$board:green:lan_link" "eth0" "link" ++ ucidef_set_led_wlan "wlan2g" "WLAN 2.4 GHz" "$board:blue:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN 5 GHz" "$board:blue:wlan5g" "phy0tpt" ++ ;; ++rme-eg200) ++ ucidef_set_led_netdev "wan" "WAN" "eg200:red:eth0" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "eg200:red:wlan" "phy0tpt" ++ ucidef_set_led_oneshot "modbus" "Modbus" "eg200:red:modbus" "100" "33" ++ ucidef_set_led_default "etactica" "etactica" "eg200:red:etactica" "ignore" ++ ;; ++rocket-m-ti) ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssiverylow" "RSSIVERYLOW" "ubnt:green:link1" "wlan0" "1" "100" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "ubnt:green:link2" "wlan0" "18" "100" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "ubnt:green:link3" "wlan0" "34" "100" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "ubnt:green:link4" "wlan0" "51" "100" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "ubnt:green:link5" "wlan0" "67" "100" ++ ucidef_set_led_rssi "rssiveryhigh" "RSSIVERYHIGH" "ubnt:green:link6" "wlan0" "84" "100" ++ ;; ++rut900) ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "$board:green:lan1" "switch0" "0x10" ++ ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x04" ++ ;; ++smart-300) ++ ucidef_set_led_netdev "wan" "WAN" "nc-link:green:wan" "eth0" ++ ucidef_set_led_switch "lan1" "LAN1" "nc-link:green:lan1" "switch0" "0x04" ++ ucidef_set_led_switch "lan2" "LAN2" "nc-link:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "nc-link:green:lan3" "switch0" "0x10" ++ ucidef_set_led_switch "lan4" "LAN4" "nc-link:green:lan4" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "nc-link:green:wlan" "phy0tpt" ++ ;; ++som9331) ++ ucidef_set_led_netdev "wan" "WAN" "$board:orange:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "$board:orange:lan1" "switch0" "0x08" ++ ucidef_set_led_switch "lan2" "LAN2" "$board:orange:lan2" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:red:wlan" "phy0tpt" ++ ucidef_set_led_usbport "usb" "USB" "$board:green:system" "usb1-port1" ++ ;; ++sr3200) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:green:wlan2g" "phy1tpt" ++ ;; ++tellstick-znet-lite) ++ ucidef_set_led_netdev "lan_act" "LANACT" "tellstick:green:lan" "eth0" "tx rx" ++ ucidef_set_led_netdev "lan_link" "LANLINK" "tellstick:orange:lan" "eth0" "link" ++ ;; ++tew-712br) ++ ucidef_set_led_netdev "wan" "WAN" "trendnet:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "trendnet:green:lan1" "switch0" "0x02" ++ ucidef_set_led_switch "lan2" "LAN2" "trendnet:green:lan2" "switch0" "0x04" ++ ucidef_set_led_switch "lan3" "LAN3" "trendnet:green:lan3" "switch0" "0x08" ++ ucidef_set_led_switch "lan4" "LAN4" "trendnet:green:lan4" "switch0" "0x10" ++ ucidef_set_led_wlan "wlan" "WLAN" "trendnet:green:wlan" "phy0tpt" ++ ;; ++tew-732br) ++ ucidef_set_led_netdev "wan" "WAN" "trendnet:green:wan" "eth1" ++ ;; ++tew-823dru) ++ ucidef_set_led_netdev "wan" "WAN" "trendnet:green:planet" "eth0" ++ ;; ++tl-mr11u|\ ++tl-mr3020|\ ++tl-mr3040|\ ++tl-mr3040-v2) ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:3g" "usb1-port1" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth0" ++ ;; ++tl-mr3220|\ ++tl-mr3420) ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:3g" "usb1-port1" ++ ;; ++tl-mr3220-v2|\ ++tl-wr741nd-v4) ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x04" ++ ucidef_set_led_switch "lan2" "LAN2" "tp-link:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "tp-link:green:lan3" "switch0" "0x10" ++ ucidef_set_led_switch "lan4" "LAN4" "tp-link:green:lan4" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ++ case "$board" in ++ tl-mr3220-v2) ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:3g" "usb1-port1" ++ ;; ++ esac ++ ;; ++tl-mr3420-v2|\ ++tl-wr841n-v8|\ ++tl-wr842n-v2|\ ++tl-wr941nd-v5) ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:green:wan" "eth0" ++ ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x04" ++ ucidef_set_led_switch "lan2" "LAN2" "tp-link:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "tp-link:green:lan3" "switch0" "0x10" ++ ucidef_set_led_switch "lan4" "LAN4" "tp-link:green:lan4" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ++ case "$board" in ++ tl-mr3420-v2|\ ++ tl-wr842n-v2) ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:3g" "usb1-port1" ++ ;; ++ esac ++ ;; ++tl-mr6400) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:white:lan" "eth0" ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:white:wan" "eth1" ++ ucidef_set_led_netdev "4g" "4G" "tp-link:white:4g" "usb0" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:white:wlan" "phy0tpt" ++ ;; ++tl-wa7210n-v2) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth0" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:green:signal1" "wlan0" "1" "100" "0" "13" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:green:signal2" "wlan0" "26" "100" "-25" "13" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:signal3" "wlan0" "51" "100" "-50" "13" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:signal4" "wlan0" "76" "100" "-75" "13" ++ ;; ++tl-wa750re) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:orange:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:orange:wlan" "phy0tpt" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:orange:signal1" "wlan0" "1" "100" "0" "13" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:orange:signal2" "wlan0" "20" "100" "-19" "13" ++ ucidef_set_led_rssi "rssimedium" "RSSIMEDIUM" "tp-link:orange:signal3" "wlan0" "40" "100" "-39" "13" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:orange:signal4" "wlan0" "60" "100" "-59" "13" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:orange:signal5" "wlan0" "80" "100" "-79" "13" ++ ;; ++tl-wa801nd-v3) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth1" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ;; ++tl-wa850re|\ ++tl-wa850re-v2) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:blue:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:blue:wlan" "phy0tpt" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:blue:signal1" "wlan0" "1" "100" "0" "13" ++ ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:blue:signal2" "wlan0" "20" "100" "-19" "13" ++ ucidef_set_led_rssi "rssimedium" "RSSIMEDIUM" "tp-link:blue:signal3" "wlan0" "40" "100" "-39" "13" ++ ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:blue:signal4" "wlan0" "60" "100" "-59" "13" ++ ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:blue:signal5" "wlan0" "80" "100" "-79" "13" ++ ;; ++tl-wa701nd-v2|\ ++tl-wa801nd-v2|\ ++tl-wa830re-v2|\ ++tl-wa860re|\ ++tl-wa901nd-v3|\ ++tl-wa901nd-v4|\ ++tl-wa901nd-v5) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ;; ++tl-wa901nd) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth0" ++ ;; ++tl-wa901nd-v2|\ ++tl-wr941nd|\ ++tl-wr1041n-v2) ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ;; ++tl-wdr3320-v2) ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "tp-link:green:wlan5g" "phy0tpt" ++ ;; ++tl-wdr3500) ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:usb" "usb1-port1" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:green:wlan2g" "phy0tpt" ++ ;; ++tl-wdr4300) ++ ucidef_set_led_usbport "usb1" "USB1" "tp-link:green:usb1" "1-1-port1" ++ ucidef_set_led_usbport "usb2" "USB2" "tp-link:green:usb2" "1-1-port2" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:blue:wlan2g" "phy0tpt" ++ ;; ++tl-wdr4900-v2) ++ ucidef_set_led_usbport "usb1" "USB1" "tp-link:green:usb1" "usb1-port1" ++ ucidef_set_led_usbport "usb2" "USB2" "tp-link:green:usb2" "usb2-port1" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:blue:wlan2g" "phy0tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "tp-link:blue:wlan5g" "phy1tpt" ++ ;; ++tl-wdr6500-v2|\ ++tl-wr741nd) ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x02" ++ ucidef_set_led_switch "lan2" "LAN2" "tp-link:green:lan2" "switch0" "0x04" ++ ucidef_set_led_switch "lan3" "LAN3" "tp-link:green:lan3" "switch0" "0x08" ++ ucidef_set_led_switch "lan4" "LAN4" "tp-link:green:lan4" "switch0" "0x10" ++ ;; ++tl-wpa8630) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ucidef_set_led_netdev "wlan" "WLAN" "$board:green:wlan" "wlan1" ++ ucidef_set_led_netdev "wlan5" "WLAN5" "$board:green:wlan5" "wlan0" ++ ;; ++tl-wr740n-v6|\ ++tl-wr841n-v9|\ ++tl-wr841n-v11|\ ++tl-wr842n-v3) ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10" ++ ucidef_set_led_switch "lan2" "LAN2" "tp-link:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "tp-link:green:lan3" "switch0" "0x04" ++ ucidef_set_led_switch "lan4" "LAN4" "tp-link:green:lan4" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ++ case "$board" in ++ tl-wr842n-v3) ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:3g" "usb1-port1" ++ ;; ++ esac ++ ;; ++tl-wr802n-v1) ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:blue:system" "phy0tpt" ++ ;; ++tl-wr802n-v2) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:system" "phy0tpt" ++ ;; ++tl-wr902ac-v1) ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" ++ ucidef_set_led_usbport "usb" "USB" "$board:green:usb" "usb1-port1" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:green:wlan2g" "phy1tpt" ++ ;; ++tl-wr940n-v4|\ ++tl-wr941nd-v6) ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:blue:wan" "eth0" ++ ucidef_set_led_switch "lan1" "LAN1" "tp-link:blue:lan1" "switch0" "0x10" ++ ucidef_set_led_switch "lan2" "LAN2" "tp-link:blue:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "tp-link:blue:lan3" "switch0" "0x04" ++ ucidef_set_led_switch "lan4" "LAN4" "tp-link:blue:lan4" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:blue:wlan" "phy0tpt" ++ ;; ++tl-wr840n-v2|\ ++tl-wr840n-v3) ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:green:wan" "eth1" ++ ucidef_set_led_switch "lan" "LAN" "tp-link:green:lan" "switch0" "0x1E" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ;; ++tl-wr940n-v6) ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:blue:wan" "eth0" ++ ;; ++tl-wr942n-v1) ++ ucidef_set_led_switch "lan1" "LAN1" "$board:green:lan1" "switch0" "0x04" ++ ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x10" ++ ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x02" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ucidef_set_led_usbport "usb1" "USB1" "$board:green:usb1" "1-1-port2" ++ ucidef_set_led_usbport "usb2" "USB2" "$board:green:usb2" "1-1-port1" ++ ;; ++tl-wr1043nd|\ ++tl-wr1043nd-v2) ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:usb" "usb1-port1" ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ;; ++tl-wr1043n-v5|\ ++tl-wr1043nd-v4) ++ ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" ++ ucidef_set_led_switch "wan" "WAN" "tp-link:green:wan" "switch0" "0x20" ++ ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10" ++ ucidef_set_led_switch "lan2" "LAN2" "tp-link:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "tp-link:green:lan3" "switch0" "0x04" ++ ucidef_set_led_switch "lan4" "LAN4" "tp-link:green:lan4" "switch0" "0x02" ++ ++ case "$board" in ++ tl-wr1043nd-v4) ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:usb" "usb1-port1" ++ ;; ++ esac ++ ;; ++tl-wr2543n) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:green:wlan2g" "phy0tpt" ++ ucidef_set_led_usbport "usb" "USB" "tp-link:green:usb" "usb1-port1" ++ ;; ++tube2h) ++ ucidef_set_led_netdev "lan" "LAN" "alfa:blue:lan" "eth0" ++ ucidef_set_rssimon "wlan0" "200000" "1" ++ ucidef_set_led_rssi "signal1" "SIGNAL1" "alfa:red:signal1" "wlan0" "1" "100" "0" "13" ++ ucidef_set_led_rssi "signal2" "SIGNAL2" "alfa:orange:signal2" "wlan0" "26" "100" "-25" "13" ++ ucidef_set_led_rssi "signal3" "SIGNAL3" "alfa:green:signal3" "wlan0" "51" "100" "-50" "13" ++ ucidef_set_led_rssi "signal4" "SIGNAL4" "alfa:green:signal4" "wlan0" "76" "100" "-75" "13" ++ ;; ++wam250) ++ ucidef_set_led_netdev "lan" "LAN" "$board:white:lan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:white:wlan" "phy0tpt" ++ ;; ++wndap360) ++ ucidef_set_led_power "power" "POWER GREEN" "netgear:green:power" "1" ++ ;; ++wndr3700) ++ ucidef_set_led_default "wan" "WAN LED (green)" "netgear:green:wan" "0" ++ ucidef_set_led_usbport "usb" "USB" "netgear:green:usb" "usb1-port1" ++ ;; ++wi2a-ac200i) ++ ucidef_set_led_default "power" "Power (green)" "nokia:green:power" "1" ++ ucidef_set_led_default "wan" "Ethernet LED (green)" "nokia:green:wan" "1" ++ ucidef_set_led_wlan "wlan5g" "WLAN" "nokia:green:wlan-5g" "phy0tpt" ++ ucidef_set_led_wlan "wlan2g" "WLAN" "nokia:green:wlan-2g" "phy1tpt" ++ ;; ++wndr3700v4|\ ++wndr4300) ++ ucidef_set_led_switch "wan-amber" "WAN (amber)" "netgear:amber:wan" "switch0" "0x20" ++ ucidef_set_led_usbport "usb" "USB" "netgear:green:usb" "usb1-port1" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "netgear:green:wlan2g" "phy0tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "netgear:blue:wlan5g" "phy1tpt" ++ ;; ++whr-g301n|\ ++whr-hp-g300n|\ ++whr-hp-gn) ++ ucidef_set_led_netdev "wan" "WAN" "buffalo:green:wan" "eth1" ++ ucidef_set_led_switch "lan1" "LAN1" "buffalo:green:lan1" "switch0" "0x02" ++ ucidef_set_led_switch "lan2" "LAN2" "buffalo:green:lan2" "switch0" "0x04" ++ ucidef_set_led_switch "lan3" "LAN3" "buffalo:green:lan3" "switch0" "0x08" ++ ucidef_set_led_switch "lan4" "LAN4" "buffalo:green:lan4" "switch0" "0x10" ++ ;; ++wifi-pineapple-nano) ++ ucidef_set_led_wlan "wlan0" "WLAN0" "$board:blue:system" "phy0tpt" ++ ;; ++wlae-ag300n) ++ ucidef_set_led_netdev "wireless" "WIRELESS" "buffalo:green:wireless" "wlan0" ++ ;; ++wnr1000-v2|\ ++wnr2000-v3) ++ ucidef_set_led_netdev "wan-amber" "WAN (amber)" "netgear:amber:wan" "eth0" ++ ucidef_set_led_default "wan-green" "WAN (green)" "netgear:green:wan" "0" ++ ucidef_set_led_wlan "wlan" "WLAN" "netgear:blue:wlan" "phy0tpt" ++ ucidef_set_led_switch "lan1green" "LAN1 (green)" "netgear:green:lan1" "switch0" "0x02" "0x04" ++ ucidef_set_led_switch "lan2green" "LAN2 (green)" "netgear:green:lan2" "switch0" "0x04" "0x04" ++ ucidef_set_led_switch "lan3green" "LAN3 (green)" "netgear:green:lan3" "switch0" "0x08" "0x04" ++ ucidef_set_led_switch "lan4green" "LAN4 (green)" "netgear:green:lan4" "switch0" "0x10" "0x04" ++ ucidef_set_led_switch "lan1amber" "LAN1 (amber)" "netgear:amber:lan1" "switch0" "0x02" "0x02" ++ ucidef_set_led_switch "lan2amber" "LAN2 (amber)" "netgear:amber:lan2" "switch0" "0x04" "0x02" ++ ucidef_set_led_switch "lan3amber" "LAN3 (amber)" "netgear:amber:lan3" "switch0" "0x08" "0x02" ++ ucidef_set_led_switch "lan4amber" "LAN4 (amber)" "netgear:amber:lan4" "switch0" "0x10" "0x02" ++ ;; ++wnr2000-v4) ++ ucidef_set_led_netdev "wan" "WAN" "netgear:green:wan" "eth0" ++ ucidef_set_led_netdev "wlan" "WLAN" "netgear:blue:wlan" "wlan0" ++ ucidef_set_led_switch "lan1" "LAN1" "netgear:amber:lan1" "switch0" "0x02" ++ ucidef_set_led_switch "lan2" "LAN2" "netgear:amber:lan2" "switch0" "0x04" ++ ucidef_set_led_switch "lan3" "LAN3" "netgear:amber:lan3" "switch0" "0x08" ++ ucidef_set_led_switch "lan4" "LAN4" "netgear:amber:lan4" "switch0" "0x10" ++ ucidef_set_led_usbport "usb" "USB" "netgear:amber:status" "usb1-port1" ++ ;; ++wnr2200) ++ ucidef_set_led_netdev "wan-amber" "WAN (amber)" "netgear:amber:wan" "eth0" ++ ucidef_set_led_default "wan-green" "WAN (green)" "netgear:green:wan" "0" ++ ucidef_set_led_wlan "wlan" "WLAN" "netgear:blue:wlan" "phy0tpt" ++ ucidef_set_led_switch "lan1green" "LAN1 (green)" "netgear:green:lan1" "switch0" "0x02" "0x04" ++ ucidef_set_led_switch "lan2green" "LAN2 (green)" "netgear:green:lan2" "switch0" "0x04" "0x04" ++ ucidef_set_led_switch "lan3green" "LAN3 (green)" "netgear:green:lan3" "switch0" "0x08" "0x04" ++ ucidef_set_led_switch "lan4green" "LAN4 (green)" "netgear:green:lan4" "switch0" "0x10" "0x04" ++ ucidef_set_led_switch "lan1amber" "LAN1 (amber)" "netgear:amber:lan1" "switch0" "0x02" "0x02" ++ ucidef_set_led_switch "lan2amber" "LAN2 (amber)" "netgear:amber:lan2" "switch0" "0x04" "0x02" ++ ucidef_set_led_switch "lan3amber" "LAN3 (amber)" "netgear:amber:lan3" "switch0" "0x08" "0x02" ++ ucidef_set_led_switch "lan4amber" "LAN4 (amber)" "netgear:amber:lan4" "switch0" "0x10" "0x02" ++ ucidef_set_led_usbport "usb" "USB" "netgear:green:usb" "usb1-port1" ++ ;; ++wnr612-v2) ++ ucidef_set_led_netdev "wan" "WAN" "netgear:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "netgear:green:wlan" "phy0tpt" ++ ucidef_set_led_switch "lan1" "LAN1" "netgear:green:lan1" "switch0" "0x02" "0x0f" ++ ucidef_set_led_switch "lan2" "LAN2" "netgear:green:lan2" "switch0" "0x04" "0x0f" ++ ;; ++wpn824n) ++ ucidef_set_led_netdev "wan-amber" "WAN (amber)" "netgear:amber:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "netgear:blue:wlan" "phy0tpt" ++ ucidef_set_led_switch "lan1amber" "LAN1 (amber)" "netgear:amber:lan1" "switch0" "0x02" ++ ucidef_set_led_switch "lan2amber" "LAN2 (amber)" "netgear:amber:lan2" "switch0" "0x04" ++ ucidef_set_led_switch "lan3amber" "LAN3 (amber)" "netgear:amber:lan3" "switch0" "0x08" ++ ucidef_set_led_switch "lan4amber" "LAN4 (amber)" "netgear:amber:lan4" "switch0" "0x10" ++ ucidef_set_led_default "lan1green" "LAN1 (green)" "netgear:green:lan1" "0" ++ ucidef_set_led_default "lan2green" "LAN2 (green)" "netgear:green:lan2" "0" ++ ucidef_set_led_default "lan3green" "LAN3 (green)" "netgear:green:lan3" "0" ++ ucidef_set_led_default "lan4green" "LAN4 (green)" "netgear:green:lan4" "0" ++ ucidef_set_led_default "wan-green" "WAN (green)" "netgear:green:wan" "0" ++ ucidef_set_led_default "wps1" "WPS1" "netgear:blue:wps1" "0" ++ ucidef_set_led_default "wps2" "WPS2" "netgear:blue:wps2" "0" ++ ucidef_set_led_default "status" "STATUS" "netgear:amber:status" "0" ++ ucidef_set_led_default "test" "TEST" "netgear:amber:test" "0" ++ ;; ++wzr-hp-ag300h) ++ ucidef_set_led_default "diag" "DIAG" "buffalo:red:diag" "0" ++ ucidef_set_led_netdev "router" "ROUTER" "buffalo:green:router" "eth1" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "buffalo:amber:band2g" "phy0tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "buffalo:amber:band5g" "phy1tpt" ++ ucidef_set_led_usbport "usb" "USB" "buffalo:green:usb" "usb1-port1" ++ ;; ++wzr-hp-g300nh) ++ ucidef_set_led_wlan "wlan" "Wireless" "buffalo:green:wireless" "phy0tpt" ++ ucidef_set_led_netdev "router" "Router" "buffalo:green:router" "eth1" ++ ucidef_set_led_usbport "usb" "USB" "buffalo:blue:usb" "usb1-port1" ++ ;; ++wzr-hp-g300nh2|\ ++wzr-hp-g450h) ++ ucidef_set_led_wlan "wlan" "Wireless" "buffalo:green:wireless" "phy0tpt" ++ ;; ++xd3200) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:blue:wlan2g" "phy1tpt" ++ ;; ++z1) ++ ucidef_set_led_netdev "wlan1" "WLAN1" "$board:blue:tricolor0" "wlan1" ++ ;; ++zcn-1523h-2) ++ ucidef_set_led_netdev "lan1" "lan1" "zcn-1523h:green:lan1" "eth0" ++ ;; ++zcn-1523h-5) ++ ucidef_set_led_netdev "lan1" "lan1" "zcn-1523h:green:lan1" "eth0" ++ ucidef_set_led_netdev "lan2" "lan2" "zcn-1523h:green:lan2" "eth1" ++ ;; ++esac ++ ++board_config_flush ++ ++exit 0 +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +new file mode 100755 +index 0000000000..e38f06b88d +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -0,0 +1,711 @@ ++#!/bin/sh ++# ++# Copyright (C) 2011-2015 OpenWrt.org ++# ++ ++. /lib/functions/system.sh ++. /lib/functions/uci-defaults.sh ++ ++ar71xx_setup_interfaces() ++{ ++ local board="$1" ++ ++ case "$board" in ++ airgatewaypro) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "4:lan" "5:wan" ++ ;; ++ airrouter|\ ++ ap121|\ ++ ap121-mini|\ ++ ap96|\ ++ dir-600-a1|\ ++ dir-615-c1|\ ++ dir-615-e1|\ ++ dir-615-e4|\ ++ hiwifi-hc6361|\ ++ ja76pf|\ ++ mc-mac1200r|\ ++ minibox-v1|\ ++ mynet-n600|\ ++ oolite-v1|\ ++ oolite-v5.2|\ ++ oolite-v5.2-dev|\ ++ qihoo-c301|\ ++ r602n|\ ++ rb-750|\ ++ rb-751|\ ++ som9331|\ ++ t830|\ ++ tew-632brp|\ ++ tew-712br|\ ++ tew-732br|\ ++ tl-mr3220|\ ++ tl-mr3420|\ ++ tl-wdr3320-v2|\ ++ tl-wdr3500|\ ++ tl-wr740n-v6|\ ++ tl-wr840n-v2|\ ++ tl-wr840n-v3|\ ++ tl-wr841n-v11|\ ++ tl-wr841n-v9|\ ++ tl-wr842n-v3|\ ++ whr-g301n|\ ++ whr-hp-g300n|\ ++ whr-hp-gn|\ ++ wzr-hp-ag300h|\ ++ zbt-we1526) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" ++ ;; ++ alfa-ap120c|\ ++ all0305|\ ++ antminer-s1|\ ++ antminer-s3|\ ++ antrouter-r1|\ ++ ap121f|\ ++ ap91-5g|\ ++ aw-nr580|\ ++ bullet-m|\ ++ bullet-m-xw|\ ++ c-55|\ ++ cap324|\ ++ cap4200ag|\ ++ cf-e380ac-v1|\ ++ cf-e380ac-v2|\ ++ cpe210-v2|\ ++ cpe210-v3|\ ++ cpe510-v2|\ ++ dr342|\ ++ eap120|\ ++ eap300v2|\ ++ eap7660d|\ ++ el-mini|\ ++ fritz300e|\ ++ fritz450e|\ ++ gl-usb150|\ ++ hiveap-121|\ ++ koala|\ ++ lbe-m5|\ ++ loco-m-xw|\ ++ mr12|\ ++ mr16|\ ++ mr1750|\ ++ mr1750v2|\ ++ mr18|\ ++ mr600|\ ++ mr600v2|\ ++ mr900|\ ++ mr900v2|\ ++ mynet-rext|\ ++ pqi-air-pen|\ ++ rb-411|\ ++ rb-411u|\ ++ rb-911-2hn|\ ++ rb-911-5hn|\ ++ rb-911g-2hpnd|\ ++ rb-911g-5hpacd|\ ++ rb-911g-5hpnd|\ ++ rb-912uag-2hpnd|\ ++ rb-912uag-5hpnd|\ ++ rb-921gs-5hpacd-r2|\ ++ rb-922uags-5hpacd|\ ++ rb-lhg-5nd|\ ++ rb-mapl-2nd|\ ++ rb-sxt2n|\ ++ rb-sxt-2nd-r3|\ ++ rb-sxt5n|\ ++ rb-wap-2nd|\ ++ rb-wapr-2nd|\ ++ rb-wapg-5hact2hnd|\ ++ re355|\ ++ re450|\ ++ rocket-m-xw|\ ++ sc300m |\ ++ tl-mr10u|\ ++ tl-mr11u|\ ++ tl-mr12u|\ ++ tl-mr13u|\ ++ tl-mr3020|\ ++ tl-mr3040|\ ++ tl-mr3040-v2|\ ++ tl-wa701nd-v2|\ ++ tl-wa7210n-v2|\ ++ tl-wa750re|\ ++ tl-wa801nd-v2|\ ++ tl-wa830re-v2|\ ++ tl-wa850re|\ ++ tl-wa850re-v2|\ ++ tl-wa855re-v1|\ ++ tl-wa901nd|\ ++ tl-wa901nd-v2|\ ++ tl-wa901nd-v3|\ ++ tl-wa901nd-v4|\ ++ tl-wa901nd-v5|\ ++ tl-wr703n|\ ++ tl-wr802n-v1|\ ++ tl-wr802n-v2|\ ++ tl-wr902ac-v1|\ ++ ts-d084|\ ++ tube2h|\ ++ unifi|\ ++ unifiac-lite|\ ++ wi2a-ac200i|\ ++ wifi-pineapple-nano|\ ++ wndap360|\ ++ wp543) ++ ucidef_set_interface_wan "eth0" ++ ;; ++ a40|\ ++ a60|\ ++ alfa-ap96|\ ++ alfa-nx|\ ++ dr344|\ ++ gl-ar150|\ ++ gl-ar300m|\ ++ gl-domino|\ ++ gl-inet|\ ++ gl-mifi|\ ++ jwap003|\ ++ om2p-hsv4|\ ++ om2pv4|\ ++ pb42|\ ++ pb44|\ ++ rb-951ui-2hnd|\ ++ routerstation|\ ++ tl-wr710n|\ ++ tl-wr720n-v3|\ ++ tl-wr810n|\ ++ tl-wr810n-v2|\ ++ wpe72|\ ++ wrtnode2q) ++ ucidef_set_interfaces_lan_wan "eth1" "eth0" ++ ;; ++ all0258n|\ ++ all0315n|\ ++ dlan-hotspot|\ ++ dlan-pro-500-wp|\ ++ ja76pf2|\ ++ rocket-m-ti|\ ++ ubnt-unifi-outdoor) ++ ucidef_set_interface_lan "eth0 eth1" ++ ;; ++ wzr-hp-g300nh2) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:1" "3:lan:2" "4:lan:3" "5:lan:4" "2:wan" ++ ;; ++ ap132|\ ++ ap136|\ ++ ap152|\ ++ rb-750gl|\ ++ rb-751g|\ ++ rb-951g-2hnd|\ ++ rb-962uigs-5hact2hnt|\ ++ wlr8100|\ ++ wzr-hp-g450h) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan" "3:lan" "4:lan" "5:lan" "1:wan" ++ ;; ++ ap135-020|\ ++ ap136-020|\ ++ bhr-4grv2|\ ++ tew-823dru|\ ++ tl-wr1043nd-v2|\ ++ wzr-450hp2) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0.2" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "5:wan" "6@eth0" ++ ;; ++ ap136-010|\ ++ ap147-010|\ ++ nbg6616|\ ++ nbg6716) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1.2" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" "6@eth1" ++ ;; ++ ap143|\ ++ rb-433|\ ++ rb-433u) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "1:lan" "2:lan" "5@eth1" ++ ;; ++ archer-c5|\ ++ archer-c7|\ ++ tl-wdr4900-v2) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0.2" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "2:lan" "3:lan" "4:lan" "5:lan" "6@eth0" "1:wan" ++ ;; ++ archer-c25-v1|\ ++ archer-c60-v1|\ ++ archer-c60-v2|\ ++ rb-750-r2|\ ++ rb-750p-pbr2|\ ++ rb-750up-r2|\ ++ rb-951ui-2nd|\ ++ rb-952ui-5ac2nd) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" ++ ;; ++ archer-c58-v1|\ ++ archer-c59-v1|\ ++ archer-c59-v2|\ ++ fritz4020|\ ++ rb-450g) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2" ++ ;; ++ arduino-yun|\ ++ dir-505-a1|\ ++ tl-wa801nd-v3) ++ ucidef_set_interface_lan "eth1" ++ ;; ++ bsb) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan" "3:lan" ++ ;; ++ c-60) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "3:wan" "4:lan" ++ ;; ++ rme-eg200) ++ ucidef_set_interface_lan "eth0" "dhcp" ++ ;; ++ cf-e375ac|\ ++ rb-map-2nd) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:wan" "2:lan" ++ ;; ++ cf-e385ac) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1.2" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan" "1:wan" "6@eth1" ++ ;; ++ cpe210|\ ++ cpe510|\ ++ wbs210|\ ++ wbs510) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "5:lan" "4:wan" ++ ;; ++ cr3000) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2" ++ ;; ++ cr5000|\ ++ dgl-5500-a1|\ ++ dhp-1565-a1|\ ++ dir-825-c1|\ ++ dir-835-a1|\ ++ esr900|\ ++ mynet-n750|\ ++ sr3200) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" ++ ;; ++ tl-wr1043n-v5) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "5:wan" ++ ;; ++ dap-2695-a1) ++ ucidef_add_switch "switch0" "0@eth0" "2:lan" "3:wan" "6@eth1" ++ ;; ++ rb-931-2nd) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:3" "2:lan:2" "3:wan:1" ++ ;; ++ rb-941-2nd) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:wan:1" ++ ;; ++ db120|\ ++ rb-2011il|\ ++ rb-2011ils|\ ++ rb-2011l|\ ++ rb-2011uas|\ ++ rb-2011uas-2hnd|\ ++ rb-2011uias|\ ++ rb-2011uias-2hnd|\ ++ rb-2011uias-2hnd-r2) ++ case "$board" in ++ rb-2011ils|\ ++ rb-2011uas*|\ ++ rb-2011uias|\ ++ rb-2011uias-2hnd|\ ++ rb-2011uias-2hnd-r2) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan" "3:lan" "4:lan" "5:lan" "1:wan" "6:sfp" ++ ;; ++ *) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan" "3:lan" "4:lan" "5:lan" "1:wan" ++ ;; ++ esac ++ ++ ucidef_add_switch "switch1" \ ++ "0@eth1" "1:lan" "2:lan" "3:lan" "4:lan" "5:lan" ++ ;; ++ dir-615-i1|\ ++ omy-g1|\ ++ r6100|\ ++ smart-300|\ ++ tl-wdr6500-v2|\ ++ tl-wr940n-v4|\ ++ tl-wr940n-v6|\ ++ tl-wr941nd-v6|\ ++ wnr1000-v2|\ ++ wnr2000-v4|\ ++ wnr2200|\ ++ wnr612-v2|\ ++ wpn824n) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan:1" "2:lan:2" "3:lan:3" "4:lan:4" ++ ;; ++ tl-mr6400) ++ ucidef_set_interfaces_lan_wan "eth0.1 eth1" "usb0" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan" "2:lan" "3:lan" ++ ;; ++ dir-825-b1|\ ++ nbg460n_550n_550nh|\ ++ tew-673gru|\ ++ wzr-hp-g300nh) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0:lan" "1:lan" "2:lan" "3:lan" "5@eth0" ++ ;; ++ dlan-pro-1200-ac) ++ ucidef_set_interface_lan "eth0" ++ ucidef_add_switch "switch0" \ ++ "0u@eth0" "2:lan" "3:lan" "4:lan" ++ ucidef_add_switch_attr "switch0" "enable" "false" ++ ;; ++ e1700ac-v2|\ ++ e750g-v8|\ ++ unifiac-pro|\ ++ xd3200) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan" "3:wan" ++ ;; ++ e558-v2) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0.2" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "4:lan" "5:lan" "6@eth0" "3:wan" ++ ;; ++ ebr-2310-c1) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:1" "2:lan:2" "3:lan:3" "4:lan:4" ++ ;; ++ el-m150) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0:lan" "1:lan" "3@eth1" ++ ;; ++ dir-869-a1|\ ++ epg5000|\ ++ esr1750|\ ++ tl-wr1043nd-v4|\ ++ wndr3700v4|\ ++ wndr4300) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "5:wan" ++ ;; ++ ew-balin) ++ ucidef_set_interface "usb2" ifname "usb0" protocol "static" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "5:lan:4" "4:lan:5" "3:wan" ++ ;; ++ ew-dorin) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan" "2:lan" "3:wan" ++ ;; ++ ew-dorin-router) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan" "3:lan" ++ ;; ++ dw33d|\ ++ f9k1115v2) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0.2" ++ ucidef_add_switch "switch0" \ ++ "2:lan" "3:lan" "4:lan" "5:lan" "6@eth1" "0@eth0" "1:wan" ++ ;; ++ gl-ar300|\ ++ wnr2000-v3) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan" "2:lan" "3:lan" "4:lan" ++ ;; ++ gl-ar750|\ ++ rb-435g) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan" "2:lan" ++ ;; ++ gl-ar750s) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan:2" "3:lan:1" "1:wan" ++ ;; ++ jwap230) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1.2" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan" "5:wan" "6@eth1" ++ ;; ++ nanostation-m-xw) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "5:lan" "1:wan" ++ ;; ++ onion-omega) ++ ucidef_set_interface_lan "wlan0" ++ ;; ++ rb-450) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "5@eth1" ++ ;; ++ routerstation-pro) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "2:lan:3" "3:lan:2" "4:lan:1" ++ ;; ++ rb-493g) ++ ucidef_set_interfaces_lan_wan "eth0.1 eth1.1" "eth1.2" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:4" "2:lan:1" "3:lan:2" "4:lan:3" ++ ucidef_add_switch "switch1" \ ++ "0@eth1" "1:lan:4" "2:lan:1" "3:lan:3" "4:lan:2" "5:wan" ++ ;; ++ rut900) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan:3" "3:lan:2" "4:lan:1" ++ ;; ++ tellstick-znet-lite) ++ ucidef_set_interface_wan "eth0" ++ ucidef_set_interface "wlan" ifname "wlan0" protocol "dhcp" ++ ;; ++ tl-mr3420-v2|\ ++ tl-wr841n-v8|\ ++ tl-wr842n-v2|\ ++ tl-wr941nd-v5|\ ++ tl-wr942n-v1) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan:4" "2:lan:1" "3:lan:2" "4:lan:3" ++ ;; ++ archer-c7-v4|\ ++ archer-c7-v5|\ ++ tl-wdr4300|\ ++ tl-wr1041n-v2) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "5:lan:4" "1:wan" ++ ;; ++ tl-wpa8630) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan:3" "3:lan:2" "4:lan:1" "5:lan:4" ++ ;; ++ tl-wr1043nd) ++ ucidef_add_switch "switch0" \ ++ "1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "5@eth0" ++ ;; ++ tl-wr2543n) ++ ucidef_add_switch "switch0" \ ++ "1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "9@eth0" ++ ;; ++ tl-mr3220-v2|\ ++ tl-wr741nd-v4) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:4" "2:lan:1" "3:lan:2" "4:lan:3" ++ ;; ++ tl-wr841n-v1|\ ++ tl-wr941nd) ++ ucidef_set_interface "eth" ifname "eth0" ++ ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ++ ;; ++ tl-wr741nd|\ ++ tl-wr841n-v7) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:1" "2:lan:2" "3:lan:3" "4:lan:4" ++ ;; ++ uap-pro|\ ++ wpj342) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan" "2:wan" ++ ;; ++ wndr3700|\ ++ wndr3700v2|\ ++ wndr3800|\ ++ wndr3800ch) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "5@eth0" ++ ++ ucidef_add_switch_attr "switch0" "blinkrate" 2 ++ ucidef_add_switch_port_attr "switch0" 1 led 6 ++ ucidef_add_switch_port_attr "switch0" 2 led 9 ++ ucidef_add_switch_port_attr "switch0" 5 led 2 ++ ;; ++ wpj344) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "3:lan" "2:wan" ++ ;; ++ wpj558) ++ ucidef_add_switch "switch0" \ ++ "5:lan" "1:wan" "6@eth0" ++ ;; ++ wpj563) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan" "3:wan" ++ ;; ++ wrt160nl) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "4@eth0" ++ ;; ++ wzr-hp-g450h) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan:1 3:lan:2 4:lan:3 5:lan:4" "1:wan" ++ ;; ++ z1) ++ ucidef_set_interfaces_lan_wan "eth0.1" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "1:lan:1" "2:lan:2" "3:lan:3" "4:lan:4" "5:wan" ++ ;; ++ ens202ext) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth1.2" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "2:lan:1" "3:lan:2" "4:lan:3" "5:lan:4" "1:wan" ++ ;; ++ *) ++ ucidef_set_interfaces_lan_wan "eth0" "eth1" ++ ;; ++ esac ++} ++ ++ar71xx_setup_macs() ++{ ++ local board="$1" ++ local lan_mac="" ++ local wan_mac="" ++ ++ case $board in ++ archer-c7-v4) ++ base_mac=$(mtd_get_mac_binary config 0x8) ++ wan_mac=$(macaddr_add "$base_mac" 1) ++ ;; ++ archer-c7-v5) ++ base_mac=$(mtd_get_mac_binary info 0x8) ++ wan_mac=$(macaddr_add "$base_mac" 1) ++ ;; ++ dgl-5500-a1|\ ++ dir-825-c1) ++ wan_mac=$(mtd_get_mac_ascii nvram "wan_mac") ++ ;; ++ dhp-1565-a1|\ ++ dir-835-a1|\ ++ wndr3700v4|\ ++ wndr4300) ++ lan_mac=$(mtd_get_mac_binary caldata 0x0) ++ wan_mac=$(mtd_get_mac_binary caldata 0x6) ++ ;; ++ dir-869-a1|\ ++ mynet-n750) ++ wan_mac=$(mtd_get_mac_ascii devdata "wanmac") ++ ;; ++ esr900) ++ wan_mac=$(mtd_get_mac_ascii u-boot-env "wanaddr") ++ ;; ++ fritz300e) ++ lan_mac=$(fritz_tffs -n maca -i $(find_mtd_part "tffs (1)")) ++ ;; ++ tl-wdr4300) ++ base_mac=$(mtd_get_mac_binary u-boot 0x1fc00) ++ wan_mac=$(macaddr_add "$base_mac" 1) ++ ;; ++ tl-wr1043n-v5|\ ++ tl-wr1043nd-v4) ++ lan_mac=$(mtd_get_mac_binary product-info 0x8) ++ wan_mac=$(macaddr_add "$lan_mac" 1) ++ ;; ++ wlr8100) ++ lan_mac=$(mtd_get_mac_ascii u-boot-env "ethaddr") ++ wan_mac=$(mtd_get_mac_ascii u-boot-env "wanaddr") ++ ;; ++ wpj344|\ ++ wpj558) ++ wan_mac=$(mtd_get_mac_binary u-boot 0x2e018) ++ ;; ++ esac ++ ++ [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac ++ [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac ++} ++ ++ar71xx_setup_ar8xxx_switch() ++{ ++ local board="$1" ++ ++ case $board in ++ ap147-010|\ ++ archer-c25-v1|\ ++ archer-c58-v1|\ ++ archer-c59-v1|\ ++ archer-c59-v2|\ ++ archer-c60-v1|\ ++ archer-c60-v2|\ ++ archer-c7-v4|\ ++ archer-c7-v5|\ ++ cf-e375ac|\ ++ cf-e385ac|\ ++ cr3000|\ ++ dhp-1565-a1|\ ++ mynet-n600|\ ++ rb-2011il|\ ++ rb-2011ils|\ ++ rb-2011l|\ ++ rb-2011uas|\ ++ rb-2011uas-2hnd|\ ++ rb-2011uias|\ ++ rb-2011uias-2hnd|\ ++ rb-2011uias-2hnd-r2|\ ++ rb-750|\ ++ rb-750p-pbr2|\ ++ rb-750-r2|\ ++ rb-750up-r2|\ ++ rb-951ui-2nd|\ ++ rb-952ui-5ac2nd|\ ++ rb-map-2nd|\ ++ tl-wr1043nd-v4|\ ++ tl-wr1043n-v5|\ ++ wndr3700v4|\ ++ wndr3700v4|\ ++ wndr4300|\ ++ wnr1000-v2|\ ++ wnr2000-v3|\ ++ wnr2200|\ ++ wnr612-v2|\ ++ wpn824n) ++ ucidef_set_ar8xxx_switch_mib "switch0" 0 500 ++ ;; ++ esac ++} ++ ++board_config_update ++board=$(board_name) ++ar71xx_setup_interfaces $board ++ar71xx_setup_macs $board ++ar71xx_setup_ar8xxx_switch $board ++board_config_flush ++ ++exit 0 +diff --git a/target/linux/ar71xx/base-files/etc/board.d/03_gpio_switches b/target/linux/ar71xx/base-files/etc/board.d/03_gpio_switches +new file mode 100755 +index 0000000000..3bb2f635a3 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/board.d/03_gpio_switches +@@ -0,0 +1,42 @@ ++#!/bin/sh ++# ++# Copyright (C) 2015 OpenWrt.org ++# ++ ++. /lib/functions/uci-defaults.sh ++ ++board_config_update ++ ++board=$(board_name) ++ ++case "$board" in ++cpe210|\ ++cpe510|\ ++wbs210|\ ++wbs510) ++ ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "20" ++ ;; ++nanostation-m) ++ ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "8" ++ ;; ++nanostation-m-xw) ++ ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "2" ++ ;; ++rb-912uag-2hpnd|\ ++rb-912uag-5hpnd) ++ ucidef_add_gpio_switch "usb_power_switch" "USB Power Switch" "61" "1" ++ ;; ++rb-750up-r2|\ ++rb-951ui-2nd|\ ++rb-952ui-5ac2nd) ++ ucidef_add_gpio_switch "usb_power_switch" "USB Power Switch" "45" "1" ++ ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "14" ++ ;; ++rb-750p-pbr2) ++ ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "14" ++ ;; ++esac ++ ++board_config_flush ++ ++exit 0 +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +new file mode 100644 +index 0000000000..1a92ad927d +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -0,0 +1,599 @@ ++#!/bin/sh ++# Copyright (C) 2009-2013 OpenWrt.org ++ ++. /lib/functions.sh ++. /lib/functions/leds.sh ++ ++get_status_led() { ++ local board=$(board_name) ++ ++ case $board in ++ a40) ++ status_led="a40:green:status" ++ ;; ++ a60) ++ status_led="a60:green:status" ++ ;; ++ alfa-nx) ++ status_led="alfa:green:led_8" ++ ;; ++ all0305) ++ status_led="eap7660d:green:ds4" ++ ;; ++ antminer-s1|\ ++ antminer-s3|\ ++ antminer-r1|\ ++ e1700ac-v2|\ ++ e558-v2|\ ++ e600gac-v2|\ ++ e750a-v4|\ ++ e750g-v8|\ ++ eap120|\ ++ minibox-v1|\ ++ minibox-v3.2|\ ++ packet-squirrel|\ ++ som9331|\ ++ sr3200|\ ++ tl-wr802n-v2|\ ++ xd3200) ++ status_led="$board:green:system" ++ ;; ++ ap121f) ++ status_led="$board:green:vpn" ++ ;; ++ ap132|\ ++ ap531b0|\ ++ cpe505n|\ ++ db120|\ ++ dr342|\ ++ dr344|\ ++ rut900|\ ++ tew-632brp|\ ++ tl-wr942n-v1|\ ++ wpj344|\ ++ zbt-we1526) ++ status_led="$board:green:status" ++ ;; ++ ap136-010|\ ++ ap136-020) ++ status_led="ap136:green:status" ++ ;; ++ ap147-010) ++ status_led="ap147:green:status" ++ ;; ++ ap135-020) ++ status_led="ap135:green:status" ++ ;; ++ archer-c25-v1|\ ++ archer-c58-v1|\ ++ archer-c59-v1|\ ++ archer-c59-v2|\ ++ archer-c60-v1|\ ++ archer-c60-v2|\ ++ archer-c7-v4|\ ++ archer-c7-v5|\ ++ fritz300e|\ ++ fritz4020|\ ++ fritz450e|\ ++ gl-ar750s|\ ++ gl-usb150|\ ++ mr12|\ ++ mr16|\ ++ nbg6616|\ ++ sc1750|\ ++ sc450|\ ++ tl-wpa8630|\ ++ tl-wr902ac-v1) ++ status_led="$board:green:power" ++ ;; ++ tl-mr10u|\ ++ tl-mr12u|\ ++ tl-mr13u|\ ++ tl-wdr4300|\ ++ tl-wdr4900-v2|\ ++ tl-wr703n|\ ++ tl-wr710n|\ ++ tl-wr720n-v3|\ ++ tl-wr802n-v1|\ ++ tl-wr810n|\ ++ tl-wr810n-v2|\ ++ tl-wr940n-v4|\ ++ tl-wr941nd-v6) ++ status_led="tp-link:blue:system" ++ ;; ++ ap90q|\ ++ cpe830|\ ++ cpe870|\ ++ gl-ar300m|\ ++ gl-inet|\ ++ gl-mifi) ++ status_led="$board:green:lan" ++ ;; ++ ap91-5g|\ ++ n5q) ++ status_led="$board:green:signal4" ++ ;; ++ ap96) ++ status_led="$board:green:led2" ++ ;; ++ aw-nr580) ++ status_led="$board:green:ready" ++ ;; ++ bhr-4grv2|\ ++ wzr-hp-ag300h|\ ++ wzr-hp-g300nh2) ++ status_led="buffalo:red:diag" ++ ;; ++ bsb) ++ status_led="$board:red:sys" ++ ;; ++ bullet-m|\ ++ bullet-m-xw|\ ++ loco-m-xw|\ ++ nano-m|\ ++ nanostation-m|\ ++ nanostation-m-xw|\ ++ rocket-m|\ ++ rocket-m-xw) ++ status_led="ubnt:green:link4" ++ ;; ++ bxu2000n-2-a1) ++ status_led="bhu:green:status" ++ ;; ++ cap324) ++ status_led="pcs:green:power" ++ ;; ++ c-55|\ ++ c-60) ++ status_led="$board:green:pwr" ++ ;; ++ cap4200ag) ++ status_led="senao:green:pwr" ++ ;; ++ cf-e316n-v2|\ ++ cf-e520n|\ ++ cf-e530n) ++ status_led="$board:blue:wan" ++ ;; ++ cf-e320n-v2) ++ status_led="$board:blue:wlan" ++ ;; ++ cf-e375ac|\ ++ cf-e380ac-v1|\ ++ cf-e380ac-v2|\ ++ cf-e385ac) ++ status_led="$board:blue:wlan2g" ++ ;; ++ cpe510) ++ status_led="tp-link:green:link4" ++ ;; ++ cr3000|\ ++ cr5000) ++ status_led="pcs:amber:power" ++ ;; ++ dap-1330-a1|\ ++ dgl-5500-a1|\ ++ dhp-1565-a1|\ ++ dir-505-a1|\ ++ dir-600-a1|\ ++ dir-615-e1|\ ++ dir-615-i1|\ ++ dir-615-e4) ++ status_led="d-link:green:power" ++ ;; ++ dir-615-c1) ++ status_led="d-link:green:status" ++ ;; ++ dir-825-b1) ++ status_led="d-link:orange:power" ++ ;; ++ dir-825-c1|\ ++ dir-835-a1) ++ status_led="d-link:amber:power" ++ ;; ++ dir-869-a1) ++ status_led="d-link:white:status" ++ ;; ++ dlan-hotspot) ++ status_led="devolo:green:wifi" ++ ;; ++ dlan-pro-500-wp) ++ status_led="devolo:green:wlan-2g" ++ ;; ++ dlan-pro-1200-ac) ++ status_led="devolo:status:wlan" ++ ;; ++ dr531) ++ status_led="$board:green:sig4" ++ ;; ++ dragino2|\ ++ oolite-v1) ++ status_led="$board:red:system" ++ ;; ++ dw33d|\ ++ r36a) ++ status_led="$board:blue:status" ++ ;; ++ e600g-v2|\ ++ oolite-v5.2-dev|\ ++ ts-d084|\ ++ wifi-pineapple-nano) ++ status_led="$board:blue:system" ++ ;; ++ eap300v2) ++ status_led="engenius:blue:power" ++ ;; ++ ens202ext|\ ++ esr900) ++ status_led="engenius:amber:power" ++ ;; ++ eap7660d) ++ status_led="$board:green:ds4" ++ ;; ++ el-m150|\ ++ el-mini) ++ status_led="easylink:green:system" ++ ;; ++ ew-balin) ++ status_led="balin:green:status" ++ ;; ++ ew-dorin|\ ++ ew-dorin-router) ++ status_led="dorin:green:status" ++ ;; ++ f9k1115v2) ++ status_led="belkin:blue:status" ++ ;; ++ epg5000|\ ++ esr1750) ++ status_led="$board:amber:power" ++ ;; ++ gl-ar750|\ ++ hiveap-121|\ ++ nbg6716|\ ++ wam250) ++ status_led="$board:white:power" ++ ;; ++ hiwifi-hc6361) ++ status_led="hiwifi:blue:system" ++ ;; ++ hornet-ub|\ ++ hornet-ub-x2) ++ status_led="alfa:blue:wps" ++ ;; ++ ja76pf|\ ++ ja76pf2) ++ status_led="jjplus:green:led1" ++ ;; ++ jwap230) ++ status_led="$board:green:led1" ++ ;; ++ koala) ++ status_led="$board:blue:sys" ++ ;; ++ lan-turtle) ++ status_led="$board:orange:system" ++ ;; ++ lbe-m5) ++ status_led="ubnt:green:sys" ++ ;; ++ ls-sr71) ++ status_led="ubnt:green:d22" ++ ;; ++ mc-mac1200r) ++ status_led="mercury:green:system" ++ ;; ++ mr18|\ ++ z1) ++ status_led="$board:green:tricolor0" ++ ;; ++ mr600) ++ status_led="$board:orange:power" ++ ;; ++ mr600v2) ++ status_led="mr600:blue:power" ++ ;; ++ mr1750|\ ++ mr1750v2) ++ status_led="mr1750:blue:power" ++ ;; ++ mr900|\ ++ mr900v2) ++ status_led="mr900:blue:power" ++ ;; ++ mynet-n600|\ ++ mynet-n750|\ ++ mynet-rext) ++ status_led="wd:blue:power" ++ ;; ++ mzk-w04nu|\ ++ mzk-w300nh) ++ status_led="planex:green:status" ++ ;; ++ nbg460n_550n_550nh) ++ status_led="nbg460n:green:power" ++ ;; ++ om2p|\ ++ om2p-hs|\ ++ om2p-hsv2|\ ++ om2p-hsv3|\ ++ om2p-hsv4|\ ++ om2p-lc|\ ++ om2pv2|\ ++ om2pv4) ++ status_led="om2p:blue:power" ++ ;; ++ om5p|\ ++ om5p-an) ++ status_led="om5p:blue:power" ++ ;; ++ om5p-ac|\ ++ om5p-acv2) ++ status_led="om5pac:blue:power" ++ ;; ++ omy-g1) ++ status_led="omy:green:wlan" ++ ;; ++ omy-x1) ++ status_led="omy:green:power" ++ ;; ++ onion-omega) ++ status_led="onion:amber:system" ++ ;; ++ pb44) ++ status_led="$board:amber:jump1" ++ ;; ++ r602n) ++ status_led="$board:green:wan" ++ ;; ++ rb-2011il|\ ++ rb-2011ils|\ ++ rb-2011l|\ ++ rb-2011uas|\ ++ rb-2011uas-2hnd) ++ status_led="rb:green:usr" ++ ;; ++ rb-411|\ ++ rb-411u|\ ++ rb-433|\ ++ rb-433u|\ ++ rb-450|\ ++ rb-450g|\ ++ rb-493) ++ status_led="rb4xx:yellow:user" ++ ;; ++ rb-750) ++ status_led="rb750:green:act" ++ ;; ++ rb-750-r2|\ ++ rb-750p-pbr2|\ ++ rb-750up-r2|\ ++ rb-911-2hn|\ ++ rb-911-5hn|\ ++ rb-911g-2hpnd|\ ++ rb-911g-5hpacd|\ ++ rb-911g-5hpnd|\ ++ rb-931-2nd|\ ++ rb-941-2nd|\ ++ rb-951ui-2nd|\ ++ rb-952ui-5ac2nd|\ ++ rb-962uigs-5hact2hnt|\ ++ rb-lhg-5nd|\ ++ rb-map-2nd|\ ++ rb-mapl-2nd|\ ++ rb-sxt-2nd-r3|\ ++ rb-wap-2nd|\ ++ rb-wapr-2nd) ++ status_led="rb:green:user" ++ ;; ++ rb-951ui-2hnd) ++ status_led="rb:green:act" ++ ;; ++ rb-912uag-2hpnd|\ ++ rb-912uag-5hpnd|\ ++ rb-sxt2n|\ ++ rb-sxt5n|\ ++ rb-wapg-5hact2hnd) ++ status_led="rb:green:power" ++ ;; ++ re355|\ ++ re450|\ ++ sc300m) ++ status_led="$board:blue:power" ++ ;; ++ rocket-m-ti) ++ status_led="ubnt:green:link6" ++ ;; ++ routerstation|\ ++ routerstation-pro) ++ status_led="ubnt:green:rf" ++ ;; ++ rw2458n) ++ status_led="$board:green:d3" ++ ;; ++ smart-300) ++ status_led="nc-link:green:system" ++ ;; ++ qihoo-c301) ++ status_led="qihoo:green:status" ++ ;; ++ t830) ++ status_led="$board:green:usb" ++ ;; ++ tellstick-znet-lite) ++ status_led="tellstick:white:system" ++ ;; ++ tew-673gru) ++ status_led="trendnet:blue:wps" ++ ;; ++ tew-712br|\ ++ tew-732br|\ ++ tew-823dru) ++ status_led="trendnet:green:power" ++ ;; ++ tl-mr3020|\ ++ tl-wr2543n) ++ status_led="tp-link:green:wps" ++ ;; ++ tl-wa750re) ++ status_led="tp-link:orange:re" ++ ;; ++ tl-wa850re|\ ++ tl-wa850re-v2) ++ status_led="tp-link:blue:re" ++ ;; ++ tl-wa855re-v1|\ ++ tl-wa860re) ++ status_led="tp-link:green:power" ++ ;; ++ tl-mr6400) ++ status_led="tp-link:white:power" ++ ;; ++ archer-c5|\ ++ archer-c7|\ ++ tl-mr3220|\ ++ tl-mr3220-v2|\ ++ tl-mr3420|\ ++ tl-mr3420-v2|\ ++ tl-wa701nd-v2|\ ++ tl-wa801nd-v2|\ ++ tl-wa801nd-v3|\ ++ tl-wa830re-v2|\ ++ tl-wa901nd|\ ++ tl-wa901nd-v2|\ ++ tl-wa901nd-v3|\ ++ tl-wa901nd-v4|\ ++ tl-wa901nd-v5|\ ++ tl-wdr3320-v2|\ ++ tl-wdr3500|\ ++ tl-wr1041n-v2|\ ++ tl-wr1043n-v5|\ ++ tl-wr1043nd|\ ++ tl-wr1043nd-v2|\ ++ tl-wr1043nd-v4|\ ++ tl-wr740n-v6|\ ++ tl-wr741nd|\ ++ tl-wr741nd-v4|\ ++ tl-wr840n-v2|\ ++ tl-wr840n-v3|\ ++ tl-wr841n-v1|\ ++ tl-wr841n-v7|\ ++ tl-wr841n-v8|\ ++ tl-wr841n-v11|\ ++ tl-wr842n-v2|\ ++ tl-wr842n-v3|\ ++ tl-wr941nd|\ ++ tl-wr941nd-v5) ++ status_led="tp-link:green:system" ++ ;; ++ tl-wr841n-v9) ++ status_led="tp-link:green:qss" ++ ;; ++ tl-wr940n-v6) ++ status_led="tp-link:orange:diag" ++ ;; ++ tl-wdr6500-v2) ++ status_led="tp-link:white:system" ++ ;; ++ tube2h) ++ status_led="alfa:green:signal4" ++ ;; ++ unifi) ++ status_led="ubnt:green:dome" ++ ;; ++ uap-pro|\ ++ unifiac-lite|\ ++ unifiac-pro) ++ status_led="ubnt:white:dome" ++ ;; ++ unifi-outdoor-plus) ++ status_led="ubnt:white:front" ++ ;; ++ airgateway|\ ++ airgatewaypro) ++ status_led="ubnt:white:status" ++ ;; ++ wi2a-ac200i) ++ status_led="nokia:green:ctrl" ++ ;; ++ whr-g301n|\ ++ whr-hp-g300n|\ ++ whr-hp-gn|\ ++ wzr-hp-g300nh) ++ status_led="buffalo:green:router" ++ ;; ++ wlae-ag300n) ++ status_led="buffalo:green:status" ++ ;; ++ r6100|\ ++ wndap360|\ ++ wndr3700|\ ++ wndr3700v4|\ ++ wndr4300|\ ++ wnr2000|\ ++ wnr2000-v3|\ ++ wnr2200|\ ++ wnr612-v2|\ ++ wnr1000-v2|\ ++ wpn824n) ++ status_led="netgear:green:power" ++ ;; ++ wp543) ++ status_led="$board:green:diag" ++ ;; ++ wpj342|\ ++ wpj531|\ ++ wpj558) ++ status_led="$board:green:sig3" ++ ;; ++ wpj563) ++ status_led="$board:green:sig1" ++ ;; ++ wrt160nl|\ ++ wrt400n) ++ status_led="$board:blue:wps" ++ ;; ++ zcn-1523h-2|\ ++ zcn-1523h-5) ++ status_led="zcn-1523h:amber:init" ++ ;; ++ wlr8100) ++ status_led="sitecom:amber:status" ++ ;; ++ esac ++} ++ ++set_state() { ++ get_status_led ++ ++ case "$1" in ++ preinit) ++ status_led_blink_preinit ++ ;; ++ failsafe) ++ status_led_blink_failsafe ++ ;; ++ preinit_regular) ++ status_led_blink_preinit_regular ++ ;; ++ upgrade) ++ status_led_blink_preinit_regular ++ ;; ++ done) ++ status_led_on ++ case $(board_name) in ++ gl-ar300m|\ ++ gl-ar750) ++ fw_printenv lc >/dev/null 2>&1 && fw_setenv "bootcount" 0 ++ ;; ++ qihoo-c301) ++ local n=$(fw_printenv activeregion | cut -d = -f 2) ++ fw_setenv "image${n}trynum" 0 ++ ;; ++ wi2a-ac200i) ++ fw_setenv PKRstCnt 0 ++ ;; ++ esac ++ ;; ++ esac ++} +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +new file mode 100644 +index 0000000000..8fe57c87cc +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +@@ -0,0 +1,178 @@ ++#!/bin/sh ++ ++[ -e /lib/firmware/$FIRMWARE ] && exit 0 ++ ++. /lib/functions.sh ++. /lib/functions/system.sh ++ ++ath9k_eeprom_die() { ++ echo "ath9k eeprom: " "$*" ++ exit 1 ++} ++ ++ath9k_eeprom_extract() { ++ local part=$1 ++ local offset=$(($2)) ++ local count=$(($3)) ++ local mtd ++ ++ mtd=$(find_mtd_chardev $part) ++ [ -n "$mtd" ] || \ ++ ath9k_eeprom_die "no mtd device found for partition $part" ++ ++ dd if=$mtd of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ ++ ath9k_eeprom_die "failed to extract from $mtd" ++} ++ ++ath9k_ubi_eeprom_extract() { ++ local part=$1 ++ local offset=$(($2)) ++ local count=$(($3)) ++ local ubidev=$(nand_find_ubi $CI_UBIPART) ++ local ubi ++ ++ ubi=$(nand_find_volume $ubidev $part) ++ [ -n "$ubi" ] || \ ++ ath9k_eeprom_die "no UBI volume found for $part" ++ ++ dd if=/dev/$ubi of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ ++ ath9k_eeprom_die "failed to extract from $ubi" ++} ++ ++ath9k_eeprom_extract_reverse() { ++ local part=$1 ++ local offset=$2 ++ local count=$(($3)) ++ local mtd ++ local reversed ++ local caldata ++ ++ mtd=$(find_mtd_chardev "$part") ++ reversed=$(hexdump -v -s $offset -n $count -e '/1 "%02x "' $mtd) ++ ++ for byte in $reversed; do ++ caldata="\x${byte}${caldata}" ++ done ++ ++ printf "%b" "$caldata" > /lib/firmware/$FIRMWARE ++} ++ ++ath9k_patch_firmware_mac() { ++ local mac=$1 ++ ++ [ -z "$mac" ] && return ++ ++ macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc oflag=seek_bytes bs=6 seek=2 count=1 ++} ++ ++board=$(board_name) ++ ++case "$FIRMWARE" in ++"soc_wmac.eeprom") ++ case $board in ++ c-55|\ ++ c-60) ++ ath9k_eeprom_extract "art" 0x1000 0x800 ++ ath9k_patch_firmware_mac $(macaddr_add $(mtd_get_mac_binary art 0x0) +1) ++ ;; ++ fritz4020|\ ++ fritz450e) ++ ath9k_eeprom_extract_reverse "urlader" 0x1541 0x440 ++ ;; ++ mr18) ++ . /lib/upgrade/nand.sh ++ ++ if [ -n "$(nand_find_volume ubi0 caldata)" ]; then ++ ath9k_ubi_eeprom_extract "caldata" 0x1000 0x800 ++ else ++ ath9k_eeprom_extract "odm-caldata" 0x1000 0x800 ++ fi ++ ath9k_patch_firmware_mac $(macaddr_add $(mtd_get_mac_binary_ubi board-config 0x66) +1) ++ ;; ++ r6100 | \ ++ wndr3700v4 | \ ++ wndr4300) ++ ath9k_eeprom_extract "caldata" 0x1000 0x800 ++ ath9k_patch_firmware_mac $(mtd_get_mac_binary caldata 0x0) ++ ;; ++ rambutan) ++ ath9k_eeprom_extract "art" 0x1000 0x800 ++ ;; ++ wlr8100) ++ ath9k_eeprom_extract "art" 0x1000 0x800 ++ ath9k_patch_firmware_mac $(mtd_get_mac_ascii u-boot-env "ethaddr") ++ ;; ++ z1) ++ . /lib/upgrade/nand.sh ++ ++ if [ -n "$(nand_find_volume ubi0 caldata)" ]; then ++ ath9k_ubi_eeprom_extract "caldata" 0x1000 0x800 ++ else ++ ath9k_eeprom_extract "origcaldata" 0x1000 0x800 ++ fi ++ ath9k_patch_firmware_mac $(macaddr_add $(mtd_get_mac_binary_ubi board-config 0x66) +2) ++ ;; ++ *) ++ ath9k_eeprom_die "board $board is not supported yet" ++ ;; ++ esac ++ ;; ++ ++"pci_wmac0.eeprom") ++ case $board in ++ c-55) ++ ath9k_eeprom_extract "art" 0x5000 0x800 ++ ath9k_patch_firmware_mac $(macaddr_add $(mtd_get_mac_binary art 0x0) +2) ++ ;; ++ fritz300e) ++ ath9k_eeprom_extract_reverse "urloader" 0x1541 0x440 ++ ;; ++ mr18) ++ . /lib/upgrade/nand.sh ++ ++ if [ -n "$(nand_find_volume ubi0 caldata)" ]; then ++ ath9k_ubi_eeprom_extract "caldata" 0x5000 0x800 ++ else ++ ath9k_eeprom_extract "odm-caldata" 0x5000 0x800 ++ fi ++ ath9k_patch_firmware_mac $(macaddr_add $(mtd_get_mac_binary_ubi board-config 0x66) +2) ++ ;; ++ wndr3700v4 | \ ++ wndr4300) ++ ath9k_eeprom_extract "caldata" 0x5000 0x800 ++ ath9k_patch_firmware_mac $(mtd_get_mac_binary caldata 0xc) ++ ;; ++ z1) ++ . /lib/upgrade/nand.sh ++ ++ if [ -n "$(nand_find_volume ubi0 caldata)" ]; then ++ ath9k_ubi_eeprom_extract "caldata" 0x15000 0x1000 ++ else ++ ath9k_eeprom_extract "origcaldata" 0x15000 0x1000 ++ fi ++ ath9k_patch_firmware_mac $(macaddr_add $(mtd_get_mac_binary_ubi board-config 0x66) +3) ++ ;; ++ *) ++ ath9k_eeprom_die "board $board is not supported yet" ++ ;; ++ esac ++ ;; ++ ++"pci_wmac1.eeprom") ++ case $board in ++ mr18) ++ . /lib/upgrade/nand.sh ++ ++ if [ -n "$(nand_find_volume ubi0 caldata)" ]; then ++ ath9k_ubi_eeprom_extract "caldata" 0x9000 0x800 ++ else ++ ath9k_eeprom_extract "odm-caldata" 0x9000 0x800 ++ fi ++ ath9k_patch_firmware_mac $(macaddr_add $(mtd_get_mac_binary_ubi board-config 0x66) +3) ++ ;; ++ *) ++ ath9k_eeprom_die "board $board is not supported yet" ++ ;; ++ esac ++ ;; ++esac +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +new file mode 100644 +index 0000000000..c0e8f17d94 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -0,0 +1,195 @@ ++#!/bin/sh ++ ++ath10kcal_die() { ++ echo "ath10cal: " "$*" ++ exit 1 ++} ++ ++ath10kcal_from_file() { ++ local source=$1 ++ local offset=$(($2)) ++ local count=$(($3)) ++ ++ dd if=$source of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ ++ ath10kcal_die "failed to extract calibration data from $source" ++} ++ ++ath10kcal_extract() { ++ local part=$1 ++ local offset=$(($2)) ++ local count=$(($3)) ++ local mtd cal_size ++ ++ mtd=$(find_mtd_chardev $part) ++ [ -n "$mtd" ] || \ ++ ath10kcal_die "no mtd device found for partition $part" ++ ++ # Check that the calibration data size in header equals the desired size ++ cal_size=$(dd if=$mtd bs=2 count=1 skip=$(( $offset / 2 )) conv=swab 2>/dev/null | hexdump -ve '1/2 "%d"') ++ ++ [ "$count" = "$cal_size" ] || \ ++ ath10kcal_die "no calibration data found in $part" ++ ++ dd if=$mtd of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ ++ ath10kcal_die "failed to extract calibration data from $mtd" ++} ++ ++ath10kcal_patch_mac() { ++ local mac=$1 ++ ++ [ -z "$mac" ] && return ++ ++ macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc oflag=seek_bytes bs=6 seek=6 count=1 ++} ++ ++[ -e /lib/firmware/$FIRMWARE ] && exit 0 ++ ++. /lib/functions.sh ++. /lib/functions/system.sh ++ ++board=$(board_name) ++ ++case "$FIRMWARE" in ++"ath10k/cal-pci-0000:00:00.0.bin") ++ case $board in ++ a40|\ ++ a60|\ ++ mr1750|\ ++ mr1750v2|\ ++ om5p-acv2) ++ ath10kcal_extract "ART" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +16) ++ ;; ++ archer-c25-v1|\ ++ tl-wdr6500-v2) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) -2) ++ ;; ++ archer-c7-v4|\ ++ archer-c7-v5) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -1) ++ ;; ++ cf-e355ac-v1|\ ++ cf-e380ac-v1|\ ++ cf-e380ac-v2|\ ++ dlan-pro-1200-ac|\ ++ e1700ac-v2|\ ++ e600gac-v2|\ ++ minibox-v3.2|\ ++ oolite-v5.2|\ ++ oolite-v5.2-dev|\ ++ sr3200|\ ++ xd3200) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ;; ++ dap-2695-a1) ++ ath10kcal_extract "radiocfg" 0x5000 0x844 ++ ath10kcal_patch_mac $(mtd_get_mac_ascii bdcfg wlanmac_a) ++ ;; ++ dir-869-a1|\ ++ qihoo-c301) ++ ath10kcal_extract "radiocfg" 0x5000 0x844 ++ ath10kcal_patch_mac $(mtd_get_mac_ascii devdata wlan5mac) ++ ;; ++ dw33d) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(mtd_get_mac_binary art 0x12) ++ ;; ++ epg5000|\ ++ esr1750) ++ ath10kcal_extract "caldata" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +1) ++ ;; ++ gl-ar750s|\ ++ gl-ar750|\ ++ tl-wpa8630) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +1) ++ ;; ++ koala) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary art 0xc) +0) ++ ;; ++ mc-mac1200r) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) -1) ++ ;; ++ r6100) ++ ath10kcal_extract "caldata" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) +2) ++ ;; ++ rb-952ui-5ac2nd|\ ++ rb-wapg-5hact2hnd) ++ ath10kcal_from_file "/sys/firmware/mikrotik/hard_config/wlan_data" 0x5000 0x844 ++ ;; ++ re355|\ ++ re450|\ ++ tl-wr902ac-v1) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -2) ++ ;; ++ unifiac-lite|\ ++ unifiac-pro) ++ ath10kcal_extract "EEPROM" 0x5000 0x844 ++ ;; ++ wi2a-ac200i) ++ ath10kcal_extract "ART" 0x5000 0x844 ++ ;; ++ esac ++ ;; ++"ath10k/cal-pci-0000:01:00.0.bin") ++ case $board in ++ archer-c5|\ ++ archer-c7) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) -1) ++ ;; ++ nbg6616|\ ++ nbg6716) ++ ath10kcal_extract "RFdata" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) -2) ++ ;; ++ om5p-ac) ++ ath10kcal_extract "ART" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +16) ++ ;; ++ rb-911g-5hpacd|\ ++ rb-921gs-5hpacd-r2|\ ++ rb-922uags-5hpacd|\ ++ rb-962uigs-5hact2hnt) ++ ath10kcal_from_file "/sys/firmware/mikrotik/hard_config/wlan_data" 0x5000 0x844 ++ ;; ++ wlr8100) ++ ath10kcal_extract "art" 0x5000 0x844 ++ ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_ascii u-boot-env ethaddr) +1) ++ ;; ++ esac ++ ;; ++"ath10k/pre-cal-pci-0000:00:00.0.bin") ++ case $board in ++ archer-c58-v1|\ ++ archer-c59-v1|\ ++ archer-c59-v2|\ ++ archer-c60-v1|\ ++ cf-e355ac-v2|\ ++ cf-e375ac) ++ ath10kcal_extract "art" 0x5000 0x2f20 ++ ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ ++ /lib/firmware/ath10k/QCA9888/hw2.0/board.bin ++ ;; ++ archer-c60-v2) ++ ath10kcal_extract "art" 0x5000 0x2f20 ++ ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ ++ /lib/firmware/ath10k/QCA9888/hw2.0/board.bin ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) -1) ++ ;; ++ cf-e385ac) ++ ath10kcal_extract "art" 0x5000 0x2f20 ++ ;; ++ esac ++ ;; ++*) ++ exit 1 ++ ;; ++esac +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +new file mode 100644 +index 0000000000..2a06b7d07b +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +@@ -0,0 +1,24 @@ ++#!/bin/ash ++ ++[ "$ACTION" == "add" ] || exit 0 ++ ++PHYNBR=${DEVPATH##*/phy} ++ ++[ -n $PHYNBR ] || exit 0 ++ ++. /lib/functions.sh ++. /lib/functions/system.sh ++ ++board=$(board_name) ++ ++case "$board" in ++ archer-c58-v1|\ ++ archer-c59-v1|\ ++ archer-c59-v2|\ ++ archer-c60-v1) ++ echo $(macaddr_add $(mtd_get_mac_binary mac 0x8) $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress ++ ;; ++ *) ++ ;; ++esac ++ +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/net/10-ar922x-led-fix b/target/linux/ar71xx/base-files/etc/hotplug.d/net/10-ar922x-led-fix +new file mode 100644 +index 0000000000..bd1abb9681 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/net/10-ar922x-led-fix +@@ -0,0 +1,52 @@ ++#!/bin/sh ++ ++# For AR9220 and AR9223, GPIO JTAG must explicit be disabled ++# before LEDs start working. Do this when wifi device is ++# detected. ++ ++# ++# $DEVPATH is not valid for some boards (including WZR-HP-AG300H). ++# Manipulate the $DEVPATH to reach the corresponding phyN. ++# ++ ++devdir=$(dirname $DEVPATH) ++devdir=$(dirname $devdir) ++phydir=/sys$devdir/ieee80211 ++ ++[ -d $phydir ] || exit 0 ++ ++phyname=$(cat $phydir/phy*/name) ++ ++[ -z $phyname -o $ACTION != "add" ] && exit 0 ++ ++# ++# ar922x_disable_gpio_jtag(): ++# ++# Emulate ++# REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); ++# for AR9220 and AR9223. ++# ++ ++ar922x_disable_gpio_jtag() { ++ local regidx=0x4054 ++ ++ [ -f /sys/kernel/debug/ieee80211/$1/ath9k/regidx ] || return ++ ++ echo $regidx > /sys/kernel/debug/ieee80211/$1/ath9k/regidx ++ regval=$(cat /sys/kernel/debug/ieee80211/$1/ath9k/regval) ++ regval=$((regval | 0x20000)) ++ echo regval $regval ++ echo $regval > /sys/kernel/debug/ieee80211/$1/ath9k/regval ++} ++ ++[ $phyname -a $ACTION = "add" ] && { ++ . /lib/functions.sh ++ ++ case $(board_name) in ++ wzr-hp-ag300h) ++ ar922x_disable_gpio_jtag $phyname ++ ;; ++ esac; ++} ++ ++exit 0 +diff --git a/target/linux/ar71xx/base-files/etc/inittab b/target/linux/ar71xx/base-files/etc/inittab +new file mode 100644 +index 0000000000..9820e7144b +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/inittab +@@ -0,0 +1,3 @@ ++::sysinit:/etc/init.d/rcS S boot ++::shutdown:/etc/init.d/rcS K shutdown ++::askconsole:/usr/libexec/login.sh +diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/03_network-switchX-migration b/target/linux/ar71xx/base-files/etc/uci-defaults/03_network-switchX-migration +new file mode 100644 +index 0000000000..0388fb6dc9 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/uci-defaults/03_network-switchX-migration +@@ -0,0 +1,108 @@ ++#!/bin/sh ++# ++# Copyright (C) 2013 OpenWrt.org ++# ++ ++SWITCH_NAME_CHANGED= ++ ++. /lib/functions.sh ++ ++do_change_switch_name() { ++ local config="$1" ++ local option=$2 ++ local oldname=$3 ++ local newname=$4 ++ local val ++ ++ config_get val "$config" $option ++ [ "$val" != "$oldname" ] && return 0 ++ ++ uci_set network "$config" $option $newname ++ SWITCH_NAME_CHANGED=1 ++ ++ return 0 ++} ++ ++migrate_switch_name() { ++ local oldname=$1 ++ local newname=$2 ++ ++ config_load network ++ ++ logger -t migrate-switchX "Updating switch names in network configuration" ++ ++ config_foreach do_change_switch_name switch name $oldname $newname ++ config_foreach do_change_switch_name switch_vlan device $oldname $newname ++ ++ [ "$SWITCH_NAME_CHANGED" = "1" ] && { ++ logger -t migrate-switchX "Switch names updated, saving network configuration" ++ uci commit network ++ } ++} ++ ++board=$(board_name) ++ ++case "$board" in ++airrouter|\ ++ap121|\ ++ap121-mini|\ ++ap96|\ ++dir-600-a1|\ ++dir-615-c1|\ ++dir-615-e1|\ ++dir-615-e4|\ ++dir-825-c1|\ ++ebr-2310-c1|\ ++ew-dorin|\ ++ew-dorin-router|\ ++ja76pf|\ ++rb-750|\ ++rb-751|\ ++tew-632brp|\ ++tew-712br|\ ++tl-mr3220|\ ++tl-mr3220-v2 |\ ++tl-mr3420|\ ++tl-wdr4300|\ ++tl-wr741nd|\ ++tl-wr741nd-v4|\ ++tl-wr841n-v7|\ ++tl-wr1041n-v2|\ ++whr-g301n|\ ++whr-hp-g300n|\ ++whr-hp-gn|\ ++wrt160nl|\ ++wzr-hp-ag300h|\ ++wzr-hp-g300nh2|\ ++wzr-hp-g450h|\ ++z1) ++ migrate_switch_name "eth0" "switch0" ++ ;; ++ ++el-m150|\ ++rb-450) ++ migrate_switch_name "eth1" "switch0" ++ ;; ++ ++db120|\ ++rb-2011il|\ ++rb-2011ils|\ ++rb-2011l|\ ++rb-2011uas-2hnd) ++ migrate_switch_name "eth0" "switch0" ++ migrate_switch_name "eth1" "switch1" ++ ;; ++ ++dir-825-b1|\ ++nbg460n_550n_550nh|\ ++tew-673gru) ++ migrate_switch_name "rtl8366s" "switch0" ++ ;; ++ ++tl-wr1043nd) ++ migrate_switch_name "rtl8366rb" "switch0" ++ ;; ++ ++esac ++ ++exit 0 +diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/03_network-vlan-migration b/target/linux/ar71xx/base-files/etc/uci-defaults/03_network-vlan-migration +new file mode 100644 +index 0000000000..259d240610 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/uci-defaults/03_network-vlan-migration +@@ -0,0 +1,13 @@ ++#!/bin/sh ++# ++# Copyright (C) 2010 OpenWrt.org ++# ++ ++dev="$(uci -q get network.@switch_vlan[0].device)" ++vlan="$(uci -q get network.@switch_vlan[0].vlan)" ++ ++if [ "$dev" = "rtl8366s" ] && [ "$vlan" = 0 ]; then ++ logger -t vlan-migration "VLAN 0 is invalid for RTL8366s, changing to 1" ++ uci set network.@switch_vlan[0].vlan=1 ++ uci commit network ++fi +diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/04_led_migration b/target/linux/ar71xx/base-files/etc/uci-defaults/04_led_migration +new file mode 100644 +index 0000000000..c244b3b460 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/uci-defaults/04_led_migration +@@ -0,0 +1,84 @@ ++#!/bin/sh ++# ++# Copyright (C) 2013 OpenWrt.org ++# ++ ++LED_OPTIONS_CHANGED=0 ++ ++. /lib/functions.sh ++ ++do_led_update_sysfs() ++{ ++ local cfg=$1; shift ++ local tuples="$@" ++ local sysfs ++ local name ++ ++ config_get sysfs $cfg sysfs ++ config_get name $cfg name ++ ++ [ -z "$sysfs" ] && return ++ ++ for tuple in $tuples; do ++ local old=${tuple%=*} ++ local new=${tuple#*=} ++ local new_sysfs ++ ++ new_sysfs=$(echo ${sysfs} | sed "s/${old}/${new}/") ++ ++ [ "$new_sysfs" = "$sysfs" ] && continue ++ ++ uci set system.${cfg}.sysfs="${new_sysfs}" ++ LED_OPTIONS_CHANGED=1 ++ ++ logger -t led-migration "sysfs option of LED \"${name}\" updated to ${new_sysfs}" ++ done; ++} ++ ++migrate_leds() ++{ ++ config_load system ++ config_foreach do_led_update_sysfs led "$@" ++} ++ ++board=$(board_name) ++ ++case "$board" in ++archer-c7) ++ migrate_leds ":blue:=:green:" ++ ;; ++dhp-1565-a1|\ ++dir-825-c1|\ ++dir-835-a1) ++ migrate_leds ":orange:=:amber:" ":wifi_bgn=:wlan2g" ++ ;; ++dr344) ++ migrate_leds ":red:=:green:" ":yellow:=:green:" ++ ;; ++gl-ar150) ++ migrate_leds "gl-ar150:wlan=gl-ar150:orange:wlan" "gl-ar150:lan=gl-ar150:green:lan" "gl-ar150:wan=gl-ar150:green:wan" ++ ;; ++oolite-v1) ++ migrate_leds "oolite:=${board}" ++ ;; ++wndap360|\ ++wndr3700|\ ++wnr2000|\ ++wnr2200) ++ migrate_leds "${board}:=netgear:" ++ ;; ++wndr3700v4|\ ++wndr4300) ++ migrate_leds ":orange:=:amber:" ++ ;; ++wnr1000-v2) ++ migrate_leds "wnr1000v2:=netgear:" ++ ;; ++wnr612-v2) ++ migrate_leds "wnr612v2:=netgear:" ++ ;; ++esac ++ ++[ "$LED_OPTIONS_CHANGED" = "1" ] && uci commit system ++ ++exit 0 +diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/09_fix-checksum b/target/linux/ar71xx/base-files/etc/uci-defaults/09_fix-checksum +new file mode 100644 +index 0000000000..2d1afb11cb +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/uci-defaults/09_fix-checksum +@@ -0,0 +1,28 @@ ++#!/bin/sh ++# ++# Copyright (C) 2010 OpenWrt.org ++# ++ ++. /lib/functions.sh ++ ++board=$(board_name) ++ ++fixtrx() { ++ mtd -o 32 fixtrx firmware ++} ++ ++fixwrgg() { ++ local kernel_size=$(sed -n 's/mtd[0-9]*: \([0-9a-f]*\).*"kernel".*/\1/p' /proc/mtd) ++ ++ [ "$kernel_size" ] && mtd -c 0x$kernel_size fixwrgg firmware ++} ++ ++case "$board" in ++mynet-rext |\ ++wrt160nl) ++ fixtrx ++ ;; ++dap-2695-a1) ++ fixwrgg ++ ;; ++esac +diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/09_fix-seama-header b/target/linux/ar71xx/base-files/etc/uci-defaults/09_fix-seama-header +new file mode 100644 +index 0000000000..b3857ef07f +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/uci-defaults/09_fix-seama-header +@@ -0,0 +1,17 @@ ++#!/bin/sh ++ ++. /lib/functions.sh ++ ++fix_seama_header() { ++ local kernel_size=$(sed -n 's/mtd[0-9]*: \([0-9a-f]*\).*"kernel".*/\1/p' /proc/mtd) ++ ++ [ "$kernel_size" ] && mtd -c 0x$kernel_size fixseama firmware ++} ++ ++board=$(board_name) ++ ++case "$board" in ++dir-869-a1) ++ fix_seama_header ++ ;; ++esac +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +new file mode 100755 +index 0000000000..044ef4eae5 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -0,0 +1,1589 @@ ++#!/bin/sh ++# ++# Copyright (C) 2009-2011 OpenWrt.org ++# ++ ++AR71XX_BOARD_NAME= ++AR71XX_MODEL= ++ ++ar71xx_get_mtd_offset_size_format() { ++ local mtd="$1" ++ local offset="$2" ++ local size="$3" ++ local format="$4" ++ local dev ++ ++ dev=$(find_mtd_part $mtd) ++ [ -z "$dev" ] && return ++ ++ dd if=$dev iflag=skip_bytes bs=$size skip=$offset count=1 2>/dev/null | hexdump -v -e "1/1 \"$format\"" ++} ++ ++ar71xx_get_mtd_part_magic() { ++ local mtd="$1" ++ ar71xx_get_mtd_offset_size_format "$mtd" 0 4 %02x ++} ++ ++wndr3700_board_detect() { ++ local machine="$1" ++ local magic ++ local name ++ ++ name="wndr3700" ++ ++ magic="$(ar71xx_get_mtd_part_magic firmware)" ++ case $magic in ++ "33373030") ++ machine="NETGEAR WNDR3700" ++ ;; ++ "33373031") ++ model="$(ar71xx_get_mtd_offset_size_format art 41 32 %c)" ++ # Use awk to remove everything unprintable ++ model_stripped="$(ar71xx_get_mtd_offset_size_format art 41 32 %c | LC_CTYPE=C awk -v 'FS=[^[:print:]]' '{print $1; exit}')" ++ case $model in ++ $'\xff'*) ++ if [ "${model:24:1}" = 'N' ]; then ++ machine="NETGEAR WNDRMAC" ++ else ++ machine="NETGEAR WNDR3700v2" ++ fi ++ ;; ++ '29763654+16+64'*) ++ machine="NETGEAR ${model_stripped:14}" ++ ;; ++ '29763654+16+128'*) ++ machine="NETGEAR ${model_stripped:15}" ++ ;; ++ *) ++ # Unknown ID ++ machine="NETGEAR ${model_stripped}" ++ esac ++ esac ++ ++ AR71XX_BOARD_NAME="$name" ++ AR71XX_MODEL="$machine" ++} ++ ++ubnt_get_mtd_part_magic() { ++ ar71xx_get_mtd_offset_size_format EEPROM 4118 2 %02x ++} ++ ++ubnt_xm_board_detect() { ++ local model ++ local magic ++ ++ magic="$(ubnt_get_mtd_part_magic)" ++ case ${magic:0:3} in ++ "e00"|\ ++ "e01"|\ ++ "e80") ++ model="Ubiquiti NanoStation M" ++ ;; ++ "e0a") ++ model="Ubiquiti NanoStation loco M" ++ ;; ++ "e1b"|\ ++ "e1d") ++ model="Ubiquiti Rocket M" ++ ;; ++ "e20"|\ ++ "e2d") ++ model="Ubiquiti Bullet M" ++ ;; ++ "e30") ++ model="Ubiquiti PicoStation M" ++ ;; ++ esac ++ ++ [ -z "$model" ] || AR71XX_MODEL="${model}${magic:3:1}" ++} ++ ++ubnt_unifi_ac_get_mtd_part_magic() { ++ ar71xx_get_mtd_offset_size_format EEPROM 12 2 %02x ++} ++ ++ubnt_unifi_ac_board_detect() { ++ local model ++ local magic ++ ++ magic="$(ubnt_unifi_ac_get_mtd_part_magic)" ++ case ${magic:0:4} in ++ "e517") ++ model="Ubiquiti UniFi-AC-LITE" ++ ;; ++ "e527") ++ model="Ubiquiti UniFi-AC-LR" ++ ;; ++ "e537") ++ model="Ubiquiti UniFi-AC-PRO" ++ ;; ++ "e557") ++ model="Ubiquiti UniFi-AC-MESH" ++ ;; ++ "e567") ++ model="Ubiquiti UniFi-AC-MESH-PRO" ++ ;; ++ esac ++ ++ [ -z "$model" ] || AR71XX_MODEL="${model}" ++} ++ ++cybertan_get_hw_magic() { ++ local part ++ ++ part=$(find_mtd_part firmware) ++ [ -z "$part" ] && return 1 ++ ++ dd bs=8 count=1 skip=0 if=$part 2>/dev/null | hexdump -v -n 8 -e '1/1 "%02x"' ++} ++ ++dir505_board_detect() { ++ local dev=$(find_mtd_part 'mac') ++ [ -z "$dev" ] && return ++ ++ # The revision is stored at the beginning of the "mac" partition ++ local rev="$(LC_CTYPE=C awk -v 'FS=[^[:print:]]' '{print $1; exit}' $dev)" ++ AR71XX_MODEL="D-Link DIR-505 rev. $rev" ++} ++ ++tplink_get_hwid() { ++ local part ++ ++ part=$(find_mtd_part firmware) ++ [ -z "$part" ] && return 1 ++ ++ dd if=$part bs=4 count=1 skip=16 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++tplink_get_mid() { ++ local part ++ ++ part=$(find_mtd_part firmware) ++ [ -z "$part" ] && return 1 ++ ++ dd if=$part bs=4 count=1 skip=17 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++tplink_board_detect() { ++ local model="$1" ++ local hwid ++ local hwver ++ ++ hwid=$(tplink_get_hwid) ++ mid=$(tplink_get_mid) ++ hwver=${hwid:6:2} ++ hwver=" v${hwver#0}" ++ ++ case "$hwid" in ++ "001001"*) ++ model="TP-Link TL-MR10U" ++ ;; ++ "001101"*) ++ model="TP-Link TL-MR11U" ++ ;; ++ "001201"*) ++ model="TP-Link TL-MR12U" ++ ;; ++ "001301"*) ++ model="TP-Link TL-MR13U" ++ ;; ++ "007260"*) ++ model="TellStick ZNet Lite" ++ ;; ++ "015000"*) ++ model="EasyLink EL-M150" ++ ;; ++ "015300"*) ++ model="EasyLink EL-MINI" ++ ;; ++ "044401"*) ++ model="ANTMINER-S1" ++ ;; ++ "044403"*) ++ model="ANTMINER-S3" ++ ;; ++ "066601"*) ++ model="OMYlink OMY-G1" ++ ;; ++ "066602"*) ++ model="OMYlink OMY-X1" ++ ;; ++ "070100"*) ++ model="TP-Link TL-WA701N/ND" ++ ;; ++ "070301"*) ++ model="TP-Link TL-WR703N" ++ ;; ++ "071000"*) ++ model="TP-Link TL-WR710N" ++ ++ [ "$hwid" = '07100002' -a "$mid" = '00000002' ] && hwver=' v2.1' ++ ;; ++ "072001"*) ++ model="TP-Link TL-WR720N" ++ ;; ++ "073000"*) ++ model="TP-Link TL-WA730RE" ++ ;; ++ "074000"*) ++ model="TP-Link TL-WR740N/ND" ++ ;; ++ "074100"*) ++ model="TP-Link TL-WR741N/ND" ++ ;; ++ "074300"*) ++ model="TP-Link TL-WR743N/ND" ++ ;; ++ "075000"*) ++ model="TP-Link TL-WA750RE" ++ ;; ++ "080100"*) ++ model="TP-Link TL-WA801N/ND" ++ ;; ++ "080200"*) ++ model="TP-Link TL-WR802N" ++ ++ [ "$hwid" = '08020002' -a "$mid" = '00000002' ] && hwver=' v2' ++ ;; ++ "081000"*) ++ model="TP-Link TL-WR810N" ++ ;; ++ "083000"*) ++ model="TP-Link TL-WA830RE" ++ ++ [ "$hwver" = ' v10' ] && hwver=' v1' ++ ;; ++ "084100"*) ++ model="TP-Link TL-WR841N/ND" ++ ++ [ "$hwid" = '08410002' -a "$mid" = '00000002' ] && hwver=' v1.5' ++ ;; ++ "084200"*) ++ model="TP-Link TL-WR842N/ND" ++ ;; ++ "084300"*) ++ model="TP-Link TL-WR843N/ND" ++ ;; ++ "085000"*) ++ model="TP-Link TL-WA850RE" ++ ;; ++ "085500"*) ++ model="TP-Link TL-WA855RE" ++ ;; ++ "086000"*) ++ model="TP-Link TL-WA860RE" ++ ;; ++ "090100"*) ++ model="TP-Link TL-WA901N/ND" ++ ;; ++ "094000"*) ++ model="TP-Link TL-WR940N" ++ ;; ++ "094100"*) ++ model="TP-Link TL-WR941N/ND" ++ ++ [ "$hwid" = "09410002" -a "$mid" = "00420001" ] && { ++ model="Rosewill RNX-N360RT" ++ hwver="" ++ } ++ ;; ++ "104100"*) ++ model="TP-Link TL-WR1041N/ND" ++ ;; ++ "104300"*) ++ model="TP-Link TL-WR1043N/ND" ++ ;; ++ "120000"*) ++ model="MERCURY MAC1200R" ++ ;; ++ "254300"*) ++ model="TP-Link TL-WR2543N/ND" ++ ;; ++ "302000"*) ++ model="TP-Link TL-MR3020" ++ ;; ++ "304000"*) ++ model="TP-Link TL-MR3040" ++ ;; ++ "322000"*) ++ model="TP-Link TL-MR3220" ++ ;; ++ "332000"*) ++ model="TP-Link TL-WDR3320" ++ ;; ++ "342000"*) ++ model="TP-Link TL-MR3420" ++ ;; ++ "350000"*) ++ model="TP-Link TL-WDR3500" ++ ;; ++ "360000"*) ++ model="TP-Link TL-WDR3600" ++ ;; ++ "430000"*) ++ model="TP-Link TL-WDR4300" ++ ;; ++ "430080"*) ++ iw reg set IL ++ model="TP-Link TL-WDR4300 (IL)" ++ ;; ++ "431000"*) ++ model="TP-Link TL-WDR4310" ++ ;; ++ "44440101"*) ++ model="ANTROUTER-R1" ++ ;; ++ "453000"*) ++ model="Mercury MW4530R" ++ ;; ++ "49000002") ++ model="TP-Link TL-WDR4900" ++ ;; ++ "640000"*) ++ model="TP-Link TL-MR6400" ++ ;; ++ "65000002") ++ model="TP-Link TL-WDR6500" ++ ;; ++ "721000"*) ++ model="TP-Link TL-WA7210N" ++ ;; ++ "750000"*|\ ++ "c70000"*) ++ model="TP-Link Archer C7" ++ ;; ++ "751000"*) ++ model="TP-Link TL-WA7510N" ++ ;; ++ "934100"*) ++ model="NC-LINK SMART-300" ++ ;; ++ "c50000"*) ++ model="TP-Link Archer C5" ++ ;; ++ *) ++ hwver="" ++ ;; ++ esac ++ ++ AR71XX_MODEL="$model$hwver" ++} ++ ++tplink_pharos_get_model_string() { ++ local part ++ part=$(find_mtd_part 'product-info') ++ [ -z "$part" ] && return 1 ++ ++ # The returned string will end with \r\n, but we don't remove it here ++ # to simplify matching against it in the sysupgrade image check ++ dd if=$part bs=1 skip=4360 2>/dev/null | head -n 1 ++} ++ ++tplink_pharos_board_detect() { ++ local model_string="$1" ++ local oIFS="$IFS"; IFS=":"; set -- $model_string; IFS="$oIFS" ++ ++ local model="${1%%\(*}" ++ ++ AR71XX_MODEL="TP-Link $model v$2" ++} ++ ++tplink_pharos_v2_get_model_string() { ++ local part ++ part=$(find_mtd_part 'product-info') ++ [ -z "$part" ] && return 1 ++ ++ dd if=$part iflag=skip_bytes bs=64 skip=4360 count=1 2>/dev/null | tr -d '\r\0' | head -n 1 ++} ++ ++mikrotik_board_detect() { ++ local machine="$1" ++ ++ case "$machine" in ++ *"2011iL") ++ name="rb-2011il" ++ ;; ++ *"2011iLS") ++ name="rb-2011ils" ++ ;; ++ *"2011L") ++ name="rb-2011l" ++ ;; ++ *"2011UAS") ++ name="rb-2011uas" ++ ;; ++ *"2011UAS-2HnD") ++ name="rb-2011uas-2hnd" ++ ;; ++ *"2011UiAS") ++ name="rb-2011uias" ++ ;; ++ *"2011UiAS-2HnD") ++ name="rb-2011uias-2hnd" ++ ;; ++ *"2011UiAS-2HnD r2") ++ name="rb-2011uias-2hnd-r2" ++ ;; ++ *"411/A/AH") ++ name="rb-411" ++ ;; ++ *"411U") ++ name="rb-411u" ++ ;; ++ *"433/AH") ++ name="rb-433" ++ ;; ++ *"433UAH") ++ name="rb-433u" ++ ;; ++ *"435G") ++ name="rb-435g" ++ ;; ++ *"450") ++ name="rb-450" ++ ;; ++ *"450G") ++ name="rb-450g" ++ ;; ++ *"493/AH") ++ name="rb-493" ++ ;; ++ *"493G") ++ name="rb-493g" ++ ;; ++ *"750") ++ name="rb-750" ++ ;; ++ *"750 r2"|\ ++ *"750r2") ++ name="rb-750-r2" ++ ;; ++ *"750GL") ++ name="rb-750gl" ++ ;; ++ *"750P r2") ++ name="rb-750p-pbr2" ++ ;; ++ *"750UP r2"|\ ++ *"750UPr2") ++ name="rb-750up-r2" ++ ;; ++ *"751") ++ name="rb-751" ++ ;; ++ *"751G") ++ name="rb-751g" ++ ;; ++ *"911-2Hn") ++ name="rb-911-2hn" ++ ;; ++ *"911-5Hn") ++ name="rb-911-5hn" ++ ;; ++ *"911G-2HPnD") ++ name="rb-911g-2hpnd" ++ ;; ++ *"911G-5HPacD") ++ name="rb-911g-5hpacd" ++ ;; ++ *"911G-5HPnD") ++ name="rb-911g-5hpnd" ++ ;; ++ *"912UAG-2HPnD") ++ name="rb-912uag-2hpnd" ++ ;; ++ *"912UAG-5HPnD") ++ name="rb-912uag-5hpnd" ++ ;; ++ *"921GS-5HPacD r2") ++ name="rb-921gs-5hpacd-r2" ++ ;; ++ *"922UAGS-5HPacD") ++ name="rb-922uags-5hpacd" ++ ;; ++ *"931-2nD") ++ name="rb-931-2nd" ++ ;; ++ *"941-2nD") ++ name="rb-941-2nd" ++ ;; ++ *"951G-2HnD") ++ name="rb-951g-2hnd" ++ ;; ++ *"951Ui-2HnD") ++ name="rb-951ui-2hnd" ++ ;; ++ *"951Ui-2nD") ++ name="rb-951ui-2nd" ++ ;; ++ *"952Ui-5ac2nD") ++ name="rb-952ui-5ac2nd" ++ ;; ++ *"962UiGS-5HacT2HnT") ++ name="rb-962uigs-5hact2hnt" ++ ;; ++ *"LHG 5nD") ++ name="rb-lhg-5nd" ++ ;; ++ *"mAP 2nD"|\ ++ *"mAP2nD") ++ name="rb-map-2nd" ++ ;; ++ *"mAP L-2nD"|\ ++ *"mAPL-2nD") ++ name="rb-mapl-2nd" ++ ;; ++ *"SXT 2nD r3") ++ name="rb-sxt-2nd-r3" ++ ;; ++ *"SXT Lite2") ++ name="rb-sxt2n" ++ ;; ++ *"SXT Lite5") ++ name="rb-sxt5n" ++ ;; ++ *"wAP 2nD r2") ++ name="rb-wap-2nd" ++ ;; ++ *"wAP R-2nD"|\ ++ *"wAPR-2nD") ++ name="rb-wapr-2nd" ++ ;; ++ *"wAP G-5HacT2HnD"|\ ++ *"wAPG-5HacT2HnD") ++ name="rb-wapg-5hact2hnd" ++ ;; ++ esac ++ ++ echo "$name" ++} ++ ++ar71xx_board_detect() { ++ local machine ++ local name ++ ++ machine=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /machine/ {print $2}' /proc/cpuinfo) ++ ++ case "$machine" in ++ *"A40") ++ name="a40" ++ ;; ++ *"A60") ++ name="a60" ++ ;; ++ *"AC1750DB") ++ name="f9k1115v2" ++ ;; ++ *"AirGateway") ++ name="airgateway" ++ ;; ++ *"AirGateway Pro") ++ name="airgatewaypro" ++ ;; ++ *"AirRouter") ++ name="airrouter" ++ ;; ++ *"ALFA Network AP120C") ++ name="alfa-ap120c" ++ ;; ++ *"ALFA Network AP96") ++ name="alfa-ap96" ++ ;; ++ *"ALFA Network N2/N5") ++ name="alfa-nx" ++ ;; ++ *"ALL0258N") ++ name="all0258n" ++ ;; ++ *"ALL0305") ++ name="all0305" ++ ;; ++ *"ALL0315N") ++ name="all0315n" ++ ;; ++ *"Antminer-S1") ++ name="antminer-s1" ++ ;; ++ *"Antminer-S3") ++ name="antminer-s3" ++ ;; ++ *"AP121 reference board") ++ name="ap121" ++ ;; ++ *"AP121-MINI") ++ name="ap121-mini" ++ ;; ++ *"AP121F") ++ name="ap121f" ++ ;; ++ *"AP132 reference board") ++ name="ap132" ++ ;; ++ *"AP135-020 reference board") ++ name="ap135-020" ++ ;; ++ *"AP136-010 reference board") ++ name="ap136-010" ++ ;; ++ *"AP136-020 reference board") ++ name="ap136-020" ++ ;; ++ *"AP143 reference board") ++ name="ap143" ++ ;; ++ *"AP147-010 reference board") ++ name="ap147-010" ++ ;; ++ *"AP152 reference board") ++ name="ap152" ++ ;; ++ *"AP531B0") ++ name="ap531b0" ++ ;; ++ *"AP90Q") ++ name="ap90q" ++ ;; ++ *"AP91-5G") ++ name="ap91-5g" ++ ;; ++ *"Archer C25 v1") ++ name="archer-c25-v1" ++ ;; ++ *"Archer C5") ++ name="archer-c5" ++ ;; ++ *"Archer C7 v4") ++ name="archer-c7-v4" ++ ;; ++ *"Archer C7 v5") ++ name="archer-c7-v5" ++ ;; ++ *"Archer C58 v1") ++ name="archer-c58-v1" ++ ;; ++ *"Archer C59 v1") ++ name="archer-c59-v1" ++ ;; ++ *"Archer C59 v2") ++ name="archer-c59-v2" ++ ;; ++ *"Archer C60 v1") ++ name="archer-c60-v1" ++ ;; ++ *"Archer C60 v2") ++ name="archer-c60-v2" ++ ;; ++ *"Archer C7") ++ name="archer-c7" ++ ;; ++ *"Arduino Yun") ++ name="arduino-yun" ++ ;; ++ *"Atheros AP96") ++ name="ap96" ++ ;; ++ *"AW-NR580") ++ name="aw-nr580" ++ ;; ++ *"BHR-4GRV2") ++ name="bhr-4grv2" ++ ;; ++ *"Black Swift board"*) ++ name="bsb" ++ ;; ++ *"Bullet M") ++ name="bullet-m" ++ ubnt_xm_board_detect ++ ;; ++ *"Bullet M XW") ++ name="bullet-m-xw" ++ ;; ++ *"BXU2000n-2 rev. A1") ++ name="bxu2000n-2-a1" ++ ;; ++ *"C-55") ++ name="c-55" ++ ;; ++ *"C-60") ++ name="c-60" ++ ;; ++ *"CAP324") ++ name="cap324" ++ ;; ++ *"CAP4200AG") ++ name="cap4200ag" ++ ;; ++ *"Carambola2"*) ++ name="carambola2" ++ ;; ++ *"CF-E316N v2") ++ name="cf-e316n-v2" ++ ;; ++ *"CF-E320N v2") ++ name="cf-e320n-v2" ++ ;; ++ *"CF-E355AC v1") ++ name="cf-e355ac-v1" ++ ;; ++ *"CF-E355AC v2") ++ name="cf-e355ac-v2" ++ ;; ++ *"CF-E375AC") ++ name="cf-e375ac" ++ ;; ++ *"CF-E380AC v1") ++ name="cf-e380ac-v1" ++ ;; ++ *"CF-E380AC v2") ++ name="cf-e380ac-v2" ++ ;; ++ *"CF-E385AC") ++ name="cf-e385ac" ++ ;; ++ *"CF-E520N") ++ name="cf-e520n" ++ ;; ++ *"CF-E530N") ++ name="cf-e530n" ++ ;; ++ *"CPE210/220") ++ name="cpe210" ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" ++ ;; ++ *"CPE210 v2") ++ name="cpe210-v2" ++ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" ++ ;; ++ *"CPE210 v3") ++ name="cpe210-v3" ++ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" ++ ;; ++ *"CPE505N") ++ name="cpe505n" ++ ;; ++ *"CPE510/520") ++ name="cpe510" ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" ++ ;; ++ *"CPE510 v2") ++ name="cpe510-v2" ++ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" ++ ;; ++ *"CPE830") ++ name="cpe830" ++ ;; ++ *"CPE870") ++ name="cpe870" ++ ;; ++ *"CR3000") ++ name="cr3000" ++ ;; ++ *"CR5000") ++ name="cr5000" ++ ;; ++ *"DAP-1330 Rev. A1") ++ name="dap-1330-a1" ++ ;; ++ *"DAP-2695 rev. A1") ++ name="dap-2695-a1" ++ ;; ++ *"DB120 reference board") ++ name="db120" ++ ;; ++ *"DGL-5500 rev. A1") ++ name="dgl-5500-a1" ++ ;; ++ *"DHP-1565 rev. A1") ++ name="dhp-1565-a1" ++ ;; ++ *"DIR-505 rev. A1") ++ name="dir-505-a1" ++ dir505_board_detect ++ ;; ++ *"DIR-600 rev. A1") ++ name="dir-600-a1" ++ ;; ++ *"DIR-615 rev. C1") ++ name="dir-615-c1" ++ ;; ++ *"DIR-615 rev. E1") ++ name="dir-615-e1" ++ ;; ++ *"DIR-615 rev. E4") ++ name="dir-615-e4" ++ ;; ++ *"DIR-615 rev. I1") ++ name="dir-615-i1" ++ ;; ++ *"DIR-825 rev. B1") ++ name="dir-825-b1" ++ ;; ++ *"DIR-825 rev. C1") ++ name="dir-825-c1" ++ ;; ++ *"DIR-835 rev. A1") ++ name="dir-835-a1" ++ ;; ++ *"DIR-869 rev. A1") ++ name="dir-869-a1" ++ ;; ++ *"dLAN Hotspot") ++ name="dlan-hotspot" ++ ;; ++ *"dLAN pro 1200+ WiFi ac") ++ name="dlan-pro-1200-ac" ++ ;; ++ *"dLAN pro 500 Wireless+") ++ name="dlan-pro-500-wp" ++ ;; ++ *"Domino Pi") ++ name="gl-domino" ++ ;; ++ *"DR342") ++ name="dr342" ++ ;; ++ *"DR344") ++ name="dr344" ++ ;; ++ *"DR531") ++ name="dr531" ++ ;; ++ *"Dragino v2") ++ name="dragino2" ++ ;; ++ *"DW33D") ++ name="dw33d" ++ ;; ++ *"E1700AC v2") ++ name="e1700ac-v2" ++ ;; ++ *"E2100L") ++ name="e2100l" ++ ;; ++ *"E558 v2") ++ name="e558-v2" ++ ;; ++ *"E600G v2") ++ name="e600g-v2" ++ ;; ++ *"E600GAC v2") ++ name="e600gac-v2" ++ ;; ++ *"E750A v4") ++ name="e750a-v4" ++ ;; ++ *"E750G v8") ++ name="e750g-v8" ++ ;; ++ *"EAP120") ++ name="eap120" ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" ++ ;; ++ *"EAP300 v2") ++ name="eap300v2" ++ ;; ++ *"EAP7660D") ++ name="eap7660d" ++ ;; ++ *"EBR-2310 rev. C1") ++ name="ebr-2310-c1" ++ ;; ++ *"EL-M150") ++ name="el-m150" ++ ;; ++ *"EL-MINI") ++ name="el-mini" ++ ;; ++ *"EmbWir-Balin") ++ name="ew-balin" ++ ;; ++ *"EmbWir-Dorin") ++ name="ew-dorin" ++ ;; ++ *"EmbWir-Dorin-Router") ++ name="ew-dorin-router" ++ ;; ++ *"ENS202EXT") ++ name="ens202ext" ++ ;; ++ *"EPG5000") ++ name="epg5000" ++ ;; ++ *"ESR1750") ++ name="esr1750" ++ ;; ++ *"ESR900") ++ name="esr900" ++ ;; ++ *"eTactica EG-200") ++ name="rme-eg200" ++ ;; ++ *"FRITZ!Box 4020") ++ name="fritz4020" ++ ;; ++ *"FRITZ!WLAN Repeater 300E") ++ name="fritz300e" ++ ;; ++ *"FRITZ!WLAN Repeater 450E") ++ name="fritz450e" ++ ;; ++ *"GL-AR150") ++ name="gl-ar150" ++ ;; ++ *"GL-AR300") ++ name="gl-ar300" ++ ;; ++ *"GL-AR300M") ++ name="gl-ar300m" ++ ;; ++ *"GL-AR750") ++ name="gl-ar750" ++ ;; ++ *"GL-AR750S") ++ name="gl-ar750s" ++ ;; ++ *"GL-CONNECT INET v1") ++ name="gl-inet" ++ ++ local size="$(mtd_get_part_size 'firmware')" ++ ++ [ "$size" = "8192000" ] && AR71XX_MODEL="GL-iNet 6408A v1" ++ [ "$size" = "16580608" ] && AR71XX_MODEL="GL-iNet 6416A v1" ++ ;; ++ *"GL-MIFI") ++ name="gl-mifi" ++ ;; ++ *"GL-USB150") ++ name="gl-usb150" ++ ;; ++ *"HiveAP-121") ++ name="hiveap-121" ++ ;; ++ *"HiWiFi HC6361") ++ name="hiwifi-hc6361" ++ ;; ++ *"Hornet-UB") ++ local size="$(mtd_get_part_size 'firmware')" ++ ++ [ "$size" = "7929856" ] && name="hornet-ub" ++ [ "$size" = "16318464" ] && name="hornet-ub-x2" ++ ;; ++ *"JA76PF") ++ name="ja76pf" ++ ;; ++ *"JA76PF2") ++ name="ja76pf2" ++ ;; ++ *"JWAP003") ++ name="jwap003" ++ ;; ++ *"JWAP230") ++ name="jwap230" ++ ;; ++ *"Koala") ++ name="koala" ++ ;; ++ *"LAN Turtle") ++ name="lan-turtle" ++ ;; ++ *"Lima"*) ++ name="lima" ++ ;; ++ *"Litebeam M5"*) ++ name="lbe-m5" ++ ;; ++ *"Loco M XW") ++ name="loco-m-xw" ++ ;; ++ *"LS-SR71") ++ name="ls-sr71" ++ ;; ++ *"MAC1200R") ++ name="mc-mac1200r" ++ ;; ++ "MikroTik"*|\ ++ "Mikrotik"*) ++ name=$(mikrotik_board_detect "$machine") ++ ;; ++ *"MiniBox V1.0") ++ name="minibox-v1" ++ ;; ++ *"Minibox V3.2") ++ name="minibox-v3.2" ++ ;; ++ *"MR12") ++ name="mr12" ++ ;; ++ *"MR16") ++ name="mr16" ++ ;; ++ *"MR1750") ++ name="mr1750" ++ ;; ++ *"MR1750v2") ++ name="mr1750v2" ++ ;; ++ *"MR18") ++ name="mr18" ++ ;; ++ *"MR600") ++ name="mr600" ++ ;; ++ *"MR600v2") ++ name="mr600v2" ++ ;; ++ *"MR900") ++ name="mr900" ++ ;; ++ *"MR900v2") ++ name="mr900v2" ++ ;; ++ *"My Net N600") ++ name="mynet-n600" ++ ;; ++ *"My Net N750") ++ name="mynet-n750" ++ ;; ++ *"My Net Wi-Fi Range Extender") ++ name="mynet-rext" ++ ;; ++ *"MZK-W04NU") ++ name="mzk-w04nu" ++ ;; ++ *"MZK-W300NH") ++ name="mzk-w300nh" ++ ;; ++ *"N5Q") ++ name="n5q" ++ ;; ++ *"Nanostation M") ++ name="nanostation-m" ++ ubnt_xm_board_detect ++ ;; ++ *"Nanostation M XW") ++ name="nanostation-m-xw" ++ ;; ++ *"NBG460N/550N/550NH") ++ name="nbg460n_550n_550nh" ++ ;; ++ *"NBG6616") ++ name="nbg6616" ++ ;; ++ *"NBG6716") ++ name="nbg6716" ++ ;; ++ *"OM2P") ++ name="om2p" ++ ;; ++ *"OM2P HS") ++ name="om2p-hs" ++ ;; ++ *"OM2P HSv2") ++ name="om2p-hsv2" ++ ;; ++ *"OM2P HSv3") ++ name="om2p-hsv3" ++ ;; ++ *"OM2P HSv4") ++ name="om2p-hsv4" ++ ;; ++ *"OM2P LC") ++ name="om2p-lc" ++ ;; ++ *"OM2Pv2") ++ name="om2pv2" ++ ;; ++ *"OM2Pv4") ++ name="om2pv4" ++ ;; ++ *"OM5P") ++ name="om5p" ++ ;; ++ *"OM5P AC") ++ name="om5p-ac" ++ ;; ++ *"OM5P ACv2") ++ name="om5p-acv2" ++ ;; ++ *"OM5P AN") ++ name="om5p-an" ++ ;; ++ *"OMY-G1") ++ name="omy-g1" ++ ;; ++ *"OMY-X1") ++ name="omy-x1" ++ ;; ++ *"Onion Omega") ++ name="onion-omega" ++ ;; ++ *"Oolite V1.0") ++ name="oolite-v1" ++ ;; ++ *"Packet Squirrel") ++ name="packet-squirrel" ++ ;; ++ *"Oolite V5.2") ++ name="oolite-v5.2" ++ ;; ++ *"Oolite V5.2-Dev") ++ name="oolite-v5.2-dev" ++ ;; ++ *"PB42") ++ name="pb42" ++ ;; ++ *"PB44 reference board") ++ name="pb44" ++ ;; ++ *"PQI Air Pen") ++ name="pqi-air-pen" ++ ;; ++ *"Qihoo 360 C301") ++ name="qihoo-c301" ++ ;; ++ *"R36A") ++ name="r36a" ++ ;; ++ *"R602N") ++ name="r602n" ++ ;; ++ *"R6100") ++ name="r6100" ++ ;; ++ *"Rambutan"*) ++ name="rambutan" ++ ;; ++ *"RE355") ++ name="re355" ++ ;; ++ *"RE450") ++ name="re450" ++ ;; ++ *"Rocket M") ++ name="rocket-m" ++ ubnt_xm_board_detect ++ ;; ++ *"Rocket M TI") ++ name="rocket-m-ti" ++ ;; ++ *"Rocket M XW") ++ name="rocket-m-xw" ++ ;; ++ *"RouterStation") ++ name="routerstation" ++ ;; ++ *"RouterStation Pro") ++ name="routerstation-pro" ++ ;; ++ *"RUT900") ++ name="rut900" ++ ;; ++ *"RW2458N") ++ name="rw2458n" ++ ;; ++ *"SC1750") ++ name="sc1750" ++ ;; ++ *"SC300M") ++ name="sc300m" ++ ;; ++ *"SC450") ++ name="sc450" ++ ;; ++ *"SMART-300") ++ name="smart-300" ++ ;; ++ *"SOM9331") ++ name="som9331" ++ ;; ++ *"SR3200") ++ name="sr3200" ++ ;; ++ *"T830") ++ name="t830" ++ ;; ++ *"TellStick ZNet Lite") ++ name="tellstick-znet-lite" ++ ;; ++ *"TEW-632BRP") ++ name="tew-632brp" ++ ;; ++ *"TEW-673GRU") ++ name="tew-673gru" ++ ;; ++ *"TEW-712BR") ++ name="tew-712br" ++ ;; ++ *"TEW-732BR") ++ name="tew-732br" ++ ;; ++ *"TEW-823DRU") ++ name="tew-823dru" ++ ;; ++ *"TL-MR10U") ++ name="tl-mr10u" ++ ;; ++ *"TL-MR11U") ++ name="tl-mr11u" ++ ;; ++ *"TL-MR12U") ++ name="tl-mr12u" ++ ;; ++ *"TL-MR13U v1") ++ name="tl-mr13u" ++ ;; ++ *"TL-MR3020") ++ name="tl-mr3020" ++ ;; ++ *"TL-MR3040") ++ name="tl-mr3040" ++ ;; ++ *"TL-MR3040 v2") ++ name="tl-mr3040-v2" ++ ;; ++ *"TL-MR3220") ++ name="tl-mr3220" ++ ;; ++ *"TL-MR3220 v2") ++ name="tl-mr3220-v2" ++ ;; ++ *"TL-MR3420") ++ name="tl-mr3420" ++ ;; ++ *"TL-MR3420 v2") ++ name="tl-mr3420-v2" ++ ;; ++ *"TL-MR6400") ++ name="tl-mr6400" ++ ;; ++ *"TL-WA701ND v2") ++ name="tl-wa701nd-v2" ++ ;; ++ *"TL-WA7210N v2") ++ name="tl-wa7210n-v2" ++ ;; ++ *"TL-WA750RE") ++ name="tl-wa750re" ++ ;; ++ *"TL-WA7510N v1") ++ name="tl-wa7510n" ++ ;; ++ *"TL-WA801ND v2") ++ name="tl-wa801nd-v2" ++ ;; ++ *"TL-WA801ND v3") ++ name="tl-wa801nd-v3" ++ ;; ++ *"TL-WA830RE v2") ++ name="tl-wa830re-v2" ++ ;; ++ *"TL-WA850RE") ++ name="tl-wa850re" ++ ;; ++ *"TL-WA850RE v2") ++ name="tl-wa850re-v2" ++ ;; ++ *"TL-WA855RE v1") ++ name="tl-wa855re-v1" ++ ;; ++ *"TL-WA860RE") ++ name="tl-wa860re" ++ ;; ++ *"TL-WA901ND") ++ name="tl-wa901nd" ++ ;; ++ *"TL-WA901ND v2") ++ name="tl-wa901nd-v2" ++ ;; ++ *"TL-WA901ND v3") ++ name="tl-wa901nd-v3" ++ ;; ++ *"TL-WA901ND v4") ++ name="tl-wa901nd-v4" ++ ;; ++ *"TL-WA901ND v5") ++ name="tl-wa901nd-v5" ++ ;; ++ *"TL-WDR3320 v2") ++ name="tl-wdr3320-v2" ++ ;; ++ *"TL-WDR3500") ++ name="tl-wdr3500" ++ ;; ++ *"TL-WDR3600/4300/4310") ++ name="tl-wdr4300" ++ ;; ++ *"TL-WDR4900 v2") ++ name="tl-wdr4900-v2" ++ ;; ++ *"TL-WDR6500 v2") ++ name="tl-wdr6500-v2" ++ ;; ++ *"TL-WPA8630") ++ name="tl-wpa8630" ++ ;; ++ *"TL-WR1041N v2") ++ name="tl-wr1041n-v2" ++ ;; ++ *"TL-WR1043N v5") ++ name="tl-wr1043n-v5" ++ ;; ++ *"TL-WR1043ND") ++ name="tl-wr1043nd" ++ ;; ++ *"TL-WR1043ND v2") ++ name="tl-wr1043nd-v2" ++ ;; ++ *"TL-WR1043ND v4") ++ name="tl-wr1043nd-v4" ++ ;; ++ *"TL-WR2543N"*) ++ name="tl-wr2543n" ++ ;; ++ *"TL-WR703N v1") ++ name="tl-wr703n" ++ ;; ++ *"TL-WR710N v1") ++ name="tl-wr710n" ++ ;; ++ *"TL-WR720N"*) ++ name="tl-wr720n-v3" ++ ;; ++ *"TL-WR740N/ND v6") ++ name="tl-wr740n-v6" ++ ;; ++ *"TL-WR741ND") ++ name="tl-wr741nd" ++ ;; ++ *"TL-WR741ND v4") ++ name="tl-wr741nd-v4" ++ ;; ++ *"TL-WR802N v1") ++ name="tl-wr802n-v1" ++ ;; ++ *"TL-WR802N v2") ++ name="tl-wr802n-v2" ++ ;; ++ *"TL-WR810N") ++ name="tl-wr810n" ++ ;; ++ *"TL-WR810N v2") ++ name="tl-wr810n-v2" ++ ;; ++ *"TL-WR840N v2") ++ name="tl-wr840n-v2" ++ ;; ++ *"TL-WR840N v3") ++ name="tl-wr840n-v3" ++ ;; ++ *"TL-WR841N v1") ++ name="tl-wr841n-v1" ++ ;; ++ *"TL-WR841N/ND v11") ++ name="tl-wr841n-v11" ++ ;; ++ *"TL-WR841N/ND v7") ++ name="tl-wr841n-v7" ++ ;; ++ *"TL-WR841N/ND v8") ++ name="tl-wr841n-v8" ++ ;; ++ *"TL-WR841N/ND v9") ++ name="tl-wr841n-v9" ++ ;; ++ *"TL-WR842N/ND v2") ++ name="tl-wr842n-v2" ++ ;; ++ *"TL-WR842N/ND v3") ++ name="tl-wr842n-v3" ++ ;; ++ *"TL-WR902AC v1") ++ name="tl-wr902ac-v1" ++ ;; ++ *"TL-WR940N v4") ++ name="tl-wr940n-v4" ++ ;; ++ *"TL-WR940N v6") ++ name="tl-wr940n-v6" ++ ;; ++ *"TL-WR941N/ND v5") ++ name="tl-wr941nd-v5" ++ ;; ++ *"TL-WR941N/ND v6") ++ name="tl-wr941nd-v6" ++ ;; ++ *"TL-WR941ND") ++ name="tl-wr941nd" ++ ;; ++ *"TL-WR942N v1") ++ name="tl-wr942n-v1" ++ ;; ++ *"TS-D084") ++ name="ts-d084" ++ ;; ++ *"Tube2H") ++ name="tube2h" ++ ;; ++ *"UniFi") ++ name="unifi" ++ ;; ++ *"UniFi AP Pro") ++ name="uap-pro" ++ ;; ++ *"UniFi-AC-LITE/MESH") ++ name="unifiac-lite" ++ ubnt_unifi_ac_board_detect ++ ;; ++ *"UniFi-AC-PRO/MESH-PRO") ++ name="unifiac-pro" ++ ubnt_unifi_ac_board_detect ++ ;; ++ *"UniFiAP Outdoor") ++ name="unifi-outdoor" ++ ;; ++ *"UniFiAP Outdoor+") ++ name="unifi-outdoor-plus" ++ ;; ++ *"WAM250") ++ name="wam250" ++ ;; ++ *"WBS210") ++ name="wbs210" ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" ++ ;; ++ *"WBS510") ++ name="wbs510" ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" ++ ;; ++ "WeIO"*) ++ name="weio" ++ ;; ++ *"WI2A-AC200i") ++ name="wi2a-ac200i" ++ ;; ++ *"WHR-G301N") ++ name="whr-g301n" ++ ;; ++ *"WHR-HP-G300N") ++ name="whr-hp-g300n" ++ ;; ++ *"WHR-HP-GN") ++ name="whr-hp-gn" ++ ;; ++ *"WiFi Pineapple NANO") ++ name="wifi-pineapple-nano" ++ ;; ++ *"WLAE-AG300N") ++ name="wlae-ag300n" ++ ;; ++ *"WLR-8100") ++ name="wlr8100" ++ ;; ++ *"WNDAP360") ++ name="wndap360" ++ ;; ++ *"WNDR3700/WNDR3800/WNDRMAC") ++ wndr3700_board_detect "$machine" ++ ;; ++ *"WNDR3700v4") ++ name="wndr3700v4" ++ ;; ++ *"WNDR4300") ++ name="wndr4300" ++ ;; ++ *"WNR1000 V2") ++ name="wnr1000-v2" ++ ;; ++ *"WNR2000") ++ name="wnr2000" ++ ;; ++ *"WNR2000 V3") ++ name="wnr2000-v3" ++ ;; ++ *"WNR2000 V4") ++ name="wnr2000-v4" ++ ;; ++ *"WNR2200") ++ name="wnr2200" ++ ;; ++ *"WNR612 V2") ++ name="wnr612-v2" ++ ;; ++ *"WP543") ++ name="wp543" ++ ;; ++ *"WPE72") ++ name="wpe72" ++ ;; ++ *"WPJ342") ++ name="wpj342" ++ ;; ++ *"WPJ344") ++ name="wpj344" ++ ;; ++ *"WPJ531") ++ name="wpj531" ++ ;; ++ *"WPJ558") ++ name="wpj558" ++ ;; ++ *"WPJ563") ++ name="wpj563" ++ ;; ++ *"WPN824N") ++ name="wpn824n" ++ ;; ++ *"WRT160NL") ++ name="wrt160nl" ++ ;; ++ *"WRT400N") ++ name="wrt400n" ++ ;; ++ *"WRTnode2Q"*) ++ name="wrtnode2q" ++ ;; ++ *"WZR-450HP2") ++ name="wzr-450hp2" ++ ;; ++ *"WZR-HP-AG300H/WZR-600DHP") ++ name="wzr-hp-ag300h" ++ ;; ++ *"WZR-HP-G300NH") ++ name="wzr-hp-g300nh" ++ ;; ++ *"WZR-HP-G300NH2") ++ name="wzr-hp-g300nh2" ++ ;; ++ *"WZR-HP-G450H") ++ name="wzr-hp-g450h" ++ ;; ++ *"XD3200") ++ name="xd3200" ++ ;; ++ *"Z1") ++ name="z1" ++ ;; ++ *"ZBT-WE1526") ++ name="zbt-we1526" ++ ;; ++ *"ZCN-1523H-2") ++ name="zcn-1523h-2" ++ ;; ++ *"ZCN-1523H-5") ++ name="zcn-1523h-5" ++ ;; ++ esac ++ ++ [ -z "$AR71XX_MODEL" ] && [ "${machine:0:8}" = 'TP-LINK ' ] && \ ++ tplink_board_detect "$machine" ++ ++ [ -z "$name" ] && name="unknown" ++ ++ [ -z "$AR71XX_BOARD_NAME" ] && AR71XX_BOARD_NAME="$name" ++ [ -z "$AR71XX_MODEL" ] && AR71XX_MODEL="$machine" ++ ++ [ -e "/tmp/sysinfo/" ] || mkdir -p "/tmp/sysinfo/" ++ ++ echo "$AR71XX_BOARD_NAME" > /tmp/sysinfo/board_name ++ echo "$AR71XX_MODEL" > /tmp/sysinfo/model ++} +diff --git a/target/linux/ar71xx/base-files/lib/preinit/01_preinit_do_ar71xx.sh b/target/linux/ar71xx/base-files/lib/preinit/01_preinit_do_ar71xx.sh +new file mode 100644 +index 0000000000..ff5407a0d4 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/preinit/01_preinit_do_ar71xx.sh +@@ -0,0 +1,9 @@ ++#!/bin/sh ++ ++do_ar71xx() { ++ . /lib/ar71xx.sh ++ ++ ar71xx_board_detect ++} ++ ++boot_hook_add preinit_main do_ar71xx +diff --git a/target/linux/ar71xx/base-files/lib/preinit/05_set_iface_mac_ar71xx b/target/linux/ar71xx/base-files/lib/preinit/05_set_iface_mac_ar71xx +new file mode 100644 +index 0000000000..b0aa150817 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/preinit/05_set_iface_mac_ar71xx +@@ -0,0 +1,60 @@ ++# ++# Copyright (C) 2009 OpenWrt.org ++# ++ ++fetch_mac_from_mtd() { ++ local mtd_part=$1 ++ local lan_env=$2 ++ local wan_env=$3 ++ local mtd mac ++ ++ mtd=$(grep $mtd_part /proc/mtd | cut -d: -f1) ++ [ -z $mtd ] && return ++ ++ mac=$(grep $lan_env /dev/$mtd | cut -d= -f2) ++ [ ! -z $mac ] && ifconfig eth0 hw ether $mac 2>/dev/null ++ ++ mac=$(grep $wan_env /dev/$mtd | cut -d= -f2) ++ [ ! -z $mac ] && ifconfig eth1 hw ether $mac 2>/dev/null ++} ++ ++preinit_set_mac_address() { ++ . /lib/functions.sh ++ ++ case $(board_name) in ++ c-55|\ ++ c-60) ++ mac_lan=$(mtd_get_mac_binary art 0x0) ++ [ -n "$mac_lan" ] && ifconfig eth0 hw ether "$mac_lan" ++ ;; ++ dir-615-c1|\ ++ tew-632brp) ++ fetch_mac_from_mtd config lan_mac wan_mac ++ ;; ++ dir-615-i1) ++ fetch_mac_from_mtd nvram sys_lan_mac sys_wan_mac ++ ;; ++ mr18|\ ++ z1) ++ mac_lan=$(mtd_get_mac_binary_ubi board-config 0x66) ++ [ -n "$mac_lan" ] && ifconfig eth0 hw ether "$mac_lan" ++ ;; ++ r6100) ++ mac_lan=$(mtd_get_mac_binary caldata 0x0) ++ [ -n "$mac_lan" ] && ifconfig eth1 hw ether "$mac_lan" ++ mac_wan=$(mtd_get_mac_binary caldata 0x6) ++ [ -n "$mac_wan" ] && ifconfig eth0 hw ether "$mac_wan" ++ ;; ++ rambutan) ++ mac_lan=$(mtd_get_mac_binary art 0x0) ++ [ -n "$mac_lan" ] && ifconfig eth0 hw ether "$mac_lan" ++ mac_wan=$(mtd_get_mac_binary art 0x6) ++ [ -n "$mac_wan" ] && ifconfig eth1 hw ether "$mac_wan" ++ ;; ++ wrt160nl) ++ fetch_mac_from_mtd nvram lan_hwaddr wan_hwaddr ++ ;; ++ esac ++} ++ ++boot_hook_add preinit_main preinit_set_mac_address +diff --git a/target/linux/ar71xx/base-files/lib/preinit/05_set_preinit_iface_ar71xx b/target/linux/ar71xx/base-files/lib/preinit/05_set_preinit_iface_ar71xx +new file mode 100644 +index 0000000000..68875fa1ec +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/preinit/05_set_preinit_iface_ar71xx +@@ -0,0 +1,57 @@ ++#!/bin/sh ++ ++# ++# Copyright (C) 2009 OpenWrt.org ++# ++ ++set_preinit_iface() { ++ . /lib/functions.sh ++ ++ case $(board_name) in ++ alfa-ap96|\ ++ alfa-nx|\ ++ ap135-020|\ ++ ap136-020|\ ++ ap147-010|\ ++ archer-c5|\ ++ archer-c7|\ ++ bhr-4grv2|\ ++ dir-505-a1|\ ++ gl-ar750|\ ++ gl-inet|\ ++ jwap003|\ ++ pb42|\ ++ pb44|\ ++ rb-433|\ ++ rb-433u|\ ++ rb-435g|\ ++ rb-450|\ ++ rb-450g|\ ++ routerstation|\ ++ routerstation-pro|\ ++ smart-300|\ ++ tl-mr3420-v2|\ ++ tl-wdr4900-v2|\ ++ tl-wr1043nd-v2|\ ++ tl-wr710n|\ ++ tl-wr720n-v3|\ ++ tl-wr841n-v8|\ ++ tl-wr842n-v2|\ ++ tl-wr940n-v4|\ ++ tl-wr940n-v6|\ ++ tl-wr941nd-v6|\ ++ wnr1000-v2|\ ++ wnr2000-v3|\ ++ wnr2200|\ ++ wnr612-v2|\ ++ wpe72|\ ++ wpn824n) ++ ifname=eth1 ++ ;; ++ *) ++ ifname=eth0 ++ ;; ++ esac ++} ++ ++boot_hook_add preinit_main set_preinit_iface +diff --git a/target/linux/ar71xx/base-files/lib/preinit/82_patch_ath10k b/target/linux/ar71xx/base-files/lib/preinit/82_patch_ath10k +new file mode 100644 +index 0000000000..cc3dc42c9c +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/preinit/82_patch_ath10k +@@ -0,0 +1,50 @@ ++#!/bin/sh ++ ++. /lib/functions.sh ++. /lib/functions/system.sh ++ ++do_patch_ath10k_firmware() { ++ local firmware_file="/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin" ++ ++ # bail out if firmware does not exist ++ [ -f "$firmware_file" ] || return ++ ++ local mac_offset=276 ++ local mac_length=6 ++ local default_mac="00:03:07:12:34:56" ++ local current_mac="$(hexdump -v -n $mac_length -s $mac_offset -e '5/1 "%02x:" 1/1 "%02x"' $firmware_file 2>/dev/null)" ++ ++ # check if mac address was already patched ++ [ "$default_mac" = "$current_mac" ] || return ++ ++ # some boards have bogus mac in otp (= directly in the PCIe card's EEPROM). ++ # we have to patch the default mac in the firmware because we cannot change ++ # the otp. ++ case $(board_name) in ++ dgl-5500-a1|\ ++ tew-823dru) ++ local mac ++ mac=$(mtd_get_mac_ascii nvram wlan1_mac) ++ ++ cp $firmware_file /tmp/ath10k-firmware.bin ++ macaddr_2bin $mac | dd of=/tmp/ath10k-firmware.bin \ ++ conv=notrunc bs=1 seek=$mac_offset count=$mac_length ++ ;; ++ esac ++ ++ [ -f /tmp/ath10k-firmware.bin ] || return ++ ++ cp /tmp/ath10k-firmware.bin $firmware_file ++ rm /tmp/ath10k-firmware.bin ++} ++ ++check_patch_ath10k_firmware() { ++ case $(board_name) in ++ dgl-5500-a1|\ ++ tew-823dru) ++ do_patch_ath10k_firmware ++ ;; ++ esac ++} ++ ++boot_hook_add preinit_main check_patch_ath10k_firmware +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/allnet.sh b/target/linux/ar71xx/base-files/lib/upgrade/allnet.sh +new file mode 100644 +index 0000000000..5295d8cfe0 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/upgrade/allnet.sh +@@ -0,0 +1,155 @@ ++# The U-Boot loader of the some Allnet devices requires image sizes and ++# checksums to be provided in the U-Boot environment. ++# In case the check fails during boot, a failsafe-system is started to provide ++# a minimal web-interface for flashing a new firmware. ++ ++# determine size of the main firmware partition ++platform_get_firmware_size() { ++ local dev size erasesize name ++ while read dev size erasesize name; do ++ name=${name#'"'}; name=${name%'"'} ++ case "$name" in ++ firmware) ++ printf "%d" "0x$size" ++ break ++ ;; ++ esac ++ done < /proc/mtd ++} ++ ++# get the first 4 bytes (magic) of a given file starting at offset in hex format ++get_magic_long_at() { ++ dd if="$1" skip=$(( $CI_BLKSZ / 4 * $2 )) bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++get_filesize() { ++ wc -c "$1" | while read image_size _n ; do echo $image_size ; break; done ++} ++ ++# scan through the update image pages until matching a magic ++platform_get_offset() { ++ offsetcount=0 ++ magiclong="x" ++ if [ -n "$3" ]; then ++ offsetcount=$3 ++ fi ++ while magiclong=$( get_magic_long_at "$1" "$offsetcount" ) && [ -n "$magiclong" ]; do ++ case "$magiclong" in ++ "2705"*) ++ # U-Boot image magic ++ if [ "$2" = "uImage" ]; then ++ echo $offsetcount ++ return ++ fi ++ ;; ++ "68737173"|"73717368") ++ # SquashFS ++ if [ "$2" = "rootfs" ]; then ++ echo $offsetcount ++ return ++ fi ++ ;; ++ "deadc0de"|"19852003") ++ # JFFS2 empty page ++ if [ "$2" = "rootfs-data" ]; then ++ echo $offsetcount ++ return ++ fi ++ ;; ++ esac ++ offsetcount=$(( $offsetcount + 1 )) ++ done ++} ++ ++platform_check_image_allnet() { ++ local fw_printenv=/usr/sbin/fw_printenv ++ [ ! -n "$fw_printenv" -o ! -x "$fw_printenv" ] && { ++ echo "Please install uboot-envtools!" ++ return 1 ++ } ++ ++ [ ! -r "/etc/fw_env.config" ] && { ++ echo "/etc/fw_env.config is missing" ++ return 1 ++ } ++ ++ local image_size=$( get_filesize "$1" ) ++ local firmware_size=$( platform_get_firmware_size ) ++ [ $image_size -ge $firmware_size ] && ++ { ++ echo "upgrade image is too big (${image_size}b > ${firmware_size}b)" ++ } ++ ++ local vmlinux_blockoffset=$( platform_get_offset "$1" uImage ) ++ [ -z $vmlinux_blockoffset ] && { ++ echo "vmlinux-uImage not found" ++ return 1 ++ } ++ ++ local rootfs_blockoffset=$( platform_get_offset "$1" rootfs "$vmlinux_blockoffset" ) ++ [ -z $rootfs_blockoffset ] && { ++ echo "missing rootfs" ++ return 1 ++ } ++ ++ local data_blockoffset=$( platform_get_offset "$1" rootfs-data "$rootfs_blockoffset" ) ++ [ -z $data_blockoffset ] && { ++ echo "rootfs doesn't have JFFS2 end marker" ++ return 1 ++ } ++ ++ return 0 ++} ++ ++platform_do_upgrade_allnet() { ++ local firmware_base_addr=$( printf "%d" "$1" ) ++ local vmlinux_blockoffset=$( platform_get_offset "$2" uImage ) ++ if [ ! -n "$vmlinux_blockoffset" ]; then ++ echo "can't determine uImage offset" ++ return 1 ++ fi ++ local rootfs_blockoffset=$( platform_get_offset "$2" rootfs $(( $vmlinux_blockoffset + 1 )) ) ++ local vmlinux_offset=$(( $vmlinux_blockoffset * $CI_BLKSZ )) ++ local vmlinux_addr=$(( $firmware_base_addr + $vmlinux_offset )) ++ local vmlinux_hexaddr=0x$( printf "%08x" "$vmlinux_addr" ) ++ if [ ! -n "$rootfs_blockoffset" ]; then ++ echo "can't determine rootfs offset" ++ return 1 ++ fi ++ local rootfs_offset=$(( $rootfs_blockoffset * $CI_BLKSZ )) ++ local rootfs_addr=$(( $firmware_base_addr + $rootfs_offset )) ++ local rootfs_hexaddr=0x$( printf "%08x" "$rootfs_addr" ) ++ local vmlinux_blockcount=$(( $rootfs_blockoffset - $vmlinux_blockoffset )) ++ local vmlinux_size=$(( $rootfs_offset - $vmlinux_offset )) ++ local vmlinux_hexsize=0x$( printf "%08x" "$vmlinux_size" ) ++ local data_blockoffset=$( platform_get_offset "$2" rootfs-data $(( $rootfs_blockoffset + 1 )) ) ++ if [ ! -n "$data_blockoffset" ]; then ++ echo "can't determine rootfs size" ++ return 1 ++ fi ++ local data_offset=$(( $data_blockoffset * $CI_BLKSZ )) ++ local rootfs_blockcount=$(( $data_blockoffset - $rootfs_blockoffset )) ++ local rootfs_size=$(( $data_offset - $rootfs_offset )) ++ local rootfs_hexsize=0x$( printf "%08x" "$rootfs_size" ) ++ ++ local rootfs_md5=$( dd if="$2" bs=$CI_BLKSZ skip=$rootfs_blockoffset count=$rootfs_blockcount 2>/dev/null | md5sum -); rootfs_md5="${rootfs_md5%% *}" ++ local vmlinux_md5=$( dd if="$2" bs=$CI_BLKSZ skip=$vmlinux_blockoffset count=$vmlinux_blockcount 2>/dev/null | md5sum -); vmlinux_md5="${vmlinux_md5%% *}" ++ # this needs a recent version of uboot-envtools! ++ cat >/tmp/fw_env_upgrade </dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++dir825b_is_caldata_valid() { ++ local mtddev=$1 ++ local magic ++ ++ magic=$(get_magic_at $mtddev 4096) ++ [ "$magic" != "a55a" ] && return 0 ++ ++ magic=$(get_magic_at $mtddev 20480) ++ [ "$magic" != "a55a" ] && return 0 ++ ++ return 1 ++} ++ ++dir825b_copy_caldata() { ++ local cal_src=$1 ++ local cal_dst=$2 ++ local mtd_src ++ local mtd_dst ++ local md5_src ++ local md5_dst ++ ++ mtd_src=$(find_mtd_part $cal_src) ++ [ -z "$mtd_src" ] && { ++ echo "no $cal_src partition found" ++ return 1 ++ } ++ ++ mtd_dst=$(find_mtd_part $cal_dst) ++ [ -z "$mtd_dst" ] && { ++ echo "no $cal_dst partition found" ++ return 1 ++ } ++ ++ dir825b_is_caldata_valid "$mtd_src" && { ++ echo "no valid calibration data found in $cal_src" ++ return 1 ++ } ++ ++ dir825b_is_caldata_valid "$mtd_dst" && { ++ echo "Copying calibration data from $cal_src to $cal_dst..." ++ dd if="$mtd_src" 2>/dev/null | mtd -q -q write - "$cal_dst" ++ } ++ ++ md5_src=$(md5sum "$mtd_src") && md5_src="${md5_src%% *}" ++ md5_dst=$(md5sum "$mtd_dst") && md5_dst="${md5_dst%% *}" ++ ++ [ "$md5_src" != "$md5_dst" ] && { ++ echo "calibration data mismatch $cal_src:$md5_src $cal_dst:$md5_dst" ++ return 1 ++ } ++ ++ return 0 ++} ++ ++dir825b_do_upgrade_combined() { ++ local fw_part=$1 ++ local fw_file=$2 ++ local fw_mtd=$(find_mtd_part $fw_part) ++ local fw_length=0x$(dd if="$fw_file" bs=2 skip=1 count=4 2>/dev/null) ++ local fw_blocks=$(($fw_length / 65536)) ++ ++ if [ -n "$fw_mtd" ] && [ ${fw_blocks:-0} -gt 0 ]; then ++ local append="" ++ [ -f "$UPGRADE_BACKUP" ] && append="-j $UPGRADE_BACKUP" ++ ++ sync ++ dd if="$fw_file" bs=64k skip=1 count=$fw_blocks 2>/dev/null | \ ++ mtd $append write - "$fw_part" ++ fi ++} ++ ++dir825b_check_image() { ++ local magic="$(get_magic_long "$1")" ++ local fw_mtd=$(find_mtd_part "firmware_orig") ++ ++ case "$magic" in ++ "27051956") ++ ;; ++ "43493030") ++ local md5_img=$(dd if="$1" bs=2 skip=9 count=16 2>/dev/null) ++ local md5_chk=$(dd if="$1" bs=64k skip=1 2>/dev/null | md5sum -); md5_chk="${md5_chk%% *}" ++ local fw_len=$(dd if="$1" bs=2 skip=1 count=4 2>/dev/null) ++ local fw_part_len=$(mtd_get_part_size "firmware") ++ ++ if [ -z "$fw_mtd" ]; then ++ ask_bool 0 "Do you have a backup of the caldata partition?" || { ++ echo "Warning, please make sure that you have a backup of the caldata partition." ++ echo "Once you have that, use 'sysupgrade -i' for upgrading to the 'fat' firmware." ++ return 1 ++ } ++ fi ++ ++ if [ -z "$md5_img" -o -z "$md5_chk" ]; then ++ echo "Unable to get image checksums. Maybe you are using a streamed image?" ++ return 1 ++ fi ++ ++ if [ "$md5_img" != "$md5_chk" ]; then ++ echo "Invalid image. Contents do not match checksum (image:$md5_img calculated:$md5_chk)" ++ return 1 ++ fi ++ ++ fw_len=$((0x$fw_len)) ++ fw_part_len=${fw_part_len:-0} ++ ++ if [ $fw_part_len -lt $fw_len ]; then ++ echo "The upgrade image is too big (size:$fw_len available:$fw_part_len)" ++ return 1 ++ fi ++ ;; ++ *) ++ echo "Unsupported image format." ++ return 1 ++ ;; ++ esac ++ ++ return 0 ++} ++ ++platform_do_upgrade_dir825b() { ++ local magic="$(get_magic_long "$1")" ++ local fw_mtd=$(find_mtd_part "firmware_orig") ++ ++ case "$magic" in ++ "27051956") ++ if [ -n "$fw_mtd" ]; then ++ # restore calibration data before downgrading to ++ # the normal image ++ dir825b_copy_caldata "caldata" "caldata_orig" || { ++ echo "unable to restore calibration data" ++ exit 1 ++ } ++ PART_NAME="firmware_orig" ++ else ++ PART_NAME="firmware" ++ fi ++ default_do_upgrade "$1" ++ ;; ++ "43493030") ++ if [ -z "$fw_mtd" ]; then ++ # backup calibration data before upgrading to the ++ # fat image ++ dir825b_copy_caldata "caldata" "caldata_copy" || { ++ echo "unable to backup calibration data" ++ exit 1 ++ } ++ fi ++ dir825b_do_upgrade_combined "firmware" "$1" ++ ;; ++ esac ++} +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/merakinand.sh b/target/linux/ar71xx/base-files/lib/upgrade/merakinand.sh +new file mode 100644 +index 0000000000..dfc57b23f5 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/upgrade/merakinand.sh +@@ -0,0 +1,165 @@ ++#!/bin/sh ++# ++# Copyright (C) 2015-2016 Chris Blake ++# ++# Custom upgrade script for Meraki NAND devices (ex. MR18) ++# Based on dir825.sh and stock nand functions ++# ++. /lib/ar71xx.sh ++. /lib/functions.sh ++ ++get_magic_at() { ++ local mtddev=$1 ++ local pos=$2 ++ dd bs=1 count=2 skip=$pos if=$mtddev 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++meraki_is_caldata_valid() { ++ local board=$1 ++ local mtddev=$2 ++ local magic ++ ++ case "$board" in ++ "mr18") ++ magic=$(get_magic_at $mtddev 4096) ++ [ "$magic" != "0202" ] && return 0 ++ ++ magic=$(get_magic_at $mtddev 20480) ++ [ "$magic" != "0202" ] && return 0 ++ ++ magic=$(get_magic_at $mtddev 36864) ++ [ "$magic" != "0202" ] && return 0 ++ ++ return 1 ++ ;; ++ "z1") ++ magic=$(get_magic_at $mtddev 4096) ++ [ "$magic" != "0202" ] && return 0 ++ ++ magic=$(get_magic_at $mtddev 86016) ++ [ "$magic" != "a55a" ] && return 0 ++ ++ return 1 ++ ;; ++ *) ++ return 1 ++ ;; ++ esac ++} ++ ++merakinand_copy_caldata() { ++ local cal_src=$1 ++ local cal_dst=$2 ++ local ubidev="$(nand_find_ubi $CI_UBIPART)" ++ local board_name="$(board_name)" ++ local rootfs_size="$(ubinfo /dev/ubi0 -N rootfs_data | grep "Size" | awk '{ print $6 }')" ++ ++ # Setup partitions using board name, in case of future platforms ++ case "$board_name" in ++ "mr18"|\ ++ "z1") ++ # Src is MTD ++ mtd_src="$(find_mtd_chardev $cal_src)" ++ [ -n "$mtd_src" ] || { ++ echo "no mtd device found for partition $cal_src" ++ exit 1 ++ } ++ ++ # Dest is UBI ++ # TODO: possibly add create (hard to do when rootfs_data is expanded & mounted) ++ # Would need to be done from ramdisk ++ mtd_dst="$(nand_find_volume $ubidev $cal_dst)" ++ [ -n "$mtd_dst" ] || { ++ echo "no ubi device found for partition $cal_dst" ++ exit 1 ++ } ++ ++ meraki_is_caldata_valid "$board_name" "$mtd_src" && { ++ echo "no valid calibration data found in $cal_src" ++ exit 1 ++ } ++ ++ meraki_is_caldata_valid "$board_name" "/dev/$mtd_dst" && { ++ echo "Copying calibration data from $cal_src to $cal_dst..." ++ dd if="$mtd_src" of=/tmp/caldata.tmp 2>/dev/null ++ ubiupdatevol "/dev/$mtd_dst" /tmp/caldata.tmp ++ rm /tmp/caldata.tmp ++ sync ++ } ++ return 0 ++ ;; ++ *) ++ echo "Unsupported device $board_name"; ++ return 1 ++ ;; ++ esac ++} ++ ++merakinand_do_kernel_check() { ++ local board_name="$1" ++ local tar_file="$2" ++ local image_magic_word=`(tar xf $tar_file sysupgrade-$board_name/kernel -O 2>/dev/null | dd bs=1 count=4 skip=0 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"')` ++ ++ # What is our kernel magic string? ++ case "$board_name" in ++ "mr18") ++ [ "$image_magic_word" == "8e73ed8a" ] && { ++ echo "pass" && return 0 ++ } ++ ;; ++ "z1") ++ [ "$image_magic_word" == "4d495053" ] && { ++ echo "pass" && return 0 ++ } ++ ;; ++ esac ++ ++ exit 1 ++} ++ ++merakinand_do_platform_check() { ++ local board_name="$1" ++ local tar_file="$2" ++ local control_length=`(tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null` ++ local file_type="$(identify_tar $2 sysupgrade-$board_name/root)" ++ local kernel_magic="$(merakinand_do_kernel_check $1 $2)" ++ ++ case "$board_name" in ++ "mr18"|\ ++ "z1") ++ [ "$control_length" = 0 -o "$file_type" != "squashfs" -o "$kernel_magic" != "pass" ] && { ++ echo "Invalid sysupgrade file for $board_name" ++ return 1 ++ } ++ ;; ++ *) ++ echo "Unsupported device $board_name"; ++ return 1 ++ ;; ++ esac ++ ++ return 0 ++} ++ ++merakinand_do_upgrade() { ++ local tar_file="$1" ++ local board_name="$(board_name)" ++ ++ # Do we need to do any platform tweaks? ++ case "$board_name" in ++ "mr18") ++ # Check and create UBI caldata if it's invalid ++ merakinand_copy_caldata "odm-caldata" "caldata" ++ nand_do_upgrade $1 ++ ;; ++ "z1") ++ # Check and create UBI caldata if it's invalid ++ merakinand_copy_caldata "origcaldata" "caldata" ++ nand_do_upgrade $1 ++ ;; ++ *) ++ echo "Unsupported device $board_name"; ++ exit 1 ++ ;; ++ esac ++} +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh b/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh +new file mode 100644 +index 0000000000..f43bdcea7f +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh +@@ -0,0 +1,232 @@ ++# The U-Boot loader of the OpenMesh devices requires image sizes and ++# checksums to be provided in the U-Boot environment. ++# The OpenMesh 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. ++ ++trim() ++{ ++ echo $1 ++} ++ ++cfg_value_get() ++{ ++ local cfg=$1 cfg_opt ++ local section=$2 our_section=0 ++ local param=$3 our_param= ++ ++ for cfg_opt in $cfg ++ do ++ [ "$cfg_opt" = "[$section]" ] && our_section=1 && continue ++ [ "$our_section" = "1" ] || continue ++ ++ our_param=$(echo ${cfg_opt%%=*}) ++ [ "$param" = "$our_param" ] && echo ${cfg_opt##*=} && break ++ done ++} ++ ++platform_check_image_target_openmesh() ++{ ++ img_board_target="$1" ++ ++ case "$img_board_target" in ++ A60) ++ [ "$board" = "a40" ] && return 0 ++ [ "$board" = "a60" ] && return 0 ++ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" ++ return 1 ++ ;; ++ OM2P) ++ [ "$board" = "om2p" ] && return 0 ++ [ "$board" = "om2pv2" ] && return 0 ++ [ "$board" = "om2pv4" ] && return 0 ++ [ "$board" = "om2p-lc" ] && return 0 ++ [ "$board" = "om2p-hs" ] && return 0 ++ [ "$board" = "om2p-hsv2" ] && return 0 ++ [ "$board" = "om2p-hsv3" ] && return 0 ++ [ "$board" = "om2p-hsv4" ] && return 0 ++ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" ++ return 1 ++ ;; ++ OM5P) ++ [ "$board" = "om5p" ] && return 0 ++ [ "$board" = "om5p-an" ] && return 0 ++ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" ++ return 1 ++ ;; ++ OM5PAC) ++ [ "$board" = "om5p-ac" ] && return 0 ++ [ "$board" = "om5p-acv2" ] && return 0 ++ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" ++ return 1 ++ ;; ++ MR1750) ++ [ "$board" = "mr1750" ] && return 0 ++ [ "$board" = "mr1750v2" ] && return 0 ++ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" ++ return 1 ++ ;; ++ MR600) ++ [ "$board" = "mr600" ] && return 0 ++ [ "$board" = "mr600v2" ] && return 0 ++ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" ++ return 1 ++ ;; ++ MR900) ++ [ "$board" = "mr900" ] && return 0 ++ [ "$board" = "mr900v2" ] && return 0 ++ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" ++ return 1 ++ ;; ++ *) ++ echo "Invalid board target ($img_board_target). Use the correct image for this platform" ++ return 1 ++ ;; ++ esac ++} ++ ++platform_check_image_openmesh() ++{ ++ local img_magic=$1 ++ local img_path=$2 ++ local fw_printenv=/usr/sbin/fw_printenv ++ local img_board_target= img_num_files= i=0 ++ local cfg_name= kernel_name= rootfs_name= ++ ++ case "$img_magic" in ++ # Combined Extended Image v1 ++ 43453031) ++ img_board_target=$(trim $(dd if="$img_path" bs=4 skip=1 count=8 2>/dev/null)) ++ img_num_files=$(trim $(dd if="$img_path" bs=2 skip=18 count=1 2>/dev/null)) ++ ;; ++ *) ++ echo "Invalid image ($img_magic). Use combined extended images on this platform" ++ return 1 ++ ;; ++ esac ++ ++ platform_check_image_target_openmesh "$img_board_target" || return 1 ++ ++ [ $img_num_files -lt 3 ] && { ++ echo "Invalid number of embedded images ($img_num_files). Use the correct image for this platform" ++ return 1 ++ } ++ ++ cfg_name=$(trim $(dd if="$img_path" bs=2 skip=19 count=16 2>/dev/null)) ++ ++ [ "$cfg_name" != "fwupgrade.cfg" ] && { ++ echo "Invalid embedded config file ($cfg_name). Use the correct image for this platform" ++ return 1 ++ } ++ ++ kernel_name=$(trim $(dd if="$img_path" bs=2 skip=55 count=16 2>/dev/null)) ++ ++ [ "$kernel_name" != "kernel" ] && { ++ echo "Invalid embedded kernel file ($kernel_name). Use the correct image for this platform" ++ return 1 ++ } ++ ++ rootfs_name=$(trim $(dd if="$img_path" bs=2 skip=91 count=16 2>/dev/null)) ++ ++ [ "$rootfs_name" != "rootfs" ] && { ++ echo "Invalid embedded kernel file ($rootfs_name). Use the correct image for this platform" ++ return 1 ++ } ++ ++ [ ! -x "$fw_printenv" ] && { ++ echo "Please install uboot-envtools!" ++ return 1 ++ } ++ ++ [ ! -r "/etc/fw_env.config" ] && { ++ echo "/etc/fw_env.config is missing" ++ return 1 ++ } ++ ++ return 0 ++} ++ ++platform_do_upgrade_openmesh() ++{ ++ local img_path=$1 img_board_target= ++ local kernel_start_addr= kernel_start_addr1= kernel_start_addr2= ++ local kernel_size= kernel_md5= ++ local rootfs_size= rootfs_checksize= rootfs_md5= ++ local kernel_bsize= total_size= ++ local data_offset=$((64 * 1024)) block_size= offset= ++ local uboot_env_upgrade="/tmp/fw_env_upgrade" ++ local cfg_size= kernel_size= rootfs_size= ++ local append="" ++ ++ [ -f "$UPGRADE_BACKUP" ] && append="-j $UPGRADE_BACKUP" ++ ++ cfg_size=$(dd if="$img_path" bs=2 skip=35 count=4 2>/dev/null) ++ kernel_size=$(dd if="$img_path" bs=2 skip=71 count=4 2>/dev/null) ++ rootfs_size=$(dd if="$img_path" bs=2 skip=107 count=4 2>/dev/null) ++ ++ img_board_target=$(trim $(dd if="$img_path" bs=4 skip=1 count=8 2>/dev/null)) ++ cfg_content=$(dd if="$img_path" bs=1 skip=$data_offset count=$(echo $((0x$cfg_size))) 2>/dev/null) ++ ++ case $img_board_target in ++ OM2P) ++ block_size=$((256 * 1024)) ++ total_size=7340032 ++ kernel_start_addr1=0x9f1c0000 ++ kernel_start_addr2=0x9f8c0000 ++ ;; ++ OM5P|OM5PAC|MR600|MR900|MR1750|A60) ++ block_size=$((64 * 1024)) ++ total_size=7995392 ++ kernel_start_addr1=0x9f0b0000 ++ kernel_start_addr2=0x9f850000 ++ ;; ++ esac ++ ++ kernel_md5=$(cfg_value_get "$cfg_content" "vmlinux" "md5sum") ++ rootfs_md5=$(cfg_value_get "$cfg_content" "rootfs" "md5sum") ++ rootfs_checksize=$(cfg_value_get "$cfg_content" "rootfs" "checksize") ++ ++ if [ "$((0x$kernel_size % $block_size))" = "0" ] ++ then ++ kernel_bsize=$(echo $((0x$kernel_size))) ++ else ++ kernel_bsize=$((0x$kernel_size + ($block_size - (0x$kernel_size % $block_size)))) ++ fi ++ ++ mtd -q erase inactive ++ ++ offset=$(echo $(($data_offset + 0x$cfg_size + 0x$kernel_size))) ++ dd if="$img_path" bs=1 skip=$offset count=$(echo $((0x$rootfs_size))) 2>&- | mtd -n -p $kernel_bsize $append write - "inactive" ++ ++ offset=$(echo $(($data_offset + 0x$cfg_size))) ++ dd if="$img_path" bs=1 skip=$offset count=$(echo $((0x$kernel_size))) 2>&- | mtd -n write - "inactive" ++ ++ rm $uboot_env_upgrade 2>&- ++ ++ if [ "$(grep 'mtd3:.*inactive' /proc/mtd)" ] ++ then ++ printf "kernel_size_1 %u\n" $(($kernel_bsize / 1024)) >> $uboot_env_upgrade ++ printf "rootfs_size_1 %u\n" $((($total_size - $kernel_bsize) / 1024)) >> $uboot_env_upgrade ++ printf "bootseq 1,2\n" >> $uboot_env_upgrade ++ kernel_start_addr=$kernel_start_addr1 ++ else ++ printf "kernel_size_2 %u\n" $(($kernel_bsize / 1024)) >> $uboot_env_upgrade ++ printf "rootfs_size_2 %u\n" $((($total_size - $kernel_bsize) / 1024)) >> $uboot_env_upgrade ++ printf "bootseq 2,1\n" >> $uboot_env_upgrade ++ kernel_start_addr=$kernel_start_addr2 ++ fi ++ ++ printf "vmlinux_start_addr %s\n" $kernel_start_addr >> $uboot_env_upgrade ++ printf "vmlinux_size 0x%s\n" $kernel_size >> $uboot_env_upgrade ++ printf "vmlinux_checksum %s\n" $kernel_md5 >> $uboot_env_upgrade ++ printf "rootfs_start_addr 0x%x\n" $(($kernel_start_addr + $kernel_bsize)) >> $uboot_env_upgrade ++ printf "rootfs_size %s\n" $rootfs_checksize >> $uboot_env_upgrade ++ printf "rootfs_checksum %s\n" $rootfs_md5 >> $uboot_env_upgrade ++ ++ mkdir -p /var/lock ++ fw_setenv -s $uboot_env_upgrade || { ++ echo "failed to update U-Boot environment" ++ return 1 ++ } ++} +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +new file mode 100755 +index 0000000000..2391a1de8a +--- /dev/null ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -0,0 +1,915 @@ ++# ++# Copyright (C) 2011 OpenWrt.org ++# ++ ++. /lib/functions/system.sh ++. /lib/ar71xx.sh ++ ++PART_NAME=firmware ++RAMFS_COPY_DATA='/lib/ar71xx.sh /etc/fw_env.config /var/lock/fw_printenv.lock' ++RAMFS_COPY_BIN='nandwrite fw_printenv fw_setenv' ++ ++CI_BLKSZ=65536 ++CI_LDADR=0x80060000 ++ ++PLATFORM_DO_UPGRADE_COMBINED_SEPARATE_MTD=0 ++ ++platform_find_partitions() { ++ local first dev size erasesize name ++ while read dev size erasesize name; do ++ name=${name#'"'}; name=${name%'"'} ++ case "$name" in ++ vmlinux.bin.l7|vmlinux|kernel|linux|linux.bin|rootfs|filesystem) ++ if [ -z "$first" ]; then ++ first="$name" ++ else ++ echo "$erasesize:$first:$name" ++ break ++ fi ++ ;; ++ esac ++ done < /proc/mtd ++} ++ ++platform_find_kernelpart() { ++ local part ++ for part in "${1%:*}" "${1#*:}"; do ++ case "$part" in ++ vmlinux.bin.l7|vmlinux|kernel|linux|linux.bin) ++ echo "$part" ++ break ++ ;; ++ esac ++ done ++} ++ ++platform_find_rootfspart() { ++ local part ++ for part in "${1%:*}" "${1#*:}"; do ++ [ "$part" != "$2" ] && echo "$part" && break ++ done ++} ++ ++platform_do_upgrade_combined() { ++ local partitions=$(platform_find_partitions) ++ local kernelpart=$(platform_find_kernelpart "${partitions#*:}") ++ local erase_size=$((0x${partitions%%:*})); partitions="${partitions#*:}" ++ local kern_length=0x$(dd if="$1" bs=2 skip=1 count=4 2>/dev/null) ++ local kern_blocks=$(($kern_length / $CI_BLKSZ)) ++ local root_blocks=$((0x$(dd if="$1" bs=2 skip=5 count=4 2>/dev/null) / $CI_BLKSZ)) ++ ++ if [ -n "$partitions" ] && [ -n "$kernelpart" ] && \ ++ [ ${kern_blocks:-0} -gt 0 ] && \ ++ [ ${root_blocks:-0} -gt 0 ] && \ ++ [ ${erase_size:-0} -gt 0 ]; ++ then ++ local rootfspart=$(platform_find_rootfspart "$partitions" "$kernelpart") ++ local append="" ++ [ -f "$UPGRADE_BACKUP" ] && append="-j $UPGRADE_BACKUP" ++ ++ if [ "$PLATFORM_DO_UPGRADE_COMBINED_SEPARATE_MTD" -ne 1 ]; then ++ ( dd if="$1" bs=$CI_BLKSZ skip=1 count=$kern_blocks 2>/dev/null; \ ++ dd if="$1" bs=$CI_BLKSZ skip=$((1+$kern_blocks)) count=$root_blocks 2>/dev/null ) | \ ++ mtd -r $append -F$kernelpart:$kern_length:$CI_LDADR,rootfs write - $partitions ++ elif [ -n "$rootfspart" ]; then ++ dd if="$1" bs=$CI_BLKSZ skip=1 count=$kern_blocks 2>/dev/null | \ ++ mtd write - $kernelpart ++ dd if="$1" bs=$CI_BLKSZ skip=$((1+$kern_blocks)) count=$root_blocks 2>/dev/null | \ ++ mtd -r $append write - $rootfspart ++ fi ++ fi ++ PLATFORM_DO_UPGRADE_COMBINED_SEPARATE_MTD=0 ++} ++ ++tplink_get_image_hwid() { ++ get_image "$@" | dd bs=4 count=1 skip=16 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++tplink_get_image_mid() { ++ get_image "$@" | dd bs=4 count=1 skip=17 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++tplink_get_image_boot_size() { ++ get_image "$@" | dd bs=4 count=1 skip=37 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++tplink_pharos_check_support_list() { ++ local image="$1" ++ local offset="$2" ++ local model="$3" ++ local trargs="$4" ++ ++ # Here $image is given to dd directly instead of using get_image; ++ # otherwise the skip will take almost a second (as dd can't seek) ++ dd if="$image" bs=1 skip=$offset count=1024 2>/dev/null | tr -d "$trargs" | ( ++ while IFS= read -r line; do ++ [ "$line" = "$model" ] && exit 0 ++ done ++ ++ exit 1 ++ ) ++} ++ ++tplink_pharos_check_image() { ++ local image_magic="$(get_magic_long "$1")" ++ local board_magic="$2" ++ [ "$image_magic" != "$board_magic" ] && { ++ echo "Invalid image magic '$image_magic'. Expected '$board_magic'." ++ return 1 ++ } ++ ++ local model_string="$3" ++ local trargs="$4" ++ ++ # New images have the support list at 7802888, old ones at 1511432 ++ tplink_pharos_check_support_list "$1" 7802888 "$model_string" "$trargs" || \ ++ tplink_pharos_check_support_list "$1" 1511432 "$model_string" "$trargs" || { ++ echo "Unsupported image (model not in support-list)" ++ return 1 ++ } ++ ++ return 0 ++} ++ ++seama_get_type_magic() { ++ get_image "$@" | dd bs=1 count=4 skip=53 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++wrgg_get_image_magic() { ++ get_image "$@" | dd bs=4 count=1 skip=8 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++cybertan_get_image_magic() { ++ get_image "$@" | dd bs=8 count=1 skip=0 2>/dev/null | hexdump -v -n 8 -e '1/1 "%02x"' ++} ++ ++cybertan_check_image() { ++ local magic="$(cybertan_get_image_magic "$1")" ++ local fw_magic="$(cybertan_get_hw_magic)" ++ ++ [ "$fw_magic" != "$magic" ] && { ++ echo "Invalid image, ID mismatch, got:$magic, but need:$fw_magic" ++ return 1 ++ } ++ ++ return 0 ++} ++ ++platform_do_upgrade_compex() { ++ local fw_file=$1 ++ local fw_part=$PART_NAME ++ local fw_mtd=$(find_mtd_part $fw_part) ++ local fw_length=0x$(dd if="$fw_file" bs=2 skip=1 count=4 2>/dev/null) ++ local fw_blocks=$(($fw_length / 65536)) ++ ++ if [ -n "$fw_mtd" ] && [ ${fw_blocks:-0} -gt 0 ]; then ++ local append="" ++ [ -f "$UPGRADE_BACKUP" ] && append="-j $UPGRADE_BACKUP" ++ ++ sync ++ dd if="$fw_file" bs=64k skip=1 count=$fw_blocks 2>/dev/null | \ ++ mtd $append write - "$fw_part" ++ fi ++} ++ ++alfa_check_image() { ++ local magic_long="$(get_magic_long "$1")" ++ local fw_part_size=$(mtd_get_part_size firmware) ++ ++ case "$magic_long" in ++ "27051956") ++ [ "$fw_part_size" != "16318464" ] && { ++ echo "Invalid image magic \"$magic_long\" for $fw_part_size bytes" ++ return 1 ++ } ++ ;; ++ "68737173") ++ [ "$fw_part_size" != "7929856" ] && { ++ echo "Invalid image magic \"$magic_long\" for $fw_part_size bytes" ++ return 1 ++ } ++ ;; ++ esac ++ ++ return 0 ++} ++ ++platform_check_image() { ++ local board=$(board_name) ++ local magic="$(get_magic_word "$1")" ++ local magic_long="$(get_magic_long "$1")" ++ ++ [ "$#" -gt 1 ] && return 1 ++ ++ case "$board" in ++ airgateway|\ ++ airgatewaypro|\ ++ airrouter|\ ++ ap121f|\ ++ ap132|\ ++ ap531b0|\ ++ ap90q|\ ++ archer-c25-v1|\ ++ archer-c58-v1|\ ++ archer-c59-v1|\ ++ archer-c59-v2|\ ++ archer-c60-v1|\ ++ archer-c60-v2|\ ++ archer-c7-v4|\ ++ archer-c7-v5|\ ++ arduino-yun|\ ++ bullet-m|\ ++ bullet-m-xw|\ ++ c-55|\ ++ carambola2|\ ++ cf-e316n-v2|\ ++ cf-e320n-v2|\ ++ cf-e355ac-v1|\ ++ cf-e355ac-v2|\ ++ cf-e375ac|\ ++ cf-e380ac-v1|\ ++ cf-e380ac-v2|\ ++ cf-e385ac|\ ++ cf-e520n|\ ++ cf-e530n|\ ++ cpe505n|\ ++ cpe830|\ ++ cpe870|\ ++ dap-1330-a1|\ ++ dgl-5500-a1|\ ++ dhp-1565-a1|\ ++ dir-505-a1|\ ++ dir-600-a1|\ ++ dir-615-c1|\ ++ dir-615-e1|\ ++ dir-615-e4|\ ++ dir-615-i1|\ ++ dir-825-c1|\ ++ dir-835-a1|\ ++ dlan-hotspot|\ ++ dlan-pro-1200-ac|\ ++ dlan-pro-500-wp|\ ++ dr342|\ ++ dr531|\ ++ dragino2|\ ++ e1700ac-v2|\ ++ e558-v2|\ ++ e600g-v2|\ ++ e600gac-v2|\ ++ e750a-v4|\ ++ e750g-v8|\ ++ ebr-2310-c1|\ ++ ens202ext|\ ++ epg5000|\ ++ esr1750|\ ++ esr900|\ ++ ew-balin|\ ++ ew-dorin|\ ++ ew-dorin-router|\ ++ gl-ar150|\ ++ gl-ar300m|\ ++ gl-ar300|\ ++ gl-ar750|\ ++ gl-ar750s|\ ++ gl-domino|\ ++ gl-mifi|\ ++ gl-usb150|\ ++ hiwifi-hc6361|\ ++ hornet-ub-x2|\ ++ jwap230|\ ++ lbe-m5|\ ++ lima|\ ++ loco-m-xw|\ ++ mzk-w04nu|\ ++ mzk-w300nh|\ ++ n5q|\ ++ nanostation-m|\ ++ nanostation-m-xw|\ ++ nbg460n_550n_550nh|\ ++ pqi-air-pen|\ ++ r36a|\ ++ r602n|\ ++ rme-eg200|\ ++ rocket-m|\ ++ rocket-m-ti|\ ++ rocket-m-xw|\ ++ rw2458n|\ ++ sc1750|\ ++ sc300m|\ ++ sc450|\ ++ sr3200|\ ++ t830|\ ++ tew-632brp|\ ++ tew-712br|\ ++ tew-732br|\ ++ tew-823dru|\ ++ tl-wr1043n-v5|\ ++ tl-wr942n-v1|\ ++ unifi|\ ++ unifi-outdoor|\ ++ unifiac-lite|\ ++ unifiac-pro|\ ++ wam250|\ ++ weio|\ ++ whr-g301n|\ ++ whr-hp-g300n|\ ++ whr-hp-gn|\ ++ wlae-ag300n|\ ++ wndap360|\ ++ wpj342|\ ++ wpj344|\ ++ wpj531|\ ++ wpj558|\ ++ wpj563|\ ++ wrt400n|\ ++ wrtnode2q|\ ++ wzr-450hp2|\ ++ wzr-hp-ag300h|\ ++ wzr-hp-g300nh|\ ++ wzr-hp-g300nh2|\ ++ wzr-hp-g450h|\ ++ xd3200) ++ [ "$magic" != "2705" ] && { ++ echo "Invalid image type." ++ return 1 ++ } ++ ++ return 0 ++ ;; ++ alfa-ap96|\ ++ alfa-nx|\ ++ ap121|\ ++ ap121-mini|\ ++ ap135-020|\ ++ ap136-010|\ ++ ap136-020|\ ++ ap147-010|\ ++ ap152|\ ++ ap91-5g|\ ++ ap96|\ ++ bhr-4grv2|\ ++ bxu2000n-2-a1|\ ++ db120|\ ++ dr344|\ ++ dw33d|\ ++ f9k1115v2|\ ++ hornet-ub|\ ++ mr12|\ ++ mr16|\ ++ zbt-we1526|\ ++ zcn-1523h-2|\ ++ zcn-1523h-5) ++ [ "$magic_long" != "68737173" -a "$magic_long" != "19852003" ] && { ++ echo "Invalid image type." ++ return 1 ++ } ++ ++ return 0 ++ ;; ++ all0258n|\ ++ all0315n|\ ++ cap324|\ ++ cap4200ag|\ ++ cr3000|\ ++ cr5000) ++ platform_check_image_allnet "$1" && return 0 ++ return 1 ++ ;; ++ all0305|\ ++ eap300v2|\ ++ eap7660d|\ ++ ja76pf|\ ++ ja76pf2|\ ++ jwap003|\ ++ ls-sr71|\ ++ pb42|\ ++ pb44|\ ++ routerstation|\ ++ routerstation-pro|\ ++ wp543|\ ++ wpe72) ++ [ "$magic" != "4349" ] && { ++ echo "Invalid image. Use *-sysupgrade.bin files on this board" ++ return 1 ++ } ++ ++ local md5_img=$(dd if="$1" bs=2 skip=9 count=16 2>/dev/null) ++ local md5_chk=$(fwtool -q -t -i /dev/null "$1"; dd if="$1" bs=$CI_BLKSZ skip=1 2>/dev/null | md5sum -); md5_chk="${md5_chk%% *}" ++ ++ if [ -n "$md5_img" -a -n "$md5_chk" ] && [ "$md5_img" = "$md5_chk" ]; then ++ return 0 ++ else ++ echo "Invalid image. Contents do not match checksum (image:$md5_img calculated:$md5_chk)" ++ return 1 ++ fi ++ ++ return 0 ++ ;; ++ antminer-s1|\ ++ antminer-s3|\ ++ antrouter-r1|\ ++ archer-c5|\ ++ archer-c7|\ ++ el-m150|\ ++ el-mini|\ ++ gl-inet|\ ++ lan-turtle|\ ++ mc-mac1200r|\ ++ minibox-v1|\ ++ minibox-v3.2|\ ++ omy-g1|\ ++ omy-x1|\ ++ onion-omega|\ ++ oolite-v1|\ ++ oolite-v5.2|\ ++ oolite-v5.2-dev|\ ++ packet-squirrel|\ ++ re355|\ ++ re450|\ ++ rut900|\ ++ smart-300|\ ++ som9331|\ ++ tellstick-znet-lite|\ ++ tl-mr10u|\ ++ tl-mr11u|\ ++ tl-mr12u|\ ++ tl-mr13u|\ ++ tl-mr3020|\ ++ tl-mr3040|\ ++ tl-mr3040-v2|\ ++ tl-mr3220|\ ++ tl-mr3220-v2|\ ++ tl-mr3420|\ ++ tl-mr3420-v2|\ ++ tl-mr6400|\ ++ tl-wa701nd-v2|\ ++ tl-wa7210n-v2|\ ++ tl-wa750re|\ ++ tl-wa7510n|\ ++ tl-wa801nd-v2|\ ++ tl-wa801nd-v3|\ ++ tl-wa830re-v2|\ ++ tl-wa850re|\ ++ tl-wa850re-v2|\ ++ tl-wa855re-v1|\ ++ tl-wa860re|\ ++ tl-wa901nd|\ ++ tl-wa901nd-v2|\ ++ tl-wa901nd-v3|\ ++ tl-wa901nd-v4|\ ++ tl-wa901nd-v5|\ ++ tl-wdr3320-v2|\ ++ tl-wdr3500|\ ++ tl-wdr4300|\ ++ tl-wdr4900-v2|\ ++ tl-wdr6500-v2|\ ++ tl-wpa8630|\ ++ tl-wr1041n-v2|\ ++ tl-wr1043nd|\ ++ tl-wr1043nd-v2|\ ++ tl-wr1043nd-v4|\ ++ tl-wr2543n|\ ++ tl-wr703n|\ ++ tl-wr710n|\ ++ tl-wr720n-v3|\ ++ tl-wr740n-v6|\ ++ tl-wr741nd|\ ++ tl-wr741nd-v4|\ ++ tl-wr802n-v1|\ ++ tl-wr802n-v2|\ ++ tl-wr810n|\ ++ tl-wr810n-v2|\ ++ tl-wr840n-v2|\ ++ tl-wr840n-v3|\ ++ tl-wr841n-v1|\ ++ tl-wr841n-v7|\ ++ tl-wr841n-v8|\ ++ tl-wr841n-v9|\ ++ tl-wr841n-v11|\ ++ tl-wr842n-v2|\ ++ tl-wr842n-v3|\ ++ tl-wr902ac-v1|\ ++ tl-wr940n-v4|\ ++ tl-wr940n-v6|\ ++ tl-wr941nd|\ ++ tl-wr941nd-v5|\ ++ tl-wr941nd-v6|\ ++ ts-d084|\ ++ wifi-pineapple-nano) ++ local magic_ver="0100" ++ ++ case "$board" in ++ tl-wdr3320-v2|tl-wdr6500-v2) ++ magic_ver="0200" ++ ;; ++ esac ++ ++ [ "$magic" != "$magic_ver" ] && { ++ echo "Invalid image type." ++ return 1 ++ } ++ ++ local hwid ++ local mid ++ local imagehwid ++ local imagemid ++ ++ hwid=$(tplink_get_hwid) ++ mid=$(tplink_get_mid) ++ imagehwid=$(tplink_get_image_hwid "$1") ++ imagemid=$(tplink_get_image_mid "$1") ++ ++ [ "$hwid" != "$imagehwid" -o "$mid" != "$imagemid" ] && { ++ echo "Invalid image, hardware ID mismatch, hw:$hwid $mid image:$imagehwid $imagemid." ++ return 1 ++ } ++ ++ local boot_size ++ ++ boot_size=$(tplink_get_image_boot_size "$1") ++ [ "$boot_size" != "00000000" ] && { ++ echo "Invalid image, it contains a bootloader." ++ return 1 ++ } ++ ++ return 0 ++ ;; ++ bsb|\ ++ dir-825-b1|\ ++ tew-673gru) ++ dir825b_check_image "$1" && return 0 ++ ;; ++ rb-411|\ ++ rb-411u|\ ++ rb-433|\ ++ rb-433u|\ ++ rb-435g|\ ++ rb-450|\ ++ rb-450g|\ ++ rb-493|\ ++ rb-493g|\ ++ rb-750|\ ++ rb-750gl|\ ++ rb-751|\ ++ rb-751g|\ ++ rb-911g-2hpnd|\ ++ rb-911g-5hpnd|\ ++ rb-911g-5hpacd|\ ++ rb-912uag-2hpnd|\ ++ rb-912uag-5hpnd|\ ++ rb-921gs-5hpacd-r2|\ ++ rb-922uags-5hpacd|\ ++ rb-951g-2hnd|\ ++ rb-951ui-2hnd|\ ++ rb-2011l|\ ++ rb-2011il|\ ++ rb-2011ils|\ ++ rb-2011uas|\ ++ rb-2011uas-2hnd|\ ++ rb-2011uias|\ ++ rb-2011uias-2hnd|\ ++ rb-2011uias-2hnd-r2|\ ++ rb-sxt2n|\ ++ rb-sxt5n) ++ nand_do_platform_check routerboard $1 ++ return $? ++ ;; ++ c-60|\ ++ hiveap-121|\ ++ nbg6716|\ ++ r6100|\ ++ rambutan|\ ++ wi2a-ac200i|\ ++ wndr3700v4|\ ++ wndr4300) ++ nand_do_platform_check $board $1 ++ return $? ++ ;; ++ cpe210|\ ++ cpe510|\ ++ eap120|\ ++ wbs210|\ ++ wbs510) ++ tplink_pharos_check_image "$1" "7f454c46" "$(tplink_pharos_get_model_string)" '' && return 0 ++ return 1 ++ ;; ++ cpe210-v2|\ ++ cpe210-v3) ++ tplink_pharos_check_image "$1" "01000000" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 ++ return 1 ++ ;; ++ cpe510-v2) ++ tplink_pharos_check_image "$1" "7f454c46" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 ++ return 1 ++ ;; ++ a40|\ ++ a60|\ ++ mr1750|\ ++ mr1750v2|\ ++ mr600|\ ++ mr600v2|\ ++ mr900|\ ++ mr900v2|\ ++ om2p|\ ++ om2p-hs|\ ++ om2p-hsv2|\ ++ om2p-hsv3|\ ++ om2p-hsv4|\ ++ om2p-lc|\ ++ om2pv2|\ ++ om2pv4|\ ++ om5p|\ ++ om5p-ac|\ ++ om5p-acv2|\ ++ om5p-an) ++ platform_check_image_openmesh "$magic_long" "$1" && return 0 ++ return 1 ++ ;; ++ mr18|\ ++ z1) ++ merakinand_do_platform_check $board $1 ++ return $? ++ ;; ++ dir-869-a1|\ ++ mynet-n600|\ ++ mynet-n750|\ ++ qihoo-c301) ++ [ "$magic_long" != "5ea3a417" ] && { ++ echo "Invalid image, bad magic: $magic_long" ++ return 1 ++ } ++ ++ local typemagic=$(seama_get_type_magic "$1") ++ [ "$typemagic" != "6669726d" ] && { ++ echo "Invalid image, bad type: $typemagic" ++ return 1 ++ } ++ ++ return 0 ++ ;; ++ e2100l|\ ++ mynet-rext|\ ++ wrt160nl) ++ cybertan_check_image "$1" && return 0 ++ return 1 ++ ;; ++ nbg6616|\ ++ uap-pro|\ ++ unifi-outdoor-plus) ++ [ "$magic_long" != "19852003" ] && { ++ echo "Invalid image type." ++ return 1 ++ } ++ ++ return 0 ++ ;; ++ tube2h) ++ alfa_check_image "$1" && return 0 ++ return 1 ++ ;; ++ wndr3700|\ ++ wnr1000-v2|\ ++ wnr2000-v3|\ ++ wnr612-v2|\ ++ wpn824n) ++ local hw_magic ++ ++ hw_magic="$(ar71xx_get_mtd_part_magic firmware)" ++ [ "$magic_long" != "$hw_magic" ] && { ++ echo "Invalid image, hardware ID mismatch, hw:$hw_magic image:$magic_long." ++ return 1 ++ } ++ ++ return 0 ++ ;; ++ wnr2000-v4) ++ [ "$magic_long" != "32303034" ] && { ++ echo "Invalid image type." ++ return 1 ++ } ++ ++ return 0 ++ ;; ++ wnr2200) ++ [ "$magic_long" != "32323030" ] && { ++ echo "Invalid image type." ++ return 1 ++ } ++ ++ return 0 ++ ;; ++ dap-2695-a1) ++ local magic=$(wrgg_get_image_magic "$1") ++ [ "$magic" != "21030820" ] && { ++ echo "Invalid image, bad type: $magic" ++ return 1 ++ } ++ ++ return 0; ++ ;; ++ # these boards use metadata images ++ fritz300e|\ ++ fritz4020|\ ++ fritz450e|\ ++ koala|\ ++ rb-750-r2|\ ++ rb-750p-pbr2|\ ++ rb-750up-r2|\ ++ rb-911-2hn|\ ++ rb-911-5hn|\ ++ rb-931-2nd|\ ++ rb-941-2nd|\ ++ rb-951ui-2nd|\ ++ rb-952ui-5ac2nd|\ ++ rb-962uigs-5hact2hnt|\ ++ rb-lhg-5nd|\ ++ rb-map-2nd|\ ++ rb-mapl-2nd|\ ++ rb-sxt-2nd-r3|\ ++ rb-wap-2nd|\ ++ rb-wapg-5hact2hnd|\ ++ rb-wapr-2nd) ++ return 0 ++ ;; ++ esac ++ ++ echo "Sysupgrade is not yet supported on $board." ++ return 1 ++} ++ ++platform_do_upgrade_mikrotik_rb() { ++ CI_KERNPART=none ++ local fw_mtd=$(find_mtd_part kernel) ++ fw_mtd="${fw_mtd/block/}" ++ [ -n "$fw_mtd" ] || return ++ ++ local board_dir=$(tar tf "$1" | grep -m 1 '^sysupgrade-.*/$') ++ board_dir=${board_dir%/} ++ [ -n "$board_dir" ] || return ++ ++ mtd erase kernel ++ tar xf "$1" ${board_dir}/kernel -O | nandwrite -o "$fw_mtd" - ++ ++ nand_do_upgrade "$1" ++} ++ ++platform_do_upgrade_nokia() { ++ case "$(fw_printenv -n dualPartition)" in ++ imgA) ++ fw_setenv dualPartition imgB ++ fw_setenv ActImg NokiaImageB ++ ;; ++ imgB) ++ fw_setenv dualPartition imgA ++ fw_setenv ActImg NokiaImageA ++ ;; ++ esac ++ ubiblock -r /dev/ubiblock0_0 2>/dev/null >/dev/null ++ rm -f /dev/ubiblock0_0 ++ ubidetach -d 0 2>/dev/null >/dev/null ++ CI_UBIPART=ubi_alt ++ CI_KERNPART=kernel_alt ++ ++ nand_do_upgrade "$1" ++} ++ ++platform_do_upgrade() { ++ local board=$(board_name) ++ ++ case "$board" in ++ rb-750-r2|\ ++ rb-750p-pbr2|\ ++ rb-750up-r2|\ ++ rb-911-2hn|\ ++ rb-911-5hn|\ ++ rb-931-2nd|\ ++ rb-941-2nd|\ ++ rb-951ui-2nd|\ ++ rb-952ui-5ac2nd|\ ++ rb-962uigs-5hact2hnt|\ ++ rb-lhg-5nd|\ ++ rb-map-2nd|\ ++ rb-mapl-2nd|\ ++ rb-sxt-2nd-r3|\ ++ rb-wap-2nd|\ ++ rb-wapg-5hact2hnd|\ ++ rb-wapr-2nd) ++ # erase firmware if booted from initramfs ++ [ -z "$(rootfs_type)" ] && mtd erase firmware ++ ;; ++ esac ++ ++ case "$board" in ++ all0258n) ++ platform_do_upgrade_allnet "0x9f050000" "$1" ++ ;; ++ all0305|\ ++ eap7660d|\ ++ ja76pf|\ ++ ja76pf2|\ ++ jwap003|\ ++ ls-sr71|\ ++ pb42|\ ++ pb44|\ ++ routerstation|\ ++ routerstation-pro) ++ platform_do_upgrade_combined "$1" ++ ;; ++ all0315n) ++ platform_do_upgrade_allnet "0x9f080000" "$1" ++ ;; ++ cap4200ag|\ ++ eap300v2|\ ++ ens202ext) ++ platform_do_upgrade_allnet "0xbf0a0000" "$1" ++ ;; ++ dir-825-b1|\ ++ tew-673gru) ++ platform_do_upgrade_dir825b "$1" ++ ;; ++ a40|\ ++ a60|\ ++ mr1750|\ ++ mr1750v2|\ ++ mr600|\ ++ mr600v2|\ ++ mr900|\ ++ mr900v2|\ ++ om2p|\ ++ om2p-hs|\ ++ om2p-hsv2|\ ++ om2p-hsv3|\ ++ om2p-hsv4|\ ++ om2p-lc|\ ++ om2pv2|\ ++ om2pv4|\ ++ om5p|\ ++ om5p-ac|\ ++ om5p-acv2|\ ++ om5p-an) ++ platform_do_upgrade_openmesh "$1" ++ ;; ++ c-60|\ ++ hiveap-121|\ ++ nbg6716|\ ++ r6100|\ ++ rambutan|\ ++ wndr3700v4|\ ++ wndr4300) ++ nand_do_upgrade "$1" ++ ;; ++ mr18|\ ++ z1) ++ merakinand_do_upgrade "$1" ++ ;; ++ rb-411|\ ++ rb-411u|\ ++ rb-433|\ ++ rb-433u|\ ++ rb-435g|\ ++ rb-450|\ ++ rb-450g|\ ++ rb-493|\ ++ rb-493g|\ ++ rb-750|\ ++ rb-750gl|\ ++ rb-751|\ ++ rb-751g|\ ++ rb-911g-2hpnd|\ ++ rb-911g-5hpacd|\ ++ rb-911g-5hpnd|\ ++ rb-912uag-2hpnd|\ ++ rb-912uag-5hpnd|\ ++ rb-921gs-5hpacd-r2|\ ++ rb-922uags-5hpacd|\ ++ rb-951g-2hnd|\ ++ rb-951ui-2hnd|\ ++ rb-2011il|\ ++ rb-2011ils|\ ++ rb-2011l|\ ++ rb-2011uas|\ ++ rb-2011uas-2hnd|\ ++ rb-2011uias|\ ++ rb-2011uias-2hnd|\ ++ rb-2011uias-2hnd-r2|\ ++ rb-sxt2n|\ ++ rb-sxt5n) ++ platform_do_upgrade_mikrotik_rb "$1" ++ ;; ++ uap-pro|\ ++ unifi-outdoor-plus) ++ MTD_CONFIG_ARGS="-s 0x180000" ++ default_do_upgrade "$1" ++ ;; ++ wi2a-ac200i) ++ platform_do_upgrade_nokia "$1" ++ ;; ++ wp543|\ ++ wpe72) ++ platform_do_upgrade_compex "$1" ++ ;; ++ *) ++ default_do_upgrade "$1" ++ ;; ++ esac ++} +diff --git a/target/linux/ar71xx/config-4.14 b/target/linux/ar71xx/config-4.14 +new file mode 100644 +index 0000000000..125b34bfa8 +--- /dev/null ++++ b/target/linux/ar71xx/config-4.14 +@@ -0,0 +1,477 @@ ++CONFIG_AG71XX=y ++# CONFIG_AG71XX_AR8216_SUPPORT is not set ++# CONFIG_AG71XX_DEBUG is not set ++# CONFIG_AG71XX_DEBUG_FS is not set ++CONFIG_ARCH_BINFMT_ELF_STATE=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_ARCH_DISCARD_MEMBLOCK=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++# CONFIG_ARCH_HAS_SG_CHAIN is not set ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y ++CONFIG_ARCH_SUPPORTS_UPROBES=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARCH_USE_BUILTIN_BSWAP=y ++CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y ++CONFIG_AT803X_PHY=y ++CONFIG_ATH79=y ++# CONFIG_ATH79_DEV_AP9X_PCI is not set ++# CONFIG_ATH79_DEV_DSA is not set ++# CONFIG_ATH79_DEV_ETH is not set ++# CONFIG_ATH79_DEV_GPIO_BUTTONS is not set ++# CONFIG_ATH79_DEV_LEDS_GPIO is not set ++# CONFIG_ATH79_DEV_M25P80 is not set ++# CONFIG_ATH79_DEV_SPI is not set ++# CONFIG_ATH79_DEV_USB is not set ++# CONFIG_ATH79_MACH_A60 is not set ++# CONFIG_ATH79_MACH_ALFA_AP120C is not set ++# CONFIG_ATH79_MACH_ALFA_AP96 is not set ++# CONFIG_ATH79_MACH_ALFA_NX is not set ++# CONFIG_ATH79_MACH_ALL0258N is not set ++# CONFIG_ATH79_MACH_ALL0315N is not set ++# CONFIG_ATH79_MACH_ANTMINER_S1 is not set ++# CONFIG_ATH79_MACH_ANTMINER_S3 is not set ++# CONFIG_ATH79_MACH_ANTROUTER_R1 is not set ++# CONFIG_ATH79_MACH_AP121 is not set ++# CONFIG_ATH79_MACH_AP121F is not set ++# CONFIG_ATH79_MACH_AP132 is not set ++# CONFIG_ATH79_MACH_AP136 is not set ++# CONFIG_ATH79_MACH_AP143 is not set ++# CONFIG_ATH79_MACH_AP147 is not set ++# CONFIG_ATH79_MACH_AP152 is not set ++# CONFIG_ATH79_MACH_AP531B0 is not set ++# CONFIG_ATH79_MACH_AP81 is not set ++# CONFIG_ATH79_MACH_AP90Q is not set ++# CONFIG_ATH79_MACH_AP91_5G is not set ++# CONFIG_ATH79_MACH_AP96 is not set ++# CONFIG_ATH79_MACH_ARCHER_C25_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C58_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C59_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C59_V2 is not set ++# CONFIG_ATH79_MACH_ARCHER_C60_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C60_V2 is not set ++# CONFIG_ATH79_MACH_ARCHER_C7 is not set ++# CONFIG_ATH79_MACH_ARDUINO_YUN is not set ++# CONFIG_ATH79_MACH_AW_NR580 is not set ++# CONFIG_ATH79_MACH_BHR_4GRV2 is not set ++# CONFIG_ATH79_MACH_BHU_BXU2000N2_A is not set ++# CONFIG_ATH79_MACH_BSB is not set ++# CONFIG_ATH79_MACH_C55 is not set ++# CONFIG_ATH79_MACH_C60 is not set ++# CONFIG_ATH79_MACH_CAP324 is not set ++# CONFIG_ATH79_MACH_CAP4200AG is not set ++# CONFIG_ATH79_MACH_CARAMBOLA2 is not set ++# CONFIG_ATH79_MACH_CF_E316N_V2 is not set ++# CONFIG_ATH79_MACH_CF_E320N_V2 is not set ++# CONFIG_ATH79_MACH_CF_E355AC is not set ++# CONFIG_ATH79_MACH_CF_E375AC is not set ++# CONFIG_ATH79_MACH_CF_E380AC_V1 is not set ++# CONFIG_ATH79_MACH_CF_E380AC_V2 is not set ++# CONFIG_ATH79_MACH_CF_E520N is not set ++# CONFIG_ATH79_MACH_CF_E530N is not set ++# CONFIG_ATH79_MACH_CPE505N is not set ++# CONFIG_ATH79_MACH_CPE510 is not set ++# CONFIG_ATH79_MACH_CPE830 is not set ++# CONFIG_ATH79_MACH_CPE870 is not set ++# CONFIG_ATH79_MACH_CR3000 is not set ++# CONFIG_ATH79_MACH_CR5000 is not set ++# CONFIG_ATH79_MACH_DAP_1330_A1 is not set ++# CONFIG_ATH79_MACH_DAP_2695_A1 is not set ++# CONFIG_ATH79_MACH_DB120 is not set ++# CONFIG_ATH79_MACH_DGL_5500_A1 is not set ++# CONFIG_ATH79_MACH_DHP_1565_A1 is not set ++# CONFIG_ATH79_MACH_DIR_505_A1 is not set ++# CONFIG_ATH79_MACH_DIR_600_A1 is not set ++# CONFIG_ATH79_MACH_DIR_615_C1 is not set ++# CONFIG_ATH79_MACH_DIR_615_I1 is not set ++# CONFIG_ATH79_MACH_DIR_825_B1 is not set ++# CONFIG_ATH79_MACH_DIR_825_C1 is not set ++# CONFIG_ATH79_MACH_DIR_869_A1 is not set ++# CONFIG_ATH79_MACH_DLAN_HOTSPOT is not set ++# CONFIG_ATH79_MACH_DLAN_PRO_1200_AC is not set ++# CONFIG_ATH79_MACH_DLAN_PRO_500_WP is not set ++# CONFIG_ATH79_MACH_DOMYWIFI_DW33D is not set ++# CONFIG_ATH79_MACH_DR342 is not set ++# CONFIG_ATH79_MACH_DR344 is not set ++# CONFIG_ATH79_MACH_DR531 is not set ++# CONFIG_ATH79_MACH_DRAGINO2 is not set ++# CONFIG_ATH79_MACH_E1700AC_V2 is not set ++# CONFIG_ATH79_MACH_E2100L is not set ++# CONFIG_ATH79_MACH_E558_V2 is not set ++# CONFIG_ATH79_MACH_E600G_V2 is not set ++# CONFIG_ATH79_MACH_E750A_V4 is not set ++# CONFIG_ATH79_MACH_E750G_V8 is not set ++# CONFIG_ATH79_MACH_EAP120 is not set ++# CONFIG_ATH79_MACH_EAP300V2 is not set ++# CONFIG_ATH79_MACH_EAP7660D is not set ++# CONFIG_ATH79_MACH_EL_M150 is not set ++# CONFIG_ATH79_MACH_EL_MINI is not set ++# CONFIG_ATH79_MACH_ENS202EXT is not set ++# CONFIG_ATH79_MACH_EPG5000 is not set ++# CONFIG_ATH79_MACH_ESR1750 is not set ++# CONFIG_ATH79_MACH_ESR900 is not set ++# CONFIG_ATH79_MACH_EW_BALIN is not set ++# CONFIG_ATH79_MACH_EW_DORIN is not set ++# CONFIG_ATH79_MACH_F9K1115V2 is not set ++# CONFIG_ATH79_MACH_FRITZ300E is not set ++# CONFIG_ATH79_MACH_FRITZ4020 is not set ++# CONFIG_ATH79_MACH_FRITZ450E is not set ++# CONFIG_ATH79_MACH_GL_AR150 is not set ++# CONFIG_ATH79_MACH_GL_AR300 is not set ++# CONFIG_ATH79_MACH_GL_AR300M is not set ++# CONFIG_ATH79_MACH_GL_AR750 is not set ++# CONFIG_ATH79_MACH_GL_AR750S is not set ++# CONFIG_ATH79_MACH_GL_DOMINO is not set ++# CONFIG_ATH79_MACH_GL_INET is not set ++# CONFIG_ATH79_MACH_GL_MIFI is not set ++# CONFIG_ATH79_MACH_GL_USB150 is not set ++# CONFIG_ATH79_MACH_GS_MINIBOX_V32 is not set ++# CONFIG_ATH79_MACH_GS_OOLITE_V1 is not set ++# CONFIG_ATH79_MACH_GS_OOLITE_V5_2 is not set ++# CONFIG_ATH79_MACH_HIVEAP_121 is not set ++# CONFIG_ATH79_MACH_HIWIFI_HC6361 is not set ++# CONFIG_ATH79_MACH_HORNET_UB is not set ++# CONFIG_ATH79_MACH_JA76PF is not set ++# CONFIG_ATH79_MACH_JWAP003 is not set ++# CONFIG_ATH79_MACH_JWAP230 is not set ++# CONFIG_ATH79_MACH_KOALA is not set ++# CONFIG_ATH79_MACH_LAN_TURTLE is not set ++# CONFIG_ATH79_MACH_LIMA is not set ++# CONFIG_ATH79_MACH_MC_MAC1200R is not set ++# CONFIG_ATH79_MACH_MR12 is not set ++# CONFIG_ATH79_MACH_MR16 is not set ++# CONFIG_ATH79_MACH_MR1750 is not set ++# CONFIG_ATH79_MACH_MR18 is not set ++# CONFIG_ATH79_MACH_MR600 is not set ++# CONFIG_ATH79_MACH_MR900 is not set ++# CONFIG_ATH79_MACH_MYNET_N600 is not set ++# CONFIG_ATH79_MACH_MYNET_N750 is not set ++# CONFIG_ATH79_MACH_MYNET_REXT is not set ++# CONFIG_ATH79_MACH_MZK_W04NU is not set ++# CONFIG_ATH79_MACH_MZK_W300NH is not set ++# CONFIG_ATH79_MACH_N5Q is not set ++# CONFIG_ATH79_MACH_NBG460N is not set ++# CONFIG_ATH79_MACH_NBG6716 is not set ++# CONFIG_ATH79_MACH_OM2P is not set ++# CONFIG_ATH79_MACH_OM5P is not set ++# CONFIG_ATH79_MACH_OM5P_AC is not set ++# CONFIG_ATH79_MACH_OM5P_ACv2 is not set ++# CONFIG_ATH79_MACH_OMY_G1 is not set ++# CONFIG_ATH79_MACH_OMY_X1 is not set ++# CONFIG_ATH79_MACH_ONION_OMEGA is not set ++# CONFIG_ATH79_MACH_PB42 is not set ++# CONFIG_ATH79_MACH_PB44 is not set ++# CONFIG_ATH79_MACH_PQI_AIR_PEN is not set ++# CONFIG_ATH79_MACH_QIHOO_C301 is not set ++# CONFIG_ATH79_MACH_R36A is not set ++# CONFIG_ATH79_MACH_R602N is not set ++# CONFIG_ATH79_MACH_R6100 is not set ++# CONFIG_ATH79_MACH_RAMBUTAN is not set ++# CONFIG_ATH79_MACH_RB2011 is not set ++# CONFIG_ATH79_MACH_RB4XX is not set ++# CONFIG_ATH79_MACH_RB750 is not set ++# CONFIG_ATH79_MACH_RB91X is not set ++# CONFIG_ATH79_MACH_RB922 is not set ++# CONFIG_ATH79_MACH_RB95X is not set ++# CONFIG_ATH79_MACH_RBSPI is not set ++# CONFIG_ATH79_MACH_RBSXTLITE is not set ++# CONFIG_ATH79_MACH_RE355 is not set ++# CONFIG_ATH79_MACH_RE450 is not set ++# CONFIG_ATH79_MACH_RME_EG200 is not set ++# CONFIG_ATH79_MACH_RUT9XX is not set ++# CONFIG_ATH79_MACH_RW2458N is not set ++# CONFIG_ATH79_MACH_SC1750 is not set ++# CONFIG_ATH79_MACH_SC300M is not set ++# CONFIG_ATH79_MACH_SC450 is not set ++# CONFIG_ATH79_MACH_SMART_300 is not set ++# CONFIG_ATH79_MACH_SOM9331 is not set ++# CONFIG_ATH79_MACH_SR3200 is not set ++# CONFIG_ATH79_MACH_T830 is not set ++# CONFIG_ATH79_MACH_TELLSTICK_ZNET_LITE is not set ++# CONFIG_ATH79_MACH_TEW_632BRP is not set ++# CONFIG_ATH79_MACH_TEW_673GRU is not set ++# CONFIG_ATH79_MACH_TEW_712BR is not set ++# CONFIG_ATH79_MACH_TEW_732BR is not set ++# CONFIG_ATH79_MACH_TEW_823DRU is not set ++# CONFIG_ATH79_MACH_TL_MR11U is not set ++# CONFIG_ATH79_MACH_TL_MR13U is not set ++# CONFIG_ATH79_MACH_TL_MR3020 is not set ++# CONFIG_ATH79_MACH_TL_MR3X20 is not set ++# CONFIG_ATH79_MACH_TL_MR6400 is not set ++# CONFIG_ATH79_MACH_TL_WA701ND_V2 is not set ++# CONFIG_ATH79_MACH_TL_WA7210N_V2 is not set ++# CONFIG_ATH79_MACH_TL_WA801ND_V3 is not set ++# CONFIG_ATH79_MACH_TL_WA830RE_V2 is not set ++# CONFIG_ATH79_MACH_TL_WA850RE_V2 is not set ++# CONFIG_ATH79_MACH_TL_WA855RE_V1 is not set ++# CONFIG_ATH79_MACH_TL_WA901ND is not set ++# CONFIG_ATH79_MACH_TL_WA901ND_V2 is not set ++# CONFIG_ATH79_MACH_TL_WA901ND_V4 is not set ++# CONFIG_ATH79_MACH_TL_WAX50RE is not set ++# CONFIG_ATH79_MACH_TL_WDR3320_V2 is not set ++# CONFIG_ATH79_MACH_TL_WDR3500 is not set ++# CONFIG_ATH79_MACH_TL_WDR4300 is not set ++# CONFIG_ATH79_MACH_TL_WDR6500_V2 is not set ++# CONFIG_ATH79_MACH_TL_WPA8630 is not set ++# CONFIG_ATH79_MACH_TL_WR1041N_V2 is not set ++# CONFIG_ATH79_MACH_TL_WR1043ND is not set ++# CONFIG_ATH79_MACH_TL_WR1043ND_V2 is not set ++# CONFIG_ATH79_MACH_TL_WR1043ND_V4 is not set ++# CONFIG_ATH79_MACH_TL_WR1043N_V5 is not set ++# CONFIG_ATH79_MACH_TL_WR2543N is not set ++# CONFIG_ATH79_MACH_TL_WR703N is not set ++# CONFIG_ATH79_MACH_TL_WR720N_V3 is not set ++# CONFIG_ATH79_MACH_TL_WR741ND is not set ++# CONFIG_ATH79_MACH_TL_WR741ND_V4 is not set ++# CONFIG_ATH79_MACH_TL_WR802N_V1 is not set ++# CONFIG_ATH79_MACH_TL_WR802N_V2 is not set ++# CONFIG_ATH79_MACH_TL_WR810N is not set ++# CONFIG_ATH79_MACH_TL_WR810N_V2 is not set ++# CONFIG_ATH79_MACH_TL_WR840N_V2 is not set ++# CONFIG_ATH79_MACH_TL_WR841N_V1 is not set ++# CONFIG_ATH79_MACH_TL_WR841N_V8 is not set ++# CONFIG_ATH79_MACH_TL_WR841N_V9 is not set ++# CONFIG_ATH79_MACH_TL_WR902AC_V1 is not set ++# CONFIG_ATH79_MACH_TL_WR940N_V4 is not set ++# CONFIG_ATH79_MACH_TL_WR941ND is not set ++# CONFIG_ATH79_MACH_TL_WR941ND_V6 is not set ++# CONFIG_ATH79_MACH_TL_WR942N_V1 is not set ++# CONFIG_ATH79_MACH_TS_D084 is not set ++# CONFIG_ATH79_MACH_TUBE2H is not set ++# CONFIG_ATH79_MACH_UBNT is not set ++# CONFIG_ATH79_MACH_UBNT_UNIFIAC is not set ++# CONFIG_ATH79_MACH_UBNT_XM is not set ++# CONFIG_ATH79_MACH_WAM250 is not set ++# CONFIG_ATH79_MACH_WEIO is not set ++# CONFIG_ATH79_MACH_WHR_HP_G300N is not set ++# CONFIG_ATH79_MACH_WI2A_AC200I is not set ++# CONFIG_ATH79_MACH_WIFI_PINEAPPLE_NANO is not set ++# CONFIG_ATH79_MACH_WLAE_AG300N is not set ++# CONFIG_ATH79_MACH_WLR8100 is not set ++# CONFIG_ATH79_MACH_WNDAP360 is not set ++# CONFIG_ATH79_MACH_WNDR3700 is not set ++# CONFIG_ATH79_MACH_WNDR4300 is not set ++# CONFIG_ATH79_MACH_WNR2000 is not set ++# CONFIG_ATH79_MACH_WNR2000_V3 is not set ++# CONFIG_ATH79_MACH_WNR2000_V4 is not set ++# CONFIG_ATH79_MACH_WNR2200 is not set ++# CONFIG_ATH79_MACH_WP543 is not set ++# CONFIG_ATH79_MACH_WPE72 is not set ++# CONFIG_ATH79_MACH_WPJ342 is not set ++# CONFIG_ATH79_MACH_WPJ344 is not set ++# CONFIG_ATH79_MACH_WPJ531 is not set ++# CONFIG_ATH79_MACH_WPJ558 is not set ++# CONFIG_ATH79_MACH_WPJ563 is not set ++# CONFIG_ATH79_MACH_WRT160NL is not set ++# CONFIG_ATH79_MACH_WRT400N is not set ++# CONFIG_ATH79_MACH_WRTNODE2Q is not set ++# CONFIG_ATH79_MACH_WZR_450HP2 is not set ++# CONFIG_ATH79_MACH_WZR_HP_AG300H is not set ++# CONFIG_ATH79_MACH_WZR_HP_G300NH is not set ++# CONFIG_ATH79_MACH_WZR_HP_G300NH2 is not set ++# CONFIG_ATH79_MACH_WZR_HP_G450H is not set ++# CONFIG_ATH79_MACH_XD3200 is not set ++# CONFIG_ATH79_MACH_Z1 is not set ++# CONFIG_ATH79_MACH_ZBT_WE1526 is not set ++# CONFIG_ATH79_MACH_ZCN_1523H is not set ++# CONFIG_ATH79_NVRAM is not set ++# CONFIG_ATH79_PCI_ATH9K_FIXUP is not set ++# CONFIG_ATH79_ROUTERBOOT is not set ++CONFIG_ATH79_WDT=y ++CONFIG_CEVT_R4K=y ++CONFIG_CLKDEV_LOOKUP=y ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_CMDLINE="rootfstype=squashfs noinitrd" ++CONFIG_CMDLINE_BOOL=y ++# CONFIG_CMDLINE_OVERRIDE is not set ++# CONFIG_COMMON_CLK_BOSTON is not set ++CONFIG_COMMON_CLK=y ++CONFIG_CPU_BIG_ENDIAN=y ++CONFIG_CPU_GENERIC_DUMP_TLB=y ++CONFIG_CPU_HAS_PREFETCH=y ++CONFIG_CPU_HAS_RIXI=y ++CONFIG_CPU_HAS_SYNC=y ++CONFIG_CPU_MIPS32=y ++CONFIG_CPU_MIPS32_R2=y ++CONFIG_CPU_MIPSR2=y ++CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y ++CONFIG_CPU_R4K_CACHE_TLB=y ++CONFIG_CPU_R4K_FPU=y ++CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y ++CONFIG_CPU_SUPPORTS_HIGHMEM=y ++CONFIG_CPU_SUPPORTS_MSA=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_WORKQUEUE=y ++CONFIG_CSRC_R4K=y ++CONFIG_DMA_NONCOHERENT=y ++CONFIG_EARLY_PRINTK=y ++CONFIG_ETHERNET_PACKET_MANGLE=y ++CONFIG_FIXED_PHY=y ++CONFIG_GENERIC_ATOMIC64=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CMOS_UPDATE=y ++CONFIG_GENERIC_IO=y ++CONFIG_GENERIC_IRQ_CHIP=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_GENERIC_PCI_IOMAP=y ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_GENERIC_SMP_IDLE_THREAD=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIOLIB_IRQCHIP=y ++CONFIG_GPIO_74X164=y ++CONFIG_GPIO_ATH79=y ++CONFIG_GPIO_GENERIC=y ++# CONFIG_GPIO_LATCH is not set ++CONFIG_GPIO_NXP_74HC153=y ++CONFIG_GPIO_PCF857X=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_HARDWARE_WATCHPOINTS=y ++CONFIG_HAS_DMA=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++# CONFIG_HAVE_ARCH_BITREVERSE is not set ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_ARCH_KGDB=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_ARCH_TRACEHOOK=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_HAVE_CBPF_JIT=y ++CONFIG_HAVE_CC_STACKPROTECTOR=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_CLK_PREPARE=y ++CONFIG_HAVE_CONTEXT_TRACKING=y ++CONFIG_HAVE_C_RECORDMCOUNT=y ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++CONFIG_HAVE_DEBUG_STACKOVERFLOW=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++CONFIG_HAVE_DMA_CONTIGUOUS=y ++CONFIG_HAVE_DYNAMIC_FTRACE=y ++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y ++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y ++CONFIG_HAVE_FUNCTION_TRACER=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_HAVE_IDE=y ++CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y ++CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y ++CONFIG_HAVE_KVM=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_HAVE_MEMBLOCK_NODE_MAP=y ++CONFIG_HAVE_MOD_ARCH_SPECIFIC=y ++CONFIG_HAVE_NET_DSA=y ++CONFIG_HAVE_OPROFILE=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y ++CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y ++CONFIG_HZ_PERIODIC=y ++CONFIG_I2C=y ++CONFIG_I2C_ALGOBIT=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_GPIO=y ++CONFIG_IMAGE_CMDLINE_HACK=y ++CONFIG_INITRAMFS_ROOT_GID=0 ++CONFIG_INITRAMFS_ROOT_UID=0 ++CONFIG_INITRAMFS_SOURCE="../../root" ++CONFIG_INTEL_XWAY_PHY=y ++CONFIG_IP17XX_PHY=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_IRQ_MIPS_CPU=y ++CONFIG_IRQ_WORK=y ++CONFIG_LEDS_GPIO=y ++CONFIG_MARVELL_PHY=y ++CONFIG_MDIO_BITBANG=y ++CONFIG_MDIO_BOARDINFO=y ++CONFIG_MDIO_GPIO=y ++CONFIG_MICREL_PHY=y ++CONFIG_MIPS=y ++CONFIG_MIPS_ASID_BITS=8 ++CONFIG_MIPS_ASID_SHIFT=0 ++CONFIG_MIPS_CLOCK_VSYSCALL=y ++# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set ++CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER=y ++# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set ++CONFIG_MIPS_L1_CACHE_SHIFT=5 ++CONFIG_MIPS_MACHINE=y ++CONFIG_MIPS_SPRAM=y ++CONFIG_MODULES_USE_ELF_REL=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_GEOMETRY=y ++# CONFIG_MTD_CFI_I2 is not set ++# CONFIG_MTD_CFI_INTELEXT is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_CYBERTAN_PARTS=y ++CONFIG_MTD_M25P80=y ++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set ++CONFIG_MTD_MYLOADER_PARTS=y ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2 ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_SPLIT_EVA_FW=y ++CONFIG_MTD_SPLIT_FIRMWARE=y ++CONFIG_MTD_SPLIT_LZMA_FW=y ++CONFIG_MTD_SPLIT_MINOR_FW=y ++CONFIG_MTD_SPLIT_SEAMA_FW=y ++CONFIG_MTD_SPLIT_TPLINK_FW=y ++CONFIG_MTD_SPLIT_UIMAGE_FW=y ++CONFIG_MTD_SPLIT_WRGG_FW=y ++CONFIG_MTD_TPLINK_PARTS=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_PER_CPU_KM=y ++CONFIG_NET_DSA=y ++CONFIG_NET_DSA_MV88E6060=y ++CONFIG_NET_DSA_MV88E6063=y ++CONFIG_NET_DSA_TAG_TRAILER=y ++CONFIG_NET_SWITCHDEV=y ++CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y ++# CONFIG_NO_IOPORT_MAP is not set ++# CONFIG_OF is not set ++# CONFIG_PCI_AR724X is not set ++CONFIG_PCI_DRIVERS_LEGACY=y ++CONFIG_PERF_USE_VMALLOC=y ++CONFIG_PGTABLE_LEVELS=2 ++CONFIG_PHYLIB=y ++CONFIG_RATIONAL=y ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCSI_DMA is not set ++# CONFIG_SERIAL_8250_FSL is not set ++CONFIG_SERIAL_8250_NR_UARTS=1 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=1 ++# CONFIG_SOC_AR71XX is not set ++# CONFIG_SOC_AR724X is not set ++# CONFIG_SOC_AR913X is not set ++# CONFIG_SOC_AR933X is not set ++# CONFIG_SOC_AR934X is not set ++# CONFIG_SOC_QCA953X is not set ++# CONFIG_SOC_QCA955X is not set ++# CONFIG_SOC_QCA956X is not set ++CONFIG_SPI=y ++CONFIG_SPI_ATH79=y ++CONFIG_SPI_BITBANG=y ++CONFIG_SPI_GPIO=y ++CONFIG_SPI_MASTER=y ++# CONFIG_SPI_RB4XX is not set ++# CONFIG_SPI_VSC7385 is not set ++CONFIG_SRCU=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=y ++CONFIG_SYS_HAS_CPU_MIPS32_R2=y ++CONFIG_SYS_HAS_EARLY_PRINTK=y ++CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y ++CONFIG_SYS_SUPPORTS_ARBIT_HZ=y ++CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y ++CONFIG_SYS_SUPPORTS_MIPS16=y ++CONFIG_SYS_SUPPORTS_ZBOOT=y ++CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM=y ++CONFIG_TICK_CPU_ACCOUNTING=y ++CONFIG_USB_SUPPORT=y ++# CONFIG_MTD_SPLIT_ELF_FW is not set ++# CONFIG_MTD_SPLIT_BCM63XX_FW is not set +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +new file mode 100644 +index 0000000000..6fd78c46a0 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -0,0 +1,2458 @@ ++config ATH79_MACH_A60 ++ bool "OpenMesh A40/A60 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_WI2A_AC200I ++ bool "Nokia WI2A-AC200i support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_NFC ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_ALFA_AP120C ++ bool "ALFA Network AP120C board support" ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_AP121F ++ bool "ALFA Network AP121F support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ALFA_AP96 ++ bool "ALFA Network AP96 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_HORNET_UB ++ bool "ALFA Network Hornet-UB board support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ALFA_NX ++ bool "ALFA Network N2/N5 board support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_TUBE2H ++ bool "ALFA Network Tube2H board support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_SC1750 ++ bool "Abicom SC1750 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_SC300M ++ bool "Abicom SC300M board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_SC450 ++ bool "Abicom SC450 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ALL0258N ++ bool "Allnet ALL0258N support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_ALL0315N ++ bool "Allnet ALL0315N support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_ANTMINER_S1 ++ bool "Bitmain Antminer S1 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ANTMINER_S3 ++ bool "Bitmain Antminer S3 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ANTROUTER_R1 ++ bool "Bitmain Antrouter R1 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARDUINO_YUN ++ bool "Arduino Yun" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_AP132 ++ bool "Atheros AP132 reference board" ++ select SOC_QCA955X ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_AP143 ++ bool "Atheros AP143 reference board" ++ select SOC_QCA953X ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_SPI ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_ETH ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_AP147 ++ bool "Atheros AP147 reference board" ++ select SOC_QCA953X ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_AP9X_PCI if PCI ++ ++config ATH79_MACH_AP152 ++ bool "Atheros AP152 reference board" ++ select SOC_QCA956X ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_AP9X_PCI if PCI ++ ++config ATH79_MACH_AP531B0 ++ bool "Rockeetech AP531B0 support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_SPI ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_AP90Q ++ bool "YunCore AP80Q/AP90Q support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_AP91_5G ++ bool "ALFA Network AP91-5G support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_AP96 ++ bool "Atheros AP96 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_PB42 ++ bool "Atheros PB42 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_C55 ++ bool "AirTight Networks C-55 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_C60 ++ bool "AirTight Networks C-60 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_AW_NR580 ++ bool "AzureWave AW-NR580 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_F9K1115V2 ++ bool "Belkin AC1750DB board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_EPG5000 ++ bool "EnGenius EPG5000 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_ESR1750 ++ bool "EnGenius ESR1750 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_PQI_AIR_PEN ++ bool "PQI Air Pen" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_SOM9331 ++ bool "SOM9331 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_SR3200 ++ bool "YunCore SR3200 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_BHR_4GRV2 ++ bool "Buffalo BHR-4GRV2 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_WHR_HP_G300N ++ bool "Buffalo WHR-HP-G300N board support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_WLAE_AG300N ++ bool "Buffalo WLAE-AG300N board support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_WLR8100 ++ bool "Sitecom WLR-8100 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WZR_HP_AG300H ++ bool "Buffalo WZR-HP-AG300H board support" ++ select SOC_AR71XX ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_WZR_HP_G300NH ++ bool "Buffalo WZR-HP-G300NH board support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select RTL8366_SMI ++ ++config ATH79_MACH_WZR_HP_G300NH2 ++ bool "Buffalo WZR-HP-G300NH2 board support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_WZR_HP_G450H ++ bool "Buffalo WZR-HP-G450H board support" ++ select SOC_AR724X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_WZR_450HP2 ++ bool "Buffalo WZR-450HP2 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WP543 ++ bool "Compex WP543/WPJ543 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select MYLOADER ++ ++config ATH79_MACH_WPE72 ++ bool "Compex WPE72/WPE72NX board support" ++ select SOC_AR724X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select MYLOADER ++ ++config ATH79_MACH_WPJ342 ++ bool "Compex WPJ342 board support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WPJ344 ++ bool "Compex WPJ344 board support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WPJ531 ++ bool "Compex WPJ531 board support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WPJ558 ++ bool "Compex WPJ558 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WPJ563 ++ bool "Compex WPJ563 board support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_XD3200 ++ bool "YunCore XD3200 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DGL_5500_A1 ++ bool "D-Link DGL-5500 A1 support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_DHP_1565_A1 ++ bool "D-Link DHP-1565 rev. A1 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DIR_505_A1 ++ bool "D-Link DIR-505-A1 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DIR_600_A1 ++ bool "D-Link DIR-600 A1/DIR-615 E1/DIR-615 E4 support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_NVRAM ++ ++config ATH79_MACH_DIR_615_C1 ++ bool "D-Link DIR-615 rev. C1 support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_DIR_615_I1 ++ bool "D-Link DIR-615 rev. I1 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DIR_825_B1 ++ bool "D-Link DIR-825 rev. B1 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_DIR_825_C1 ++ bool "D-Link DIR-825 rev. C1/DIR-835 rev. A1 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DIR_869_A1 ++ bool "D-Link DIR-869 rev. A1" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_DLAN_HOTSPOT ++ bool "devolo dLAN Hotspot support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DLAN_PRO_500_WP ++ bool "devolo dLAN pro 500 Wireless+ support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_SPI ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_DLAN_PRO_1200_AC ++ bool "devolo dLAN pro 1200+ WiFi ac support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_SPI ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_DOMYWIFI_DW33D ++ bool "DomyWifi DW33D support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_NFC ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_DR342 ++ bool "Wallys DR342 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DR344 ++ bool "Wallys DR344 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DR531 ++ bool "Wallys DR531 board support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DRAGINO2 ++ bool "DRAGINO V2 support" ++ select SOC_AR933X ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_ETH ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_E1700AC_V2 ++ bool "Qxwlan E1700AC v2 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_E2100L ++ bool "Linksys E2100L board support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_E558_V2 ++ bool "Qxwlan E558 v2 support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_E600G_V2 ++ bool "Qxwlan E600G/E600GAC v2 support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_E750A_V4 ++ bool "Qxwlan E750A v4 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_E750G_V8 ++ bool "Qxwlan E750G v8 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ESR900 ++ bool "EnGenius ESR900 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_EW_BALIN ++ bool "embedded wireless Balin Platform support" ++ select SOC_AR934X ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_ETH ++ select ATH79_DEV_USB ++ select ATH79_DEV_AP9X_PCI if PCI ++ ++config ATH79_MACH_EW_DORIN ++ bool "embedded wireless Dorin Platform support" ++ select SOC_AR933X ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_ETH ++ ++config ATH79_MACH_EL_M150 ++ bool "EasyLink EL-M150 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_EL_MINI ++ bool "EasyLink EL-MINI support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_AR150 ++ bool "GL AR150 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_AR300 ++ bool "GL_AR300 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_AR300M ++ bool "GL_AR300M support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_AR750 ++ bool "GL.iNet GL-AR750 support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_AR750S ++ bool "GL.iNet GL-AR750S support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_DOMINO ++ bool "DOMINO support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_MIFI ++ bool "GL MIFI support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_INET ++ bool "GL-INET support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GL_USB150 ++ bool "GL.iNet GL-USB150 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_EAP120 ++ bool "TP-LINK EAP120 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ENS202EXT ++ bool "EnGenius ENS202EXT support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_EAP300V2 ++ bool "EnGenius EAP300 v2 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GS_MINIBOX_V32 ++ bool "Gainstrong Minibox V3.2 support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_SPI ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_ETH ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_GS_OOLITE_V1 ++ bool "GainStrong Oolite/Minibox V1.0 support" ++ select SOC_AR933X ++ select ARH79_DEV_ETH ++ select ARH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_GS_OOLITE_V5_2 ++ bool "GainStrong Oolite V5.2 support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_HIVEAP_121 ++ bool "Aerohive HiveAP-121 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_HIWIFI_HC6361 ++ bool "HiWiFi HC6361 board support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_JA76PF ++ bool "jjPlus JA76PF board support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_JWAP003 ++ bool "jjPlus JWAP003 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_JWAP230 ++ bool "jjPlus JWAP230 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_KOALA ++ bool "OCEDO Koala board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_ETH ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WAM250 ++ bool "Samsung WAM250 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WIFI_PINEAPPLE_NANO ++ bool "Hak5 WiFi Pineapple NANO support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WRT160NL ++ bool "Linksys WRT160NL board support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_WRT400N ++ bool "Linksys WRT400N board support" ++ select SOC_AR71XX ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_WRTNODE2Q ++ bool "WRTnode2Q board support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_R36A ++ bool "ALFA Network R36A support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_R602N ++ bool "P&W R602N support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_R6100 ++ bool "NETGEAR R6100 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MC_MAC1200R ++ bool "MERCURY MAC1200R board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_RB4XX ++ bool "MikroTik RouterBOARD 4xx series support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_RB750 ++ bool "MikroTik RouterBOARD 750 support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_USB ++ select ATH79_ROUTERBOOT ++ ++config ATH79_MACH_RB91X ++ bool "MikroTik RouterBOARD 91X support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_SPI ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ select ATH79_ROUTERBOOT ++ ++config ATH79_MACH_RB922 ++ bool "MikroTik RouterBOARD 922 support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_ROUTERBOOT ++ select RLE_DECOMPRESS ++ ++config ATH79_MACH_RB95X ++ bool "MikroTik RouterBOARD 95X support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_NFC ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ select ATH79_ROUTERBOOT ++ ++config ATH79_MACH_RB2011 ++ bool "MikroTik RouterBOARD 2011 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_ROUTERBOOT ++ ++config ATH79_MACH_RBSPI ++ bool "MikroTik RouterBOARD SPI-NOR support" ++ select SOC_AR934X ++ select SOC_QCA953X ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_ROUTERBOOT ++ help ++ Say 'Y' here if you want your kernel to support the ++ MikroTik ROuterBOARD 911-2Hn (911 Lite2) ++ MikroTik ROuterBOARD 911-5Hn (911 Lite5) ++ MikroTik RouterBOARD mAP ++ MikroTik RouterBOARD mAP lite ++ MikroTik RouterBOARD hAP mini ++ MikroTik RouterBOARD hAP lite ++ MikroTik RouterBOARD hAP ++ MikroTik RouterBOARD hAP ac ++ MikroTik RouterBOARD hAP ac lite ++ MikroTik RouterBOARD hEX PoE lite ++ MikroTik RouterBOARD hEX lite ++ MikroTik RouterBOARD Powerbox ++ MikroTik RouterBOARD LHG 5 ++ MikroTik RouterBOARD cAP (EXPERIMENTAL) ++ MikroTik RouterBOARD SXT Lite 2 r3 ++ MikroTik RouterBOARD wAP ++ MikroTik RouterBOARD wAP R-2nD ++ ++config ATH79_MACH_RBSXTLITE ++ bool "MikroTik RouterBOARD SXT Lite" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_NFC ++ select ATH79_DEV_WMAC ++ select ATH79_ROUTERBOOT ++ ++config ATH79_MACH_SMART_300 ++ bool "NC-LINK SMART-300 board support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_T830 ++ bool "YunCore T830 support" ++ select SOC_QCA953X ++ select ARH79_DEV_ETH ++ select ARH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TELLSTICK_ZNET_LITE ++ bool "TellStick ZNet Lite" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WNDAP360 ++ bool "NETGEAR WNDAP360 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_WNDR3700 ++ bool "NETGEAR WNDR3700 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_WNDR4300 ++ bool "NETGEAR WNDR3700v4/WNDR4300 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WNR2000 ++ bool "NETGEAR WNR2000 board support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_WNR2000_V3 ++ bool "NETGEAR WNR2000 V3/WNR612 v2/WNR1000 v2/WPN824N board support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_WNR2200 ++ bool "NETGEAR WNR2200 board support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_WNR2000_V4 ++ bool "NETGEAR WNR2000 V4" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_OM2P ++ bool "OpenMesh OM2P board support" ++ select SOC_AR724X ++ select SOC_AR933X ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_OM5P ++ bool "OpenMesh OM5P board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_OM5P_AC ++ bool "OpenMesh OM5P-AC board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_OM5P_ACv2 ++ bool "OpenMesh OM5P-ACv2 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_OMY_G1 ++ bool "OMYlink OMY G1 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_OMY_X1 ++ bool "OMYlink OMY X1 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ONION_OMEGA ++ bool "ONION OMEGA support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MR12 ++ bool "Meraki MR12 board support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MR16 ++ bool "Meraki MR16 board support" ++ select SOC_AR71XX ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MR18 ++ bool "Meraki MR18 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_NFC ++ select ATH79_DEV_WMAC ++ select LEDS_NU801 ++ ++config ATH79_MACH_MR600 ++ bool "OpenMesh MR600 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MZK_W04NU ++ bool "Planex MZK-W04NU board support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MZK_W300NH ++ bool "Planex MZK-W300NH board support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_RE355 ++ bool "TP-LINK RE355 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_RE450 ++ bool "TP-LINK RE450 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_RME_EG200 ++ bool "eTactica EG200 board supprt" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_RUT9XX ++ bool "Teltonika RUT900 series support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select GPIO_PCA953X ++ ++config ATH79_MACH_RW2458N ++ bool "Redwave RW2458N board support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_CAP324 ++ bool "PowerCloud Systems CAP324 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CAP4200AG ++ bool "Senao CAP4200AG support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CR3000 ++ bool "PowerCloud Systems CR3000 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CR5000 ++ bool "PowerCloud CR5000 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MR1750 ++ bool "OpenMesh MR1750 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MR900 ++ bool "OpenMesh MR900 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_EAP7660D ++ bool "Senao EAP7660D support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_BSB ++ bool "Smart Electronics Black Swift board" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARCHER_C25_V1 ++ bool "TP-LINK Archer C25 v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARCHER_C58_V1 ++ bool "TP-LINK Archer C58 v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARCHER_C59_V1 ++ bool "TP-LINK Archer C59 v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARCHER_C59_V2 ++ bool "TP-LINK Archer C59 v2 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARCHER_C60_V1 ++ bool "TP-LINK Archer C60 v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARCHER_C60_V2 ++ bool "TP-LINK Archer C60 v2 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARCHER_C7 ++ bool "TP-LINK Archer C5/C7/TL-WDR4900 v2 board support" ++ select SOC_QCA955X ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CPE505N ++ bool "P&W CPE505N support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CPE510 ++ bool "TP-LINK CPE510 support" ++ select SOC_AR934X ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CPE830 ++ bool "YunCore CPE830 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CPE870 ++ bool "YunCore CPE870 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_MR11U ++ bool "TP-LINK TL-MR11U/TL-MR3040 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_MR13U ++ bool "TP-LINK TL-MR13U support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_MR3020 ++ bool "TP-LINK TL-MR3020 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_MR3X20 ++ bool "TP-LINK TL-MR3220/3420 support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_TL_MR6400 ++ bool "TP-LINK TL-MR6400 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WAX50RE ++ bool "TP-LINK TL-WA750/850RE support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WA701ND_V2 ++ bool "TP-LINK TL-WA701ND v2 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WA7210N_V2 ++ bool "TP-LINK TL-WA7210N v2 support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WA801ND_V3 ++ bool "TP-LINK TL-WA801ND v3 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WA830RE_V2 ++ bool "TP-LINK TL-WA830RE v2 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WA850RE_V2 ++ bool "TP-LINK TL-WA850RE v2 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WA855RE_V1 ++ bool "TP-LINK TL-WA855RE V1 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WA901ND ++ bool "TP-LINK TL-WA901ND/TL-WA7510N support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_TL_WA901ND_V2 ++ bool "TP-LINK TL-WA901ND v2 support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WA901ND_V4 ++ bool "TP-LINK TL-WA901ND v4 support" ++ select SOC_QCA956X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WDR3320_V2 ++ bool "TP-LINK TL-WDR3320 v2 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WDR3500 ++ bool "TP-LINK TL-WDR3500 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WDR4300 ++ bool "TP-LINK TL-WDR3600/4300/4310 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WDR6500_V2 ++ bool "TP-LINK TL-WDR6500 v2 board support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR703N ++ bool "TP-LINK TL-WR703N/TL-WR710N/TL-MR10U support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR720N_V3 ++ bool "TP-LINK TL-WR720N v3/v4 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR741ND ++ bool "TP-LINK TL-WR741ND support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_TL_WR741ND_V4 ++ bool "TP-LINK TL-WR741ND v4/TL-MR3220 v2 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR802N_V1 ++ bool "TP-LINK TL-WR802N v1 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_TL_WR802N_V2 ++ bool "TP-LINK TL-WR802N v2 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_TL_WR810N ++ bool "TP-LINK TL-WR810N support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR810N_V2 ++ bool "TP-LINK TL-WR810N v2 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR840N_V2 ++ bool "TP-LINK TL-WR840N v2/v3 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR841N_V1 ++ bool "TP-LINK TL-WR841N v1 support" ++ select SOC_AR71XX ++ select ATH79_DEV_DSA ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_TL_WR841N_V8 ++ bool "TP-LINK TL-WR841N/ND v8/TL-MR3420 v2 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR841N_V9 ++ bool "TP-LINK TL-WR841N/ND v9/TL-WR842N/ND v3/TL-WR740N/ND v6 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR902AC_V1 ++ bool "TP-LINK TL-WR902AC v1 support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR941ND ++ bool "TP-LINK TL-WR941ND support" ++ select SOC_AR913X ++ select ATH79_DEV_DSA ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR941ND_V6 ++ bool "TP-LINK TL-WR941ND v6 support" ++ select SOC_QCA956X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR940N_V4 ++ bool "TP-LINK TL-WR940N v4 support" ++ select SOC_QCA956X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR942N_V1 ++ bool "TP-LINK TL-WR942N v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_TL_WR1041N_V2 ++ bool "TP-LINK TL-WR1041N v2 support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR1043N_V5 ++ bool "TP-LINK TL-WR1043N v5 support" ++ select SOC_QCA956X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR1043ND ++ bool "TP-LINK TL-WR1043ND support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR1043ND_V2 ++ bool "TP-LINK TL-WR1043ND v2 support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR1043ND_V4 ++ bool "TP-LINK TL-WR1043ND v4 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TL_WR2543N ++ bool "TP-LINK TL-WR2543N/ND support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_TS_D084 ++ bool "PISEN TS-D084 support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TEW_632BRP ++ bool "TRENDnet TEW-632BRP support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_TEW_673GRU ++ bool "TRENDnet TEW-673GRU support" ++ select SOC_AR71XX ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_TEW_712BR ++ bool "TRENDnet TEW-712BR support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TEW_732BR ++ bool "TRENDnet TEW-732BR support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_TEW_823DRU ++ bool "TRENDnet TEW-823DRU support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_UBNT ++ bool "Ubiquiti AR71xx based boards support" ++ select SOC_AR71XX ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_UBNT_UNIFIAC ++ bool "Ubiquiti UniFi AC (LITE/LR/MESH/PRO/MESH-PRO) support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_WEIO ++ bool "WeIO board" ++ select SOC_AR933X ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_MYNET_N600 ++ bool "WD My Net N600 board support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_MYNET_N750 ++ bool "WD My Net N750 board support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_MYNET_REXT ++ bool "WD My Net Wi-Fi Range Extender board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_Z1 ++ bool "Meraki Z1 board support" ++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select LEDS_NU801 ++ ++config ATH79_MACH_ZBT_WE1526 ++ bool "Zbtlink ZBT-WE1526 board support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ZCN_1523H ++ bool "Zcomax ZCN-1523H support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_N5Q ++ bool "ALFA Network N5Q support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_NBG460N ++ bool "Zyxel NBG460N/550N/550NH board support" ++ select SOC_AR913X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_NBG6716 ++ bool "Zyxel NBG6616/NBG6716 board support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_CARAMBOLA2 ++ bool "8devices Carambola2 board" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_LAN_TURTLE ++ bool "Hak5 LAN Turtle and Packet Squirrel support" ++ select SOC_AR933X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ ++config ATH79_MACH_LIMA ++ bool "8devices Lima board" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_SPI ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_ETH ++ ++config ATH79_MACH_RAMBUTAN ++ bool "8devices Rambutan board" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CF_E316N_V2 ++ bool "COMFAST CF-E316N v2 support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CF_E320N_V2 ++ bool "COMFAST CF-E320N v2 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CF_E355AC ++ bool "COMFAST CF-E355AC v1/v2 support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CF_E375AC ++ bool "COMFAST CF-E375AC support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CF_E380AC_V1 ++ bool "COMFAST CF-E380AC v1 support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CF_E380AC_V2 ++ bool "COMFAST CF-E380AC v2 support" ++ select SOC_QCA955X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CF_E520N ++ bool "COMFAST CF-E520N support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_CF_E530N ++ bool "COMFAST CF-E530N support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_BHU_BXU2000N2_A ++ bool "BHU BXU2000n-2 rev. A support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_QIHOO_C301 ++ bool "Qihoo 360 C301 board support" ++ select SOC_AR934X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_DEV_USB ++ select ATH79_NVRAM ++ ++config ATH79_MACH_DAP_1330_A1 ++ bool "D-Link DAP-1330 rev. A1 support" ++ select SOC_QCA953X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_DAP_2695_A1 ++ bool "D-Link DAP-2695 rev. A1 support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ select ATH79_NVRAM ++ ++config ATH79_MACH_TL_WPA8630 ++ bool "TP-Link TL-WPA8630 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_FRITZ300E ++ bool "AVM FRITZ!WLAN Repeater 300E support" ++ select SOC_AR724X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_FRITZ4020 ++ bool "AVM FRITZ!Box 4020 support" ++ select SOC_QCA956X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_USB ++ select ATH79_DEV_M25P80 ++ ++config ATH79_MACH_FRITZ450E ++ bool "AVM FRITZ!WLAN Repeater 450E support" ++ select SOC_QCA955X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Makefile b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +new file mode 100644 +index 0000000000..0265b3d818 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +@@ -0,0 +1,290 @@ ++# ++# Makefile for the Atheros AR71XX/AR724X/AR913X specific parts of the kernel ++# ++# Copyright (C) 2008-2011 Gabor Juhos ++# Copyright (C) 2008 Imre Kaloz ++# ++# 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. ++ ++obj-y := prom.o setup.o irq.o common.o clock.o gpio.o ++ ++obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ++obj-$(CONFIG_PCI) += pci.o ++ ++# ++# Devices ++# ++obj-y += dev-common.o ++obj-$(CONFIG_ATH79_DEV_AP9X_PCI) += dev-ap9x-pci.o ++obj-$(CONFIG_ATH79_DEV_DSA) += dev-dsa.o ++obj-$(CONFIG_ATH79_DEV_ETH) += dev-eth.o ++obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS) += dev-gpio-buttons.o ++obj-$(CONFIG_ATH79_DEV_LEDS_GPIO) += dev-leds-gpio.o ++obj-$(CONFIG_ATH79_DEV_M25P80) += dev-m25p80.o ++obj-$(CONFIG_ATH79_DEV_NFC) += dev-nfc.o ++obj-$(CONFIG_ATH79_DEV_SPI) += dev-spi.o ++obj-$(CONFIG_ATH79_DEV_USB) += dev-usb.o ++obj-$(CONFIG_ATH79_DEV_WMAC) += dev-wmac.o ++ ++# ++# Miscellaneous objects ++# ++obj-$(CONFIG_ATH79_NVRAM) += nvram.o ++obj-$(CONFIG_ATH79_PCI_ATH9K_FIXUP) += pci-ath9k-fixup.o ++obj-$(CONFIG_ATH79_ROUTERBOOT) += routerboot.o ++ ++# ++# Machines ++# ++obj-$(CONFIG_ATH79_MACH_A60) += mach-a60.o ++obj-$(CONFIG_ATH79_MACH_WI2A_AC200I) += mach-wi2a-ac200i.o ++obj-$(CONFIG_ATH79_MACH_ALFA_AP120C) += mach-alfa-ap120c.o ++obj-$(CONFIG_ATH79_MACH_ALFA_AP96) += mach-alfa-ap96.o ++obj-$(CONFIG_ATH79_MACH_ALFA_NX) += mach-alfa-nx.o ++obj-$(CONFIG_ATH79_MACH_ALL0258N) += mach-all0258n.o ++obj-$(CONFIG_ATH79_MACH_ALL0315N) += mach-all0315n.o ++obj-$(CONFIG_ATH79_MACH_ANTMINER_S1) += mach-antminer-s1.o ++obj-$(CONFIG_ATH79_MACH_ANTMINER_S3) += mach-antminer-s3.o ++obj-$(CONFIG_ATH79_MACH_ANTROUTER_R1) += mach-antrouter-r1.o ++obj-$(CONFIG_ATH79_MACH_AP121) += mach-ap121.o ++obj-$(CONFIG_ATH79_MACH_AP121F) += mach-ap121f.o ++obj-$(CONFIG_ATH79_MACH_AP132) += mach-ap132.o ++obj-$(CONFIG_ATH79_MACH_AP136) += mach-ap136.o ++obj-$(CONFIG_ATH79_MACH_AP143) += mach-ap143.o ++obj-$(CONFIG_ATH79_MACH_AP147) += mach-ap147.o ++obj-$(CONFIG_ATH79_MACH_AP152) += mach-ap152.o ++obj-$(CONFIG_ATH79_MACH_AP531B0) += mach-ap531b0.o ++obj-$(CONFIG_ATH79_MACH_AP90Q) += mach-ap90q.o ++obj-$(CONFIG_ATH79_MACH_AP91_5G) += mach-ap91-5g.o ++obj-$(CONFIG_ATH79_MACH_AP96) += mach-ap96.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C25_V1) += mach-archer-c25-v1.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C58_V1) += mach-archer-c59-v1.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C59_V1) += mach-archer-c59-v1.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C60_V1) += mach-archer-c60-v1.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C60_V2) += mach-archer-c60-v1.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7-v4.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7-v5.o ++obj-$(CONFIG_ATH79_MACH_ARDUINO_YUN) += mach-arduino-yun.o ++obj-$(CONFIG_ATH79_MACH_AW_NR580) += mach-aw-nr580.o ++obj-$(CONFIG_ATH79_MACH_BHR_4GRV2) += mach-bhr-4grv2.o ++obj-$(CONFIG_ATH79_MACH_BHU_BXU2000N2_A) += mach-bhu-bxu2000n2-a.o ++obj-$(CONFIG_ATH79_MACH_BSB) += mach-bsb.o ++obj-$(CONFIG_ATH79_MACH_C55) += mach-c55.o ++obj-$(CONFIG_ATH79_MACH_C60) += mach-c60.o ++obj-$(CONFIG_ATH79_MACH_CAP324) += mach-cap324.o ++obj-$(CONFIG_ATH79_MACH_CAP4200AG) += mach-cap4200ag.o ++obj-$(CONFIG_ATH79_MACH_CARAMBOLA2) += mach-carambola2.o ++obj-$(CONFIG_ATH79_MACH_CF_E316N_V2) += mach-cf-e316n-v2.o ++obj-$(CONFIG_ATH79_MACH_CF_E320N_V2) += mach-cf-e316n-v2.o ++obj-$(CONFIG_ATH79_MACH_CF_E355AC) += mach-cf-e316n-v2.o ++obj-$(CONFIG_ATH79_MACH_CF_E375AC) += mach-cf-e316n-v2.o ++obj-$(CONFIG_ATH79_MACH_CF_E380AC_V1) += mach-cf-e316n-v2.o ++obj-$(CONFIG_ATH79_MACH_CF_E380AC_V2) += mach-cf-e316n-v2.o ++obj-$(CONFIG_ATH79_MACH_CF_E520N) += mach-cf-e316n-v2.o ++obj-$(CONFIG_ATH79_MACH_CF_E530N) += mach-cf-e316n-v2.o ++obj-$(CONFIG_ATH79_MACH_CPE505N) += mach-r602n.o ++obj-$(CONFIG_ATH79_MACH_CPE510) += mach-cpe510.o ++obj-$(CONFIG_ATH79_MACH_CPE830) += mach-ap90q.o ++obj-$(CONFIG_ATH79_MACH_CPE870) += mach-cpe870.o ++obj-$(CONFIG_ATH79_MACH_CR3000) += mach-cr3000.o ++obj-$(CONFIG_ATH79_MACH_CR5000) += mach-cr5000.o ++obj-$(CONFIG_ATH79_MACH_DAP_1330_A1) += mach-dap-1330-a1.o ++obj-$(CONFIG_ATH79_MACH_DAP_2695_A1) += mach-dap-2695-a1.o ++obj-$(CONFIG_ATH79_MACH_DB120) += mach-db120.o ++obj-$(CONFIG_ATH79_MACH_DGL_5500_A1) += mach-dgl-5500-a1.o ++obj-$(CONFIG_ATH79_MACH_DHP_1565_A1) += mach-dhp-1565-a1.o ++obj-$(CONFIG_ATH79_MACH_DIR_505_A1) += mach-dir-505-a1.o ++obj-$(CONFIG_ATH79_MACH_DIR_600_A1) += mach-dir-600-a1.o ++obj-$(CONFIG_ATH79_MACH_DIR_615_C1) += mach-dir-615-c1.o ++obj-$(CONFIG_ATH79_MACH_DIR_615_I1) += mach-dir-615-i1.o ++obj-$(CONFIG_ATH79_MACH_DIR_825_B1) += mach-dir-825-b1.o ++obj-$(CONFIG_ATH79_MACH_DIR_825_C1) += mach-dir-825-c1.o ++obj-$(CONFIG_ATH79_MACH_DIR_869_A1) += mach-dir-869-a1.o ++obj-$(CONFIG_ATH79_MACH_DLAN_HOTSPOT) += mach-dlan-hotspot.o ++obj-$(CONFIG_ATH79_MACH_DLAN_PRO_1200_AC) += mach-dlan-pro-1200-ac.o ++obj-$(CONFIG_ATH79_MACH_DLAN_PRO_500_WP) += mach-dlan-pro-500-wp.o ++obj-$(CONFIG_ATH79_MACH_DOMYWIFI_DW33D) += mach-domywifi-dw33d.o ++obj-$(CONFIG_ATH79_MACH_DR342) += mach-dr344.o ++obj-$(CONFIG_ATH79_MACH_DR344) += mach-dr344.o ++obj-$(CONFIG_ATH79_MACH_DR531) += mach-dr531.o ++obj-$(CONFIG_ATH79_MACH_DRAGINO2) += mach-dragino2.o ++obj-$(CONFIG_ATH79_MACH_E1700AC_V2) += mach-e1700ac-v2.o ++obj-$(CONFIG_ATH79_MACH_E558_V2) += mach-e558-v2.o ++obj-$(CONFIG_ATH79_MACH_E600G_V2) += mach-e600g-v2.o ++obj-$(CONFIG_ATH79_MACH_E750A_V4) += mach-e750a-v4.o ++obj-$(CONFIG_ATH79_MACH_E750G_V8) += mach-e750g-v8.o ++obj-$(CONFIG_ATH79_MACH_EAP120) += mach-eap120.o ++obj-$(CONFIG_ATH79_MACH_EAP300V2) += mach-eap300v2.o ++obj-$(CONFIG_ATH79_MACH_EAP7660D) += mach-eap7660d.o ++obj-$(CONFIG_ATH79_MACH_EL_M150) += mach-el-m150.o ++obj-$(CONFIG_ATH79_MACH_EL_MINI) += mach-el-mini.o ++obj-$(CONFIG_ATH79_MACH_ENS202EXT) += mach-ens202ext.o ++obj-$(CONFIG_ATH79_MACH_EPG5000) += mach-epg5000.o ++obj-$(CONFIG_ATH79_MACH_ESR1750) += mach-esr1750.o ++obj-$(CONFIG_ATH79_MACH_ESR900) += mach-esr900.o ++obj-$(CONFIG_ATH79_MACH_EW_BALIN) += mach-ew-balin.o ++obj-$(CONFIG_ATH79_MACH_EW_DORIN) += mach-ew-dorin.o ++obj-$(CONFIG_ATH79_MACH_F9K1115V2) += mach-f9k1115v2.o ++obj-$(CONFIG_ATH79_MACH_FRITZ300E) += mach-fritz300e.o ++obj-$(CONFIG_ATH79_MACH_FRITZ4020) += mach-fritz4020.o ++obj-$(CONFIG_ATH79_MACH_FRITZ450E) += mach-fritz450e.o ++obj-$(CONFIG_ATH79_MACH_GL_AR150) += mach-gl-ar150.o ++obj-$(CONFIG_ATH79_MACH_GL_AR300) += mach-gl-ar300.o ++obj-$(CONFIG_ATH79_MACH_GL_AR300M) += mach-gl-ar300m.o ++obj-$(CONFIG_ATH79_MACH_GL_AR750) += mach-gl-ar750.o ++obj-$(CONFIG_ATH79_MACH_GL_AR750S) += mach-gl-ar750s.o ++obj-$(CONFIG_ATH79_MACH_GL_DOMINO) += mach-gl-domino.o ++obj-$(CONFIG_ATH79_MACH_GL_INET) += mach-gl-inet.o ++obj-$(CONFIG_ATH79_MACH_GL_MIFI) += mach-gl-mifi.o ++obj-$(CONFIG_ATH79_MACH_GL_USB150) += mach-gl-usb150.o ++obj-$(CONFIG_ATH79_MACH_GS_MINIBOX_V32) += mach-gs-minibox-v32.o ++obj-$(CONFIG_ATH79_MACH_GS_OOLITE_V1) += mach-gs-oolite-v1.o ++obj-$(CONFIG_ATH79_MACH_GS_OOLITE_V5_2) += mach-gs-oolite-v5-2.o ++obj-$(CONFIG_ATH79_MACH_HIVEAP_121) += mach-hiveap-121.o ++obj-$(CONFIG_ATH79_MACH_HIWIFI_HC6361) += mach-hiwifi-hc6361.o ++obj-$(CONFIG_ATH79_MACH_HORNET_UB) += mach-hornet-ub.o ++obj-$(CONFIG_ATH79_MACH_JA76PF) += mach-ja76pf.o ++obj-$(CONFIG_ATH79_MACH_JWAP003) += mach-jwap003.o ++obj-$(CONFIG_ATH79_MACH_JWAP230) += mach-jwap230.o ++obj-$(CONFIG_ATH79_MACH_KOALA) += mach-koala.o ++obj-$(CONFIG_ATH79_MACH_LAN_TURTLE) += mach-lan-turtle.o ++obj-$(CONFIG_ATH79_MACH_LIMA) += mach-lima.o ++obj-$(CONFIG_ATH79_MACH_MC_MAC1200R) += mach-mc-mac1200r.o ++obj-$(CONFIG_ATH79_MACH_MR12) += mach-mr12.o ++obj-$(CONFIG_ATH79_MACH_MR16) += mach-mr16.o ++obj-$(CONFIG_ATH79_MACH_MR1750) += mach-mr1750.o ++obj-$(CONFIG_ATH79_MACH_MR18) += mach-mr18.o ++obj-$(CONFIG_ATH79_MACH_MR600) += mach-mr600.o ++obj-$(CONFIG_ATH79_MACH_MR900) += mach-mr900.o ++obj-$(CONFIG_ATH79_MACH_MYNET_N600) += mach-mynet-n600.o ++obj-$(CONFIG_ATH79_MACH_MYNET_N750) += mach-mynet-n750.o ++obj-$(CONFIG_ATH79_MACH_MYNET_REXT) += mach-mynet-rext.o ++obj-$(CONFIG_ATH79_MACH_MZK_W04NU) += mach-mzk-w04nu.o ++obj-$(CONFIG_ATH79_MACH_MZK_W300NH) += mach-mzk-w300nh.o ++obj-$(CONFIG_ATH79_MACH_N5Q) += mach-n5q.o ++obj-$(CONFIG_ATH79_MACH_NBG460N) += mach-nbg460n.o ++obj-$(CONFIG_ATH79_MACH_NBG6716) += mach-nbg6716.o ++obj-$(CONFIG_ATH79_MACH_RAMBUTAN) += mach-rambutan.o ++obj-$(CONFIG_ATH79_MACH_OM2P) += mach-om2p.o ++obj-$(CONFIG_ATH79_MACH_OM5P) += mach-om5p.o ++obj-$(CONFIG_ATH79_MACH_OM5P_AC) += mach-om5pac.o ++obj-$(CONFIG_ATH79_MACH_OM5P_ACv2) += mach-om5pacv2.o ++obj-$(CONFIG_ATH79_MACH_OMY_G1) += mach-omy-g1.o ++obj-$(CONFIG_ATH79_MACH_OMY_X1) += mach-omy-x1.o ++obj-$(CONFIG_ATH79_MACH_ONION_OMEGA) += mach-onion-omega.o ++obj-$(CONFIG_ATH79_MACH_PB42) += mach-pb42.o ++obj-$(CONFIG_ATH79_MACH_PB44) += mach-pb44.o ++obj-$(CONFIG_ATH79_MACH_PQI_AIR_PEN) += mach-pqi-air-pen.o ++obj-$(CONFIG_ATH79_MACH_QIHOO_C301) += mach-qihoo-c301.o ++obj-$(CONFIG_ATH79_MACH_R36A) += mach-r36a.o ++obj-$(CONFIG_ATH79_MACH_R602N) += mach-r602n.o ++obj-$(CONFIG_ATH79_MACH_R6100) += mach-r6100.o ++obj-$(CONFIG_ATH79_MACH_RB2011) += mach-rb2011.o ++obj-$(CONFIG_ATH79_MACH_RB4XX) += mach-rb4xx.o ++obj-$(CONFIG_ATH79_MACH_RB750) += mach-rb750.o ++obj-$(CONFIG_ATH79_MACH_RB91X) += mach-rb91x.o ++obj-$(CONFIG_ATH79_MACH_RB922) += mach-rb922.o ++obj-$(CONFIG_ATH79_MACH_RB941) += mach-rb941.o ++obj-$(CONFIG_ATH79_MACH_RB95X) += mach-rb95x.o ++obj-$(CONFIG_ATH79_MACH_RBSPI) += mach-rbspi.o ++obj-$(CONFIG_ATH79_MACH_RBSXTLITE) += mach-rbsxtlite.o ++obj-$(CONFIG_ATH79_MACH_RE355) += mach-re450.o ++obj-$(CONFIG_ATH79_MACH_RE450) += mach-re450.o ++obj-$(CONFIG_ATH79_MACH_RME_EG200) += mach-rme-eg200.o ++obj-$(CONFIG_ATH79_MACH_RUT9XX) += mach-rut9xx.o ++obj-$(CONFIG_ATH79_MACH_RW2458N) += mach-rw2458n.o ++obj-$(CONFIG_ATH79_MACH_SC1750) += mach-sc1750.o ++obj-$(CONFIG_ATH79_MACH_SC300M) += mach-sc300m.o ++obj-$(CONFIG_ATH79_MACH_SC450) += mach-sc450.o ++obj-$(CONFIG_ATH79_MACH_SMART_300) += mach-smart-300.o ++obj-$(CONFIG_ATH79_MACH_SOM9331) += mach-som9331.o ++obj-$(CONFIG_ATH79_MACH_SR3200) += mach-sr3200.o ++obj-$(CONFIG_ATH79_MACH_T830) += mach-t830.o ++obj-$(CONFIG_ATH79_MACH_TELLSTICK_ZNET_LITE) += mach-tellstick-znet-lite.o ++obj-$(CONFIG_ATH79_MACH_TEW_632BRP) += mach-tew-632brp.o ++obj-$(CONFIG_ATH79_MACH_TEW_673GRU) += mach-tew-673gru.o ++obj-$(CONFIG_ATH79_MACH_TEW_712BR) += mach-tew-712br.o ++obj-$(CONFIG_ATH79_MACH_TEW_732BR) += mach-tew-732br.o ++obj-$(CONFIG_ATH79_MACH_TEW_823DRU) += mach-tew-823dru.o ++obj-$(CONFIG_ATH79_MACH_TL_MR11U) += mach-tl-mr11u.o ++obj-$(CONFIG_ATH79_MACH_TL_MR13U) += mach-tl-mr13u.o ++obj-$(CONFIG_ATH79_MACH_TL_MR3020) += mach-tl-mr3020.o ++obj-$(CONFIG_ATH79_MACH_TL_MR3X20) += mach-tl-mr3x20.o ++obj-$(CONFIG_ATH79_MACH_TL_MR6400) += mach-tl-mr6400.o ++obj-$(CONFIG_ATH79_MACH_TL_WA701ND_V2) += mach-tl-wa701nd-v2.o ++obj-$(CONFIG_ATH79_MACH_TL_WA7210N_V2) += mach-tl-wa7210n-v2.o ++obj-$(CONFIG_ATH79_MACH_TL_WA801ND_V3) += mach-tl-wa801nd-v3.o ++obj-$(CONFIG_ATH79_MACH_TL_WA830RE_V2) += mach-tl-wa830re-v2.o ++obj-$(CONFIG_ATH79_MACH_TL_WA850RE_V2) += mach-tl-wax50re.o ++obj-$(CONFIG_ATH79_MACH_TL_WA855RE_V1) += mach-tl-wax50re.o ++obj-$(CONFIG_ATH79_MACH_TL_WA901ND) += mach-tl-wa901nd.o ++obj-$(CONFIG_ATH79_MACH_TL_WA901ND_V2) += mach-tl-wa901nd-v2.o ++obj-$(CONFIG_ATH79_MACH_TL_WA901ND_V4) += mach-tl-wa901nd-v4.o ++obj-$(CONFIG_ATH79_MACH_TL_WAX50RE) += mach-tl-wax50re.o ++obj-$(CONFIG_ATH79_MACH_TL_WDR3320_V2) += mach-tl-wdr3320-v2.o ++obj-$(CONFIG_ATH79_MACH_TL_WDR3500) += mach-tl-wdr3500.o ++obj-$(CONFIG_ATH79_MACH_TL_WDR4300) += mach-tl-wdr4300.o ++obj-$(CONFIG_ATH79_MACH_TL_WDR6500_V2) += mach-tl-wdr6500-v2.o ++obj-$(CONFIG_ATH79_MACH_TL_WPA8630) += mach-tl-wpa8630.o ++obj-$(CONFIG_ATH79_MACH_TL_WR1041N_V2) += mach-tl-wr1041n-v2.o ++obj-$(CONFIG_ATH79_MACH_TL_WR1043ND) += mach-tl-wr1043nd.o ++obj-$(CONFIG_ATH79_MACH_TL_WR1043ND_V2) += mach-tl-wr1043nd-v2.o ++obj-$(CONFIG_ATH79_MACH_TL_WR1043ND_V4) += mach-tl-wr1043nd-v4.o ++obj-$(CONFIG_ATH79_MACH_TL_WR2543N) += mach-tl-wr2543n.o ++obj-$(CONFIG_ATH79_MACH_TL_WR703N) += mach-tl-wr703n.o ++obj-$(CONFIG_ATH79_MACH_TL_WR720N_V3) += mach-tl-wr720n-v3.o ++obj-$(CONFIG_ATH79_MACH_TL_WR741ND) += mach-tl-wr741nd.o ++obj-$(CONFIG_ATH79_MACH_TL_WR741ND_V4) += mach-tl-wr741nd-v4.o ++obj-$(CONFIG_ATH79_MACH_TL_WR802N_V1) += mach-tl-wr802n.o ++obj-$(CONFIG_ATH79_MACH_TL_WR802N_V2) += mach-tl-wr802n.o ++obj-$(CONFIG_ATH79_MACH_TL_WR810N) += mach-tl-wr810n.o ++obj-$(CONFIG_ATH79_MACH_TL_WR810N_V2) += mach-tl-wr810n.o ++obj-$(CONFIG_ATH79_MACH_TL_WR840N_V2) += mach-tl-wr841n-v9.o ++obj-$(CONFIG_ATH79_MACH_TL_WR841N_V1) += mach-tl-wr841n.o ++obj-$(CONFIG_ATH79_MACH_TL_WR841N_V8) += mach-tl-wr841n-v8.o ++obj-$(CONFIG_ATH79_MACH_TL_WR841N_V9) += mach-tl-wr841n-v9.o ++obj-$(CONFIG_ATH79_MACH_TL_WR902AC_V1) += mach-tl-wr902ac-v1.o ++obj-$(CONFIG_ATH79_MACH_TL_WR941ND) += mach-tl-wr941nd.o ++obj-$(CONFIG_ATH79_MACH_TL_WR941ND_V6) += mach-tl-wr941nd-v6.o ++obj-$(CONFIG_ATH79_MACH_TL_WR940N_V4) += mach-tl-wr940n-v4.o ++obj-$(CONFIG_ATH79_MACH_TL_WR942N_V1) += mach-tl-wr942n-v1.o ++obj-$(CONFIG_ATH79_MACH_TS_D084) += mach-ts-d084.o ++obj-$(CONFIG_ATH79_MACH_TUBE2H) += mach-tube2h.o ++obj-$(CONFIG_ATH79_MACH_UBNT) += mach-ubnt.o ++obj-$(CONFIG_ATH79_MACH_UBNT_UNIFIAC) += mach-ubnt-unifiac.o ++obj-$(CONFIG_ATH79_MACH_UBNT_XM) += mach-ubnt-xm.o ++obj-$(CONFIG_ATH79_MACH_WAM250) += mach-wam250.o ++obj-$(CONFIG_ATH79_MACH_WEIO) += mach-weio.o ++obj-$(CONFIG_ATH79_MACH_WHR_HP_G300N) += mach-whr-hp-g300n.o ++obj-$(CONFIG_ATH79_MACH_WIFI_PINEAPPLE_NANO) += mach-wifi-pineapple-nano.o ++obj-$(CONFIG_ATH79_MACH_WLAE_AG300N) += mach-wlae-ag300n.o ++obj-$(CONFIG_ATH79_MACH_WLR8100) += mach-wlr8100.o ++obj-$(CONFIG_ATH79_MACH_WNDAP360) += mach-wndap360.o ++obj-$(CONFIG_ATH79_MACH_WNDR3700) += mach-wndr3700.o ++obj-$(CONFIG_ATH79_MACH_WNDR4300) += mach-wndr4300.o ++obj-$(CONFIG_ATH79_MACH_WNR2000) += mach-wnr2000.o ++obj-$(CONFIG_ATH79_MACH_WNR2000_V3) += mach-wnr2000-v3.o ++obj-$(CONFIG_ATH79_MACH_WNR2000_V4) += mach-wnr2000-v4.o ++obj-$(CONFIG_ATH79_MACH_WNR2200) += mach-wnr2200.o ++obj-$(CONFIG_ATH79_MACH_WP543) += mach-wp543.o ++obj-$(CONFIG_ATH79_MACH_WPE72) += mach-wpe72.o ++obj-$(CONFIG_ATH79_MACH_WPJ342) += mach-wpj342.o ++obj-$(CONFIG_ATH79_MACH_WPJ344) += mach-wpj344.o ++obj-$(CONFIG_ATH79_MACH_WPJ531) += mach-wpj531.o ++obj-$(CONFIG_ATH79_MACH_WPJ558) += mach-wpj558.o ++obj-$(CONFIG_ATH79_MACH_WPJ563) += mach-wpj563.o ++obj-$(CONFIG_ATH79_MACH_WRT160NL) += mach-wrt160nl.o ++obj-$(CONFIG_ATH79_MACH_WRT400N) += mach-wrt400n.o ++obj-$(CONFIG_ATH79_MACH_WRTNODE2Q) += mach-wrtnode2q.o ++obj-$(CONFIG_ATH79_MACH_WZR_450HP2) += mach-wzr-450hp2.o ++obj-$(CONFIG_ATH79_MACH_WZR_HP_AG300H) += mach-wzr-hp-ag300h.o ++obj-$(CONFIG_ATH79_MACH_WZR_HP_G300NH) += mach-wzr-hp-g300nh.o ++obj-$(CONFIG_ATH79_MACH_WZR_HP_G300NH2) += mach-wzr-hp-g300nh2.o ++obj-$(CONFIG_ATH79_MACH_WZR_HP_G450H) += mach-wzr-hp-g450h.o ++obj-$(CONFIG_ATH79_MACH_XD3200) += mach-sr3200.o ++obj-$(CONFIG_ATH79_MACH_Z1) += mach-z1.o ++obj-$(CONFIG_ATH79_MACH_ZBT_WE1526) += mach-zbt-we1526.o ++obj-$(CONFIG_ATH79_MACH_ZCN_1523H) += mach-zcn-1523h.o +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c +new file mode 100644 +index 0000000000..483aed78ed +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c +@@ -0,0 +1,173 @@ ++/* ++ * Atheros AP9X reference board PCI initialization ++ * ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "dev-ap9x-pci.h" ++#include "pci-ath9k-fixup.h" ++#include "pci.h" ++ ++static struct ath9k_platform_data ap9x_wmac0_data = { ++ .led_pin = -1, ++}; ++static struct ath9k_platform_data ap9x_wmac1_data = { ++ .led_pin = -1, ++}; ++static char ap9x_wmac0_mac[6]; ++static char ap9x_wmac1_mac[6]; ++ ++__init void ap9x_pci_setup_wmac_led_pin(unsigned wmac, int pin) ++{ ++ switch (wmac) { ++ case 0: ++ ap9x_wmac0_data.led_pin = pin; ++ break; ++ case 1: ++ ap9x_wmac1_data.led_pin = pin; ++ break; ++ } ++} ++ ++__init struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac) ++{ ++ switch (wmac) { ++ case 0: ++ return &ap9x_wmac0_data; ++ ++ case 1: ++ return &ap9x_wmac1_data; ++ } ++ ++ return NULL; ++} ++ ++__init void ap9x_pci_setup_wmac_gpio(unsigned wmac, u32 mask, u32 val) ++{ ++ switch (wmac) { ++ case 0: ++ ap9x_wmac0_data.gpio_mask = mask; ++ ap9x_wmac0_data.gpio_val = val; ++ break; ++ case 1: ++ ap9x_wmac1_data.gpio_mask = mask; ++ ap9x_wmac1_data.gpio_val = val; ++ break; ++ } ++} ++ ++__init void ap9x_pci_setup_wmac_leds(unsigned wmac, struct gpio_led *leds, ++ int num_leds) ++{ ++ switch (wmac) { ++ case 0: ++ ap9x_wmac0_data.leds = leds; ++ ap9x_wmac0_data.num_leds = num_leds; ++ break; ++ case 1: ++ ap9x_wmac1_data.leds = leds; ++ ap9x_wmac1_data.num_leds = num_leds; ++ break; ++ } ++} ++ ++__init void ap9x_pci_setup_wmac_btns(unsigned wmac, ++ struct gpio_keys_button *btns, ++ unsigned num_btns, unsigned poll_interval) ++{ ++ struct ath9k_platform_data *ap9x_wmac_data; ++ ++ if (!(ap9x_wmac_data = ap9x_pci_get_wmac_data(wmac))) ++ return; ++ ++ ap9x_wmac_data->btns = btns; ++ ap9x_wmac_data->num_btns = num_btns; ++ ap9x_wmac_data->btn_poll_interval = poll_interval; ++} ++ ++static int ap91_pci_plat_dev_init(struct pci_dev *dev) ++{ ++ switch (PCI_SLOT(dev->devfn)) { ++ case 0: ++ dev->dev.platform_data = &ap9x_wmac0_data; ++ break; ++ } ++ ++ return 0; ++} ++ ++__init void ap91_pci_init(u8 *cal_data, u8 *mac_addr) ++{ ++ if (cal_data) ++ memcpy(ap9x_wmac0_data.eeprom_data, cal_data, ++ sizeof(ap9x_wmac0_data.eeprom_data)); ++ ++ if (mac_addr) { ++ memcpy(ap9x_wmac0_mac, mac_addr, sizeof(ap9x_wmac0_mac)); ++ ap9x_wmac0_data.macaddr = ap9x_wmac0_mac; ++ } ++ ++ ath79_pci_set_plat_dev_init(ap91_pci_plat_dev_init); ++ ath79_register_pci(); ++ ++ pci_enable_ath9k_fixup(0, ap9x_wmac0_data.eeprom_data); ++} ++ ++__init void ap91_pci_init_simple(void) ++{ ++ ap91_pci_init(NULL, NULL); ++ ap9x_wmac0_data.eeprom_name = "pci_wmac0.eeprom"; ++} ++ ++static int ap94_pci_plat_dev_init(struct pci_dev *dev) ++{ ++ switch (PCI_SLOT(dev->devfn)) { ++ case 17: ++ dev->dev.platform_data = &ap9x_wmac0_data; ++ break; ++ ++ case 18: ++ dev->dev.platform_data = &ap9x_wmac1_data; ++ break; ++ } ++ ++ return 0; ++} ++ ++__init void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, ++ u8 *cal_data1, u8 *mac_addr1) ++{ ++ if (cal_data0) ++ memcpy(ap9x_wmac0_data.eeprom_data, cal_data0, ++ sizeof(ap9x_wmac0_data.eeprom_data)); ++ ++ if (cal_data1) ++ memcpy(ap9x_wmac1_data.eeprom_data, cal_data1, ++ sizeof(ap9x_wmac1_data.eeprom_data)); ++ ++ if (mac_addr0) { ++ memcpy(ap9x_wmac0_mac, mac_addr0, sizeof(ap9x_wmac0_mac)); ++ ap9x_wmac0_data.macaddr = ap9x_wmac0_mac; ++ } ++ ++ if (mac_addr1) { ++ memcpy(ap9x_wmac1_mac, mac_addr1, sizeof(ap9x_wmac1_mac)); ++ ap9x_wmac1_data.macaddr = ap9x_wmac1_mac; ++ } ++ ++ ath79_pci_set_plat_dev_init(ap94_pci_plat_dev_init); ++ ath79_register_pci(); ++ ++ pci_enable_ath9k_fixup(17, ap9x_wmac0_data.eeprom_data); ++ pci_enable_ath9k_fixup(18, ap9x_wmac1_data.eeprom_data); ++} +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h +new file mode 100644 +index 0000000000..d2a045fc1c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h +@@ -0,0 +1,55 @@ ++/* ++ * Atheros AP9X reference board PCI initialization ++ * ++ * Copyright (C) 2009-2012 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 _ATH79_DEV_AP9X_PCI_H ++#define _ATH79_DEV_AP9X_PCI_H ++ ++struct gpio_led; ++struct gpio_keys_button; ++struct ath9k_platform_data; ++ ++#if defined(CONFIG_ATH79_DEV_AP9X_PCI) ++void ap9x_pci_setup_wmac_led_pin(unsigned wmac, int pin); ++void ap9x_pci_setup_wmac_gpio(unsigned wmac, u32 mask, u32 val); ++void ap9x_pci_setup_wmac_leds(unsigned wmac, struct gpio_led *leds, ++ int num_leds); ++void ap9x_pci_setup_wmac_btns(unsigned wmac, struct gpio_keys_button *btns, ++ unsigned num_btns, unsigned poll_interval); ++struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac); ++ ++void ap91_pci_init(u8 *cal_data, u8 *mac_addr); ++void ap91_pci_init_simple(void); ++void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, ++ u8 *cal_data1, u8 *mac_addr1); ++ ++#else ++static inline void ap9x_pci_setup_wmac_led_pin(unsigned wmac, int pin) {} ++static inline void ap9x_pci_setup_wmac_gpio(unsigned wmac, ++ u32 mask, u32 val) {} ++static inline void ap9x_pci_setup_wmac_leds(unsigned wmac, ++ struct gpio_led *leds, ++ int num_leds) {} ++static inline void ap9x_pci_setup_wmac_btns(unsigned wmac, ++ struct gpio_keys_button *btns, ++ unsigned num_btns, ++ unsigned poll_interval) {} ++static inline struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac) ++{ ++ return NULL; ++} ++ ++static inline void ap91_pci_init(u8 *cal_data, u8 *mac_addr) {} ++static inline void ap91_pci_init_simple(void) {} ++static inline void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, ++ u8 *cal_data1, u8 *mac_addr1) {} ++#endif ++ ++#endif /* _ATH79_DEV_AP9X_PCI_H */ ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-dsa.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-dsa.c +new file mode 100644 +index 0000000000..4ade218f7e +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-dsa.c +@@ -0,0 +1,36 @@ ++/* ++ * Atheros AR71xx DSA switch device support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-dsa.h" ++ ++static struct platform_device ar71xx_dsa_switch_device = { ++ .name = "dsa", ++ .id = 0, ++}; ++ ++void __init ath79_register_dsa(struct device *netdev, ++ struct device *miidev, ++ struct dsa_platform_data *d) ++{ ++ int i; ++ ++ d->netdev = netdev; ++ for (i = 0; i < d->nr_chips; i++) ++ d->chip[i].host_dev = miidev; ++ ++ ar71xx_dsa_switch_device.dev.platform_data = d; ++ platform_device_register(&ar71xx_dsa_switch_device); ++} +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-dsa.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-dsa.h +new file mode 100644 +index 0000000000..3730202e8d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-dsa.h +@@ -0,0 +1,21 @@ ++/* ++ * Atheros AR71xx DSA switch device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 _ATH79_DEV_DSA_H ++#define _ATH79_DEV_DSA_H ++ ++#include ++ ++void ath79_register_dsa(struct device *netdev, ++ struct device *miidev, ++ struct dsa_platform_data *d); ++ ++#endif /* _ATH79_DEV_DSA_H */ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c +new file mode 100644 +index 0000000000..1e230bce61 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c +@@ -0,0 +1,1262 @@ ++/* ++ * Atheros AR71xx SoC platform devices ++ * ++ * Copyright (C) 2010-2011 Jaiganesh Narayanan ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * Parts of this file are based on Atheros 2.6.15 BSP ++ * Parts of this file are based on Atheros 2.6.31 BSP ++ * ++ * 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 ++#include ++ ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++ ++unsigned char ath79_mac_base[ETH_ALEN] __initdata; ++ ++static struct resource ath79_mdio0_resources[] = { ++ { ++ .name = "mdio_base", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_GE0_BASE, ++ .end = AR71XX_GE0_BASE + 0x200 - 1, ++ } ++}; ++ ++struct ag71xx_mdio_platform_data ath79_mdio0_data; ++ ++struct platform_device ath79_mdio0_device = { ++ .name = "ag71xx-mdio", ++ .id = 0, ++ .resource = ath79_mdio0_resources, ++ .num_resources = ARRAY_SIZE(ath79_mdio0_resources), ++ .dev = { ++ .platform_data = &ath79_mdio0_data, ++ }, ++}; ++ ++static struct resource ath79_mdio1_resources[] = { ++ { ++ .name = "mdio_base", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_GE1_BASE, ++ .end = AR71XX_GE1_BASE + 0x200 - 1, ++ } ++}; ++ ++struct ag71xx_mdio_platform_data ath79_mdio1_data; ++ ++struct platform_device ath79_mdio1_device = { ++ .name = "ag71xx-mdio", ++ .id = 1, ++ .resource = ath79_mdio1_resources, ++ .num_resources = ARRAY_SIZE(ath79_mdio1_resources), ++ .dev = { ++ .platform_data = &ath79_mdio1_data, ++ }, ++}; ++ ++static void ath79_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ ++ t = __raw_readl(base + cfg_reg); ++ t &= ~(3 << shift); ++ t |= (2 << shift); ++ __raw_writel(t, base + cfg_reg); ++ udelay(100); ++ ++ __raw_writel(pll_val, base + pll_reg); ++ ++ t |= (3 << shift); ++ __raw_writel(t, base + cfg_reg); ++ udelay(100); ++ ++ t &= ~(3 << shift); ++ __raw_writel(t, base + cfg_reg); ++ udelay(100); ++ ++ printk(KERN_DEBUG "ar71xx: pll_reg %#x: %#x\n", ++ (unsigned int)(base + pll_reg), __raw_readl(base + pll_reg)); ++ ++ iounmap(base); ++} ++ ++static void __init ath79_mii_ctrl_set_if(unsigned int reg, ++ unsigned int mii_if) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(AR71XX_MII_BASE, AR71XX_MII_SIZE); ++ ++ t = __raw_readl(base + reg); ++ t &= ~(AR71XX_MII_CTRL_IF_MASK); ++ t |= (mii_if & AR71XX_MII_CTRL_IF_MASK); ++ __raw_writel(t, base + reg); ++ ++ iounmap(base); ++} ++ ++static void ath79_mii_ctrl_set_speed(unsigned int reg, unsigned int speed) ++{ ++ void __iomem *base; ++ unsigned int mii_speed; ++ u32 t; ++ ++ switch (speed) { ++ case SPEED_10: ++ mii_speed = AR71XX_MII_CTRL_SPEED_10; ++ break; ++ case SPEED_100: ++ mii_speed = AR71XX_MII_CTRL_SPEED_100; ++ break; ++ case SPEED_1000: ++ mii_speed = AR71XX_MII_CTRL_SPEED_1000; ++ break; ++ default: ++ BUG(); ++ } ++ ++ base = ioremap(AR71XX_MII_BASE, AR71XX_MII_SIZE); ++ ++ t = __raw_readl(base + reg); ++ t &= ~(AR71XX_MII_CTRL_SPEED_MASK << AR71XX_MII_CTRL_SPEED_SHIFT); ++ t |= mii_speed << AR71XX_MII_CTRL_SPEED_SHIFT; ++ __raw_writel(t, base + reg); ++ ++ iounmap(base); ++} ++ ++static unsigned long ar934x_get_mdio_ref_clock(void) ++{ ++ void __iomem *base; ++ unsigned long ret; ++ u32 t; ++ ++ base = ioremap(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ ++ ret = 0; ++ t = __raw_readl(base + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG); ++ if (t & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) { ++ ret = 100 * 1000 * 1000; ++ } else { ++ struct clk *clk; ++ ++ clk = clk_get(NULL, "ref"); ++ if (!IS_ERR(clk)) ++ ret = clk_get_rate(clk); ++ } ++ ++ iounmap(base); ++ ++ return ret; ++} ++ ++void __init ath79_register_mdio(unsigned int id, u32 phy_mask) ++{ ++ struct platform_device *mdio_dev; ++ struct ag71xx_mdio_platform_data *mdio_data; ++ unsigned int max_id; ++ ++ if (ath79_soc == ATH79_SOC_AR9341 || ++ ath79_soc == ATH79_SOC_AR9342 || ++ ath79_soc == ATH79_SOC_AR9344 || ++ ath79_soc == ATH79_SOC_QCA9556 || ++ ath79_soc == ATH79_SOC_QCA9558 || ++ ath79_soc == ATH79_SOC_QCA956X) ++ max_id = 1; ++ else ++ max_id = 0; ++ ++ if (id > max_id) { ++ printk(KERN_ERR "ar71xx: invalid MDIO id %u\n", id); ++ return; ++ } ++ ++ switch (ath79_soc) { ++ case ATH79_SOC_AR7241: ++ case ATH79_SOC_AR9330: ++ case ATH79_SOC_AR9331: ++ case ATH79_SOC_QCA9533: ++ case ATH79_SOC_TP9343: ++ mdio_dev = &ath79_mdio1_device; ++ mdio_data = &ath79_mdio1_data; ++ break; ++ ++ case ATH79_SOC_AR9341: ++ case ATH79_SOC_AR9342: ++ case ATH79_SOC_AR9344: ++ case ATH79_SOC_QCA9556: ++ case ATH79_SOC_QCA9558: ++ case ATH79_SOC_QCA956X: ++ if (id == 0) { ++ mdio_dev = &ath79_mdio0_device; ++ mdio_data = &ath79_mdio0_data; ++ } else { ++ mdio_dev = &ath79_mdio1_device; ++ mdio_data = &ath79_mdio1_data; ++ } ++ break; ++ ++ case ATH79_SOC_AR7242: ++ ath79_set_pll(AR71XX_PLL_REG_SEC_CONFIG, ++ AR7242_PLL_REG_ETH0_INT_CLOCK, 0x62000000, ++ AR71XX_ETH0_PLL_SHIFT); ++ /* fall through */ ++ default: ++ mdio_dev = &ath79_mdio0_device; ++ mdio_data = &ath79_mdio0_data; ++ break; ++ } ++ ++ mdio_data->phy_mask = phy_mask; ++ ++ switch (ath79_soc) { ++ case ATH79_SOC_AR7240: ++ mdio_data->is_ar7240 = 1; ++ /* fall through */ ++ case ATH79_SOC_AR7241: ++ mdio_data->builtin_switch = 1; ++ break; ++ ++ case ATH79_SOC_AR9330: ++ mdio_data->is_ar9330 = 1; ++ /* fall through */ ++ case ATH79_SOC_AR9331: ++ mdio_data->builtin_switch = 1; ++ break; ++ ++ case ATH79_SOC_AR9341: ++ case ATH79_SOC_AR9342: ++ case ATH79_SOC_AR9344: ++ if (id == 1) { ++ mdio_data->builtin_switch = 1; ++ mdio_data->ref_clock = ar934x_get_mdio_ref_clock(); ++ mdio_data->mdio_clock = 6250000; ++ } ++ mdio_data->is_ar934x = 1; ++ break; ++ ++ case ATH79_SOC_QCA9533: ++ case ATH79_SOC_TP9343: ++ mdio_data->builtin_switch = 1; ++ break; ++ ++ case ATH79_SOC_QCA9556: ++ case ATH79_SOC_QCA9558: ++ mdio_data->is_ar934x = 1; ++ break; ++ ++ case ATH79_SOC_QCA956X: ++ if (id == 1) ++ mdio_data->builtin_switch = 1; ++ mdio_data->is_ar934x = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ platform_device_register(mdio_dev); ++} ++ ++struct ath79_eth_pll_data ath79_eth0_pll_data; ++struct ath79_eth_pll_data ath79_eth1_pll_data; ++ ++static u32 ath79_get_eth_pll(unsigned int mac, int speed) ++{ ++ struct ath79_eth_pll_data *pll_data; ++ u32 pll_val; ++ ++ switch (mac) { ++ case 0: ++ pll_data = &ath79_eth0_pll_data; ++ break; ++ case 1: ++ pll_data = &ath79_eth1_pll_data; ++ break; ++ default: ++ BUG(); ++ } ++ ++ switch (speed) { ++ case SPEED_10: ++ pll_val = pll_data->pll_10; ++ break; ++ case SPEED_100: ++ pll_val = pll_data->pll_100; ++ break; ++ case SPEED_1000: ++ pll_val = pll_data->pll_1000; ++ break; ++ default: ++ BUG(); ++ } ++ ++ return pll_val; ++} ++ ++static void ath79_set_speed_ge0(int speed) ++{ ++ u32 val = ath79_get_eth_pll(0, speed); ++ ++ ath79_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH0_INT_CLOCK, ++ val, AR71XX_ETH0_PLL_SHIFT); ++ ath79_mii_ctrl_set_speed(AR71XX_MII_REG_MII0_CTRL, speed); ++} ++ ++static void ath79_set_speed_ge1(int speed) ++{ ++ u32 val = ath79_get_eth_pll(1, speed); ++ ++ ath79_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH1_INT_CLOCK, ++ val, AR71XX_ETH1_PLL_SHIFT); ++ ath79_mii_ctrl_set_speed(AR71XX_MII_REG_MII1_CTRL, speed); ++} ++ ++static void ar7242_set_speed_ge0(int speed) ++{ ++ u32 val = ath79_get_eth_pll(0, speed); ++ void __iomem *base; ++ ++ base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ __raw_writel(val, base + AR7242_PLL_REG_ETH0_INT_CLOCK); ++ iounmap(base); ++} ++ ++static void ar91xx_set_speed_ge0(int speed) ++{ ++ u32 val = ath79_get_eth_pll(0, speed); ++ ++ ath79_set_pll(AR913X_PLL_REG_ETH_CONFIG, AR913X_PLL_REG_ETH0_INT_CLOCK, ++ val, AR913X_ETH0_PLL_SHIFT); ++ ath79_mii_ctrl_set_speed(AR71XX_MII_REG_MII0_CTRL, speed); ++} ++ ++static void ar91xx_set_speed_ge1(int speed) ++{ ++ u32 val = ath79_get_eth_pll(1, speed); ++ ++ ath79_set_pll(AR913X_PLL_REG_ETH_CONFIG, AR913X_PLL_REG_ETH1_INT_CLOCK, ++ val, AR913X_ETH1_PLL_SHIFT); ++ ath79_mii_ctrl_set_speed(AR71XX_MII_REG_MII1_CTRL, speed); ++} ++ ++static void ar934x_set_speed_ge0(int speed) ++{ ++ void __iomem *base; ++ u32 val = ath79_get_eth_pll(0, speed); ++ ++ base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ __raw_writel(val, base + AR934X_PLL_ETH_XMII_CONTROL_REG); ++ iounmap(base); ++} ++ ++static void qca955x_set_speed_xmii(int speed) ++{ ++ void __iomem *base; ++ u32 val = ath79_get_eth_pll(0, speed); ++ ++ base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ __raw_writel(val, base + QCA955X_PLL_ETH_XMII_CONTROL_REG); ++ iounmap(base); ++} ++ ++static void qca955x_set_speed_sgmii(int id, int speed) ++{ ++ void __iomem *base; ++ u32 val = ath79_get_eth_pll(id, speed); ++ ++ base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ __raw_writel(val, base + QCA955X_PLL_ETH_SGMII_CONTROL_REG); ++ iounmap(base); ++} ++ ++static void qca9556_set_speed_sgmii(int speed) ++{ ++ qca955x_set_speed_sgmii(0, speed); ++} ++ ++static void qca9558_set_speed_sgmii(int speed) ++{ ++ qca955x_set_speed_sgmii(1, speed); ++} ++ ++static void qca956x_set_speed_sgmii(int speed) ++{ ++ void __iomem *base; ++ u32 val = ath79_get_eth_pll(0, speed); ++ ++ base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ __raw_writel(val, base + QCA955X_PLL_ETH_SGMII_CONTROL_REG); ++ iounmap(base); ++} ++ ++static void ath79_set_speed_dummy(int speed) ++{ ++} ++ ++static void ath79_ddr_flush_ge0(void) ++{ ++ ath79_ddr_wb_flush(0); ++} ++ ++static void ath79_ddr_flush_ge1(void) ++{ ++ ath79_ddr_wb_flush(1); ++} ++ ++static struct resource ath79_eth0_resources[] = { ++ { ++ .name = "mac_base", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_GE0_BASE, ++ .end = AR71XX_GE0_BASE + 0x200 - 1, ++ }, { ++ .name = "mac_irq", ++ .flags = IORESOURCE_IRQ, ++ .start = ATH79_CPU_IRQ(4), ++ .end = ATH79_CPU_IRQ(4), ++ }, ++}; ++ ++struct ag71xx_platform_data ath79_eth0_data = { ++ .reset_bit = AR71XX_RESET_GE0_MAC, ++}; ++ ++struct platform_device ath79_eth0_device = { ++ .name = "ag71xx", ++ .id = 0, ++ .resource = ath79_eth0_resources, ++ .num_resources = ARRAY_SIZE(ath79_eth0_resources), ++ .dev = { ++ .platform_data = &ath79_eth0_data, ++ }, ++}; ++ ++static struct resource ath79_eth1_resources[] = { ++ { ++ .name = "mac_base", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_GE1_BASE, ++ .end = AR71XX_GE1_BASE + 0x200 - 1, ++ }, { ++ .name = "mac_irq", ++ .flags = IORESOURCE_IRQ, ++ .start = ATH79_CPU_IRQ(5), ++ .end = ATH79_CPU_IRQ(5), ++ }, ++}; ++ ++struct ag71xx_platform_data ath79_eth1_data = { ++ .reset_bit = AR71XX_RESET_GE1_MAC, ++}; ++ ++struct platform_device ath79_eth1_device = { ++ .name = "ag71xx", ++ .id = 1, ++ .resource = ath79_eth1_resources, ++ .num_resources = ARRAY_SIZE(ath79_eth1_resources), ++ .dev = { ++ .platform_data = &ath79_eth1_data, ++ }, ++}; ++ ++struct ag71xx_switch_platform_data ath79_switch_data; ++ ++#define AR71XX_PLL_VAL_1000 0x00110000 ++#define AR71XX_PLL_VAL_100 0x00001099 ++#define AR71XX_PLL_VAL_10 0x00991099 ++ ++#define AR724X_PLL_VAL_1000 0x00110000 ++#define AR724X_PLL_VAL_100 0x00001099 ++#define AR724X_PLL_VAL_10 0x00991099 ++ ++#define AR7242_PLL_VAL_1000 0x16000000 ++#define AR7242_PLL_VAL_100 0x00000101 ++#define AR7242_PLL_VAL_10 0x00001616 ++ ++#define AR913X_PLL_VAL_1000 0x1a000000 ++#define AR913X_PLL_VAL_100 0x13000a44 ++#define AR913X_PLL_VAL_10 0x00441099 ++ ++#define AR933X_PLL_VAL_1000 0x00110000 ++#define AR933X_PLL_VAL_100 0x00001099 ++#define AR933X_PLL_VAL_10 0x00991099 ++ ++#define AR934X_PLL_VAL_1000 0x16000000 ++#define AR934X_PLL_VAL_100 0x00000101 ++#define AR934X_PLL_VAL_10 0x00001616 ++ ++#define QCA956X_PLL_VAL_1000 0x03000000 ++#define QCA956X_PLL_VAL_100 0x00000101 ++#define QCA956X_PLL_VAL_10 0x00001919 ++ ++static void __init ath79_init_eth_pll_data(unsigned int id) ++{ ++ struct ath79_eth_pll_data *pll_data; ++ u32 pll_10, pll_100, pll_1000; ++ ++ switch (id) { ++ case 0: ++ pll_data = &ath79_eth0_pll_data; ++ break; ++ case 1: ++ pll_data = &ath79_eth1_pll_data; ++ break; ++ default: ++ BUG(); ++ } ++ ++ switch (ath79_soc) { ++ case ATH79_SOC_AR7130: ++ case ATH79_SOC_AR7141: ++ case ATH79_SOC_AR7161: ++ pll_10 = AR71XX_PLL_VAL_10; ++ pll_100 = AR71XX_PLL_VAL_100; ++ pll_1000 = AR71XX_PLL_VAL_1000; ++ break; ++ ++ case ATH79_SOC_AR7240: ++ case ATH79_SOC_AR7241: ++ pll_10 = AR724X_PLL_VAL_10; ++ pll_100 = AR724X_PLL_VAL_100; ++ pll_1000 = AR724X_PLL_VAL_1000; ++ break; ++ ++ case ATH79_SOC_AR7242: ++ pll_10 = AR7242_PLL_VAL_10; ++ pll_100 = AR7242_PLL_VAL_100; ++ pll_1000 = AR7242_PLL_VAL_1000; ++ break; ++ ++ case ATH79_SOC_AR9130: ++ case ATH79_SOC_AR9132: ++ pll_10 = AR913X_PLL_VAL_10; ++ pll_100 = AR913X_PLL_VAL_100; ++ pll_1000 = AR913X_PLL_VAL_1000; ++ break; ++ ++ case ATH79_SOC_AR9330: ++ case ATH79_SOC_AR9331: ++ pll_10 = AR933X_PLL_VAL_10; ++ pll_100 = AR933X_PLL_VAL_100; ++ pll_1000 = AR933X_PLL_VAL_1000; ++ break; ++ ++ case ATH79_SOC_AR9341: ++ case ATH79_SOC_AR9342: ++ case ATH79_SOC_AR9344: ++ case ATH79_SOC_QCA9533: ++ case ATH79_SOC_QCA9556: ++ case ATH79_SOC_QCA9558: ++ case ATH79_SOC_TP9343: ++ pll_10 = AR934X_PLL_VAL_10; ++ pll_100 = AR934X_PLL_VAL_100; ++ pll_1000 = AR934X_PLL_VAL_1000; ++ break; ++ ++ case ATH79_SOC_QCA956X: ++ pll_10 = QCA956X_PLL_VAL_10; ++ pll_100 = QCA956X_PLL_VAL_100; ++ pll_1000 = QCA956X_PLL_VAL_1000; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ if (!pll_data->pll_10) ++ pll_data->pll_10 = pll_10; ++ ++ if (!pll_data->pll_100) ++ pll_data->pll_100 = pll_100; ++ ++ if (!pll_data->pll_1000) ++ pll_data->pll_1000 = pll_1000; ++} ++ ++static int __init ath79_setup_phy_if_mode(unsigned int id, ++ struct ag71xx_platform_data *pdata) ++{ ++ unsigned int mii_if; ++ ++ switch (id) { ++ case 0: ++ switch (ath79_soc) { ++ case ATH79_SOC_AR7130: ++ case ATH79_SOC_AR7141: ++ case ATH79_SOC_AR7161: ++ case ATH79_SOC_AR9130: ++ case ATH79_SOC_AR9132: ++ switch (pdata->phy_if_mode) { ++ case PHY_INTERFACE_MODE_MII: ++ mii_if = AR71XX_MII0_CTRL_IF_MII; ++ break; ++ case PHY_INTERFACE_MODE_GMII: ++ mii_if = AR71XX_MII0_CTRL_IF_GMII; ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ mii_if = AR71XX_MII0_CTRL_IF_RGMII; ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ mii_if = AR71XX_MII0_CTRL_IF_RMII; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ath79_mii_ctrl_set_if(AR71XX_MII_REG_MII0_CTRL, mii_if); ++ break; ++ ++ case ATH79_SOC_AR7240: ++ case ATH79_SOC_AR7241: ++ case ATH79_SOC_AR9330: ++ case ATH79_SOC_AR9331: ++ case ATH79_SOC_QCA9533: ++ case ATH79_SOC_TP9343: ++ pdata->phy_if_mode = PHY_INTERFACE_MODE_MII; ++ break; ++ ++ case ATH79_SOC_AR7242: ++ /* FIXME */ ++ ++ case ATH79_SOC_AR9341: ++ case ATH79_SOC_AR9342: ++ case ATH79_SOC_AR9344: ++ switch (pdata->phy_if_mode) { ++ case PHY_INTERFACE_MODE_MII: ++ case PHY_INTERFACE_MODE_GMII: ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RMII: ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ ++ case ATH79_SOC_QCA9556: ++ case ATH79_SOC_QCA9558: ++ case ATH79_SOC_QCA956X: ++ switch (pdata->phy_if_mode) { ++ case PHY_INTERFACE_MODE_MII: ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ ++ default: ++ BUG(); ++ } ++ break; ++ case 1: ++ switch (ath79_soc) { ++ case ATH79_SOC_AR7130: ++ case ATH79_SOC_AR7141: ++ case ATH79_SOC_AR7161: ++ case ATH79_SOC_AR9130: ++ case ATH79_SOC_AR9132: ++ switch (pdata->phy_if_mode) { ++ case PHY_INTERFACE_MODE_RMII: ++ mii_if = AR71XX_MII1_CTRL_IF_RMII; ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ mii_if = AR71XX_MII1_CTRL_IF_RGMII; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ath79_mii_ctrl_set_if(AR71XX_MII_REG_MII1_CTRL, mii_if); ++ break; ++ ++ case ATH79_SOC_AR7240: ++ case ATH79_SOC_AR7241: ++ case ATH79_SOC_AR9330: ++ case ATH79_SOC_AR9331: ++ case ATH79_SOC_TP9343: ++ pdata->phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ break; ++ ++ case ATH79_SOC_AR7242: ++ /* FIXME */ ++ ++ case ATH79_SOC_AR9341: ++ case ATH79_SOC_AR9342: ++ case ATH79_SOC_AR9344: ++ case ATH79_SOC_QCA9533: ++ case ATH79_SOC_QCA956X: ++ switch (pdata->phy_if_mode) { ++ case PHY_INTERFACE_MODE_MII: ++ case PHY_INTERFACE_MODE_GMII: ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ ++ case ATH79_SOC_QCA9556: ++ case ATH79_SOC_QCA9558: ++ switch (pdata->phy_if_mode) { ++ case PHY_INTERFACE_MODE_MII: ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ ++ default: ++ BUG(); ++ } ++ break; ++ } ++ ++ return 0; ++} ++ ++void __init ath79_setup_ar933x_phy4_switch(bool mac, bool mdio) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(AR933X_GMAC_BASE, AR933X_GMAC_SIZE); ++ ++ t = __raw_readl(base + AR933X_GMAC_REG_ETH_CFG); ++ t &= ~(AR933X_ETH_CFG_SW_PHY_SWAP | AR933X_ETH_CFG_SW_PHY_ADDR_SWAP); ++ if (mac) ++ t |= AR933X_ETH_CFG_SW_PHY_SWAP; ++ if (mdio) ++ t |= AR933X_ETH_CFG_SW_PHY_ADDR_SWAP; ++ __raw_writel(t, base + AR933X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++void __init ath79_setup_ar934x_eth_cfg(u32 mask) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(AR934X_GMAC_BASE, AR934X_GMAC_SIZE); ++ ++ t = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); ++ ++ t &= ~(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_MII_GMAC0 | ++ AR934X_ETH_CFG_GMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE | ++ AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ t |= mask; ++ ++ __raw_writel(t, base + AR934X_GMAC_REG_ETH_CFG); ++ /* flush write */ ++ __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++void __init ath79_setup_ar934x_eth_rx_delay(unsigned int rxd, ++ unsigned int rxdv) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ rxd &= AR934X_ETH_CFG_RXD_DELAY_MASK; ++ rxdv &= AR934X_ETH_CFG_RDV_DELAY_MASK; ++ ++ base = ioremap(AR934X_GMAC_BASE, AR934X_GMAC_SIZE); ++ ++ t = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); ++ ++ t &= ~(AR934X_ETH_CFG_RXD_DELAY_MASK << AR934X_ETH_CFG_RXD_DELAY_SHIFT | ++ AR934X_ETH_CFG_RDV_DELAY_MASK << AR934X_ETH_CFG_RDV_DELAY_SHIFT); ++ ++ t |= (rxd << AR934X_ETH_CFG_RXD_DELAY_SHIFT | ++ rxdv << AR934X_ETH_CFG_RDV_DELAY_SHIFT); ++ ++ __raw_writel(t, base + AR934X_GMAC_REG_ETH_CFG); ++ /* flush write */ ++ __raw_readl(base + AR934X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++void __init ath79_setup_qca955x_eth_cfg(u32 mask) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ ++ t = __raw_readl(base + QCA955X_GMAC_REG_ETH_CFG); ++ ++ t &= ~(QCA955X_ETH_CFG_RGMII_EN | QCA955X_ETH_CFG_GE0_SGMII); ++ ++ t |= mask; ++ ++ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++void __init ath79_setup_qca956x_eth_cfg(u32 mask) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(QCA956X_GMAC_BASE, QCA956X_GMAC_SIZE); ++ ++ t = __raw_readl(base + QCA956X_GMAC_REG_ETH_CFG); ++ ++ t &= ~(QCA956X_ETH_CFG_SW_ONLY_MODE | ++ QCA956X_ETH_CFG_SW_PHY_SWAP); ++ ++ t |= mask; ++ ++ __raw_writel(t, base + QCA956X_GMAC_REG_ETH_CFG); ++ /* flush write */ ++ __raw_readl(base + QCA956X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++static int ath79_eth_instance __initdata; ++void __init ath79_register_eth(unsigned int id) ++{ ++ struct platform_device *pdev; ++ struct ag71xx_platform_data *pdata; ++ int err; ++ ++ if (id > 1) { ++ printk(KERN_ERR "ar71xx: invalid ethernet id %d\n", id); ++ return; ++ } ++ ++ ath79_init_eth_pll_data(id); ++ ++ if (id == 0) ++ pdev = &ath79_eth0_device; ++ else ++ pdev = &ath79_eth1_device; ++ ++ pdata = pdev->dev.platform_data; ++ ++ pdata->max_frame_len = 1540; ++ pdata->desc_pktlen_mask = 0xfff; ++ ++ err = ath79_setup_phy_if_mode(id, pdata); ++ if (err) { ++ printk(KERN_ERR ++ "ar71xx: invalid PHY interface mode for GE%u\n", id); ++ return; ++ } ++ ++ if (id == 0) ++ pdata->ddr_flush = ath79_ddr_flush_ge0; ++ else ++ pdata->ddr_flush = ath79_ddr_flush_ge1; ++ ++ switch (ath79_soc) { ++ case ATH79_SOC_AR7130: ++ if (id == 0) ++ pdata->set_speed = ath79_set_speed_ge0; ++ else ++ pdata->set_speed = ath79_set_speed_ge1; ++ break; ++ ++ case ATH79_SOC_AR7141: ++ case ATH79_SOC_AR7161: ++ if (id == 0) ++ pdata->set_speed = ath79_set_speed_ge0; ++ else ++ pdata->set_speed = ath79_set_speed_ge1; ++ pdata->has_gbit = 1; ++ break; ++ ++ case ATH79_SOC_AR7242: ++ if (id == 0) { ++ pdata->reset_bit |= AR724X_RESET_GE0_MDIO | ++ AR71XX_RESET_GE0_PHY; ++ pdata->set_speed = ar7242_set_speed_ge0; ++ } else { ++ pdata->reset_bit |= AR724X_RESET_GE1_MDIO | ++ AR71XX_RESET_GE1_PHY; ++ pdata->set_speed = ath79_set_speed_dummy; ++ } ++ pdata->has_gbit = 1; ++ pdata->is_ar724x = 1; ++ break; ++ ++ case ATH79_SOC_AR7241: ++ if (id == 0) ++ pdata->reset_bit |= AR724X_RESET_GE0_MDIO; ++ else ++ pdata->reset_bit |= AR724X_RESET_GE1_MDIO; ++ /* fall through */ ++ case ATH79_SOC_AR7240: ++ if (id == 0) { ++ pdata->reset_bit |= AR71XX_RESET_GE0_PHY; ++ pdata->set_speed = ath79_set_speed_dummy; ++ ++ pdata->phy_mask = BIT(4); ++ } else { ++ pdata->reset_bit |= AR71XX_RESET_GE1_PHY; ++ pdata->set_speed = ath79_set_speed_dummy; ++ ++ pdata->speed = SPEED_1000; ++ pdata->duplex = DUPLEX_FULL; ++ pdata->switch_data = &ath79_switch_data; ++ pdata->use_flow_control = 1; ++ ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ } ++ pdata->has_gbit = 1; ++ pdata->is_ar724x = 1; ++ if (ath79_soc == ATH79_SOC_AR7240) ++ pdata->is_ar7240 = 1; ++ break; ++ ++ case ATH79_SOC_AR9132: ++ pdata->has_gbit = 1; ++ /* fall through */ ++ case ATH79_SOC_AR9130: ++ if (id == 0) ++ pdata->set_speed = ar91xx_set_speed_ge0; ++ else ++ pdata->set_speed = ar91xx_set_speed_ge1; ++ pdata->is_ar91xx = 1; ++ break; ++ ++ case ATH79_SOC_AR9330: ++ case ATH79_SOC_AR9331: ++ if (id == 0) { ++ pdata->reset_bit = AR933X_RESET_GE0_MAC | ++ AR933X_RESET_GE0_MDIO; ++ pdata->set_speed = ath79_set_speed_dummy; ++ ++ pdata->phy_mask = BIT(4); ++ } else { ++ pdata->reset_bit = AR933X_RESET_GE1_MAC | ++ AR933X_RESET_GE1_MDIO; ++ pdata->set_speed = ath79_set_speed_dummy; ++ ++ pdata->speed = SPEED_1000; ++ pdata->has_gbit = 1; ++ pdata->duplex = DUPLEX_FULL; ++ pdata->switch_data = &ath79_switch_data; ++ pdata->use_flow_control = 1; ++ ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ } ++ ++ pdata->is_ar724x = 1; ++ break; ++ ++ case ATH79_SOC_AR9341: ++ case ATH79_SOC_AR9342: ++ case ATH79_SOC_AR9344: ++ case ATH79_SOC_QCA9533: ++ if (id == 0) { ++ pdata->reset_bit = AR934X_RESET_GE0_MAC | ++ AR934X_RESET_GE0_MDIO; ++ pdata->set_speed = ar934x_set_speed_ge0; ++ ++ if (ath79_soc == ATH79_SOC_QCA9533) ++ pdata->disable_inline_checksum_engine = 1; ++ } else { ++ pdata->reset_bit = AR934X_RESET_GE1_MAC | ++ AR934X_RESET_GE1_MDIO; ++ pdata->set_speed = ath79_set_speed_dummy; ++ ++ pdata->switch_data = &ath79_switch_data; ++ ++ /* reset the built-in switch */ ++ ath79_device_reset_set(AR934X_RESET_ETH_SWITCH); ++ ath79_device_reset_clear(AR934X_RESET_ETH_SWITCH); ++ } ++ ++ pdata->has_gbit = 1; ++ pdata->is_ar724x = 1; ++ ++ pdata->max_frame_len = SZ_16K - 1; ++ pdata->desc_pktlen_mask = SZ_16K - 1; ++ break; ++ ++ case ATH79_SOC_TP9343: ++ if (id == 0) { ++ pdata->reset_bit = AR933X_RESET_GE0_MAC | ++ AR933X_RESET_GE0_MDIO; ++ pdata->set_speed = ath79_set_speed_dummy; ++ ++ if (!pdata->phy_mask) ++ pdata->phy_mask = BIT(4); ++ } else { ++ pdata->reset_bit = AR933X_RESET_GE1_MAC | ++ AR933X_RESET_GE1_MDIO; ++ pdata->set_speed = ath79_set_speed_dummy; ++ ++ pdata->speed = SPEED_1000; ++ pdata->duplex = DUPLEX_FULL; ++ pdata->switch_data = &ath79_switch_data; ++ pdata->use_flow_control = 1; ++ ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ } ++ ++ pdata->has_gbit = 1; ++ pdata->is_ar724x = 1; ++ break; ++ ++ case ATH79_SOC_QCA9556: ++ case ATH79_SOC_QCA9558: ++ if (id == 0) { ++ pdata->reset_bit = QCA955X_RESET_GE0_MAC | ++ QCA955X_RESET_GE0_MDIO; ++ pdata->set_speed = qca955x_set_speed_xmii; ++ ++ /* QCA9556 only has SGMII interface */ ++ if (ath79_soc == ATH79_SOC_QCA9556) ++ pdata->set_speed = qca9556_set_speed_sgmii; ++ } else { ++ pdata->reset_bit = QCA955X_RESET_GE1_MAC | ++ QCA955X_RESET_GE1_MDIO; ++ pdata->set_speed = qca9558_set_speed_sgmii; ++ } ++ ++ pdata->has_gbit = 1; ++ pdata->is_ar724x = 1; ++ ++ /* ++ * Limit the maximum frame length to 4095 bytes. ++ * Although the documentation says that the hardware ++ * limit is 16383 bytes but that does not work in ++ * practice. It seems that the hardware only updates ++ * the lowest 12 bits of the packet length field ++ * in the RX descriptor. ++ */ ++ pdata->max_frame_len = SZ_4K - 1; ++ pdata->desc_pktlen_mask = SZ_16K - 1; ++ break; ++ ++ case ATH79_SOC_QCA956X: ++ if (id == 0) { ++ pdata->reset_bit = QCA955X_RESET_GE0_MAC | ++ QCA955X_RESET_GE0_MDIO; ++ ++ if (pdata->phy_if_mode == PHY_INTERFACE_MODE_SGMII) ++ pdata->set_speed = qca956x_set_speed_sgmii; ++ else ++ pdata->set_speed = ar934x_set_speed_ge0; ++ ++ pdata->disable_inline_checksum_engine = 1; ++ } else { ++ pdata->reset_bit = QCA955X_RESET_GE1_MAC | ++ QCA955X_RESET_GE1_MDIO; ++ ++ pdata->set_speed = ath79_set_speed_dummy; ++ ++ pdata->switch_data = &ath79_switch_data; ++ ++ pdata->speed = SPEED_1000; ++ pdata->duplex = DUPLEX_FULL; ++ pdata->use_flow_control = 1; ++ ++ /* reset the built-in switch */ ++ ath79_device_reset_set(AR934X_RESET_ETH_SWITCH); ++ ath79_device_reset_clear(AR934X_RESET_ETH_SWITCH); ++ } ++ ++ pdata->has_gbit = 1; ++ pdata->is_ar724x = 1; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ switch (pdata->phy_if_mode) { ++ case PHY_INTERFACE_MODE_GMII: ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ if (!pdata->has_gbit) { ++ printk(KERN_ERR "ar71xx: no gbit available on eth%d\n", ++ id); ++ return; ++ } ++ /* fallthrough */ ++ default: ++ break; ++ } ++ ++ if (!is_valid_ether_addr(pdata->mac_addr)) { ++ random_ether_addr(pdata->mac_addr); ++ printk(KERN_DEBUG ++ "ar71xx: using random MAC address for eth%d\n", ++ ath79_eth_instance); ++ } ++ ++ if (pdata->mii_bus_dev == NULL) { ++ switch (ath79_soc) { ++ case ATH79_SOC_AR9341: ++ case ATH79_SOC_AR9342: ++ case ATH79_SOC_AR9344: ++ if (id == 0) ++ pdata->mii_bus_dev = &ath79_mdio0_device.dev; ++ else ++ pdata->mii_bus_dev = &ath79_mdio1_device.dev; ++ break; ++ ++ case ATH79_SOC_AR7241: ++ case ATH79_SOC_AR9330: ++ case ATH79_SOC_AR9331: ++ case ATH79_SOC_QCA9533: ++ case ATH79_SOC_TP9343: ++ pdata->mii_bus_dev = &ath79_mdio1_device.dev; ++ break; ++ ++ case ATH79_SOC_QCA9556: ++ case ATH79_SOC_QCA9558: ++ /* don't assign any MDIO device by default */ ++ break; ++ ++ case ATH79_SOC_QCA956X: ++ if (pdata->phy_if_mode != PHY_INTERFACE_MODE_SGMII) ++ pdata->mii_bus_dev = &ath79_mdio1_device.dev; ++ break; ++ ++ default: ++ pdata->mii_bus_dev = &ath79_mdio0_device.dev; ++ break; ++ } ++ } ++ ++ /* Reset the device */ ++ ath79_device_reset_set(pdata->reset_bit); ++ msleep(100); ++ ++ ath79_device_reset_clear(pdata->reset_bit); ++ msleep(100); ++ ++ platform_device_register(pdev); ++ ath79_eth_instance++; ++} ++ ++void __init ath79_set_mac_base(unsigned char *mac) ++{ ++ memcpy(ath79_mac_base, mac, ETH_ALEN); ++} ++ ++void __init ath79_parse_ascii_mac(char *mac_str, u8 *mac) ++{ ++ int t; ++ ++ t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ ++ if (t != ETH_ALEN) ++ t = sscanf(mac_str, "%02hhx.%02hhx.%02hhx.%02hhx.%02hhx.%02hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ ++ if (t != ETH_ALEN || !is_valid_ether_addr(mac)) { ++ memset(mac, 0, ETH_ALEN); ++ printk(KERN_DEBUG "ar71xx: invalid mac address \"%s\"\n", ++ mac_str); ++ } ++} ++ ++void __init ath79_extract_mac_reverse(u8 *ptr, u8 *out) ++{ ++ int i; ++ ++ for (i = 0; i < ETH_ALEN; i++) { ++ out[i] = ptr[ETH_ALEN-i-1]; ++ } ++} ++ ++static void __init ath79_set_mac_base_ascii(char *str) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ ath79_parse_ascii_mac(str, mac); ++ ath79_set_mac_base(mac); ++} ++ ++static int __init ath79_ethaddr_setup(char *str) ++{ ++ ath79_set_mac_base_ascii(str); ++ return 1; ++} ++__setup("ethaddr=", ath79_ethaddr_setup); ++ ++static int __init ath79_kmac_setup(char *str) ++{ ++ ath79_set_mac_base_ascii(str); ++ return 1; ++} ++__setup("kmac=", ath79_kmac_setup); ++ ++void __init ath79_init_mac(unsigned char *dst, const unsigned char *src, ++ int offset) ++{ ++ int t; ++ ++ if (!dst) ++ return; ++ ++ if (!src || !is_valid_ether_addr(src)) { ++ memset(dst, '\0', ETH_ALEN); ++ return; ++ } ++ ++ t = (((u32) src[3]) << 16) + (((u32) src[4]) << 8) + ((u32) src[5]); ++ t += offset; ++ ++ dst[0] = src[0]; ++ dst[1] = src[1]; ++ dst[2] = src[2]; ++ dst[3] = (t >> 16) & 0xff; ++ dst[4] = (t >> 8) & 0xff; ++ dst[5] = t & 0xff; ++} ++ ++void __init ath79_init_local_mac(unsigned char *dst, const unsigned char *src) ++{ ++ int i; ++ ++ if (!dst) ++ return; ++ ++ if (!src || !is_valid_ether_addr(src)) { ++ memset(dst, '\0', ETH_ALEN); ++ return; ++ } ++ ++ for (i = 0; i < ETH_ALEN; i++) ++ dst[i] = src[i]; ++ dst[0] |= 0x02; ++} +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h +new file mode 100644 +index 0000000000..4d78260fbe +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h +@@ -0,0 +1,55 @@ ++/* ++ * Atheros AR71xx SoC device definitions ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 _ATH79_DEV_ETH_H ++#define _ATH79_DEV_ETH_H ++ ++#include ++ ++struct platform_device; ++ ++extern unsigned char ath79_mac_base[] __initdata; ++void ath79_parse_ascii_mac(char *mac_str, u8 *mac); ++void ath79_extract_mac_reverse(u8 *ptr, u8 *out); ++void ath79_init_mac(unsigned char *dst, const unsigned char *src, ++ int offset); ++void ath79_init_local_mac(unsigned char *dst, const unsigned char *src); ++ ++struct ath79_eth_pll_data { ++ u32 pll_10; ++ u32 pll_100; ++ u32 pll_1000; ++}; ++ ++extern struct ath79_eth_pll_data ath79_eth0_pll_data; ++extern struct ath79_eth_pll_data ath79_eth1_pll_data; ++ ++extern struct ag71xx_platform_data ath79_eth0_data; ++extern struct ag71xx_platform_data ath79_eth1_data; ++extern struct platform_device ath79_eth0_device; ++extern struct platform_device ath79_eth1_device; ++void ath79_register_eth(unsigned int id); ++ ++extern struct ag71xx_switch_platform_data ath79_switch_data; ++ ++extern struct ag71xx_mdio_platform_data ath79_mdio0_data; ++extern struct ag71xx_mdio_platform_data ath79_mdio1_data; ++extern struct platform_device ath79_mdio0_device; ++extern struct platform_device ath79_mdio1_device; ++void ath79_register_mdio(unsigned int id, u32 phy_mask); ++ ++void ath79_setup_ar933x_phy4_switch(bool mac, bool mdio); ++void ath79_setup_ar934x_eth_cfg(u32 mask); ++void ath79_setup_ar934x_eth_rx_delay(unsigned int rxd, unsigned int rxdv); ++void ath79_setup_qca955x_eth_cfg(u32 mask); ++void ath79_setup_qca956x_eth_cfg(u32 mask); ++ ++#endif /* _ATH79_DEV_ETH_H */ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c +new file mode 100644 +index 0000000000..e53d97dcbf +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dev-spi.h" ++#include "dev-m25p80.h" ++ ++static struct spi_board_info ath79_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ }, ++ { ++ .bus_num = 0, ++ .chip_select = 1, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ } ++}; ++ ++static struct ath79_spi_platform_data ath79_spi_data; ++ ++void __init ath79_register_m25p80(struct flash_platform_data *pdata) ++{ ++ ath79_spi_data.bus_num = 0; ++ ath79_spi_data.num_chipselect = 1; ++ ath79_spi_info[0].platform_data = pdata; ++ ath79_register_spi(&ath79_spi_data, ath79_spi_info, 1); ++} ++ ++static struct flash_platform_data *multi_pdata; ++ ++static struct mtd_info *concat_devs[2] = { NULL, NULL }; ++static struct work_struct mtd_concat_work; ++ ++static void mtd_concat_add_work(struct work_struct *work) ++{ ++ struct mtd_info *mtd; ++ ++ mtd = mtd_concat_create(concat_devs, ARRAY_SIZE(concat_devs), "flash"); ++ ++ mtd_device_register(mtd, multi_pdata->parts, multi_pdata->nr_parts); ++} ++ ++static void mtd_concat_add(struct mtd_info *mtd) ++{ ++ static bool registered = false; ++ ++ if (registered) ++ return; ++ ++ if (!strcmp(mtd->name, "spi0.0")) ++ concat_devs[0] = mtd; ++ else if (!strcmp(mtd->name, "spi0.1")) ++ concat_devs[1] = mtd; ++ else ++ return; ++ ++ if (!concat_devs[0] || !concat_devs[1]) ++ return; ++ ++ registered = true; ++ INIT_WORK(&mtd_concat_work, mtd_concat_add_work); ++ schedule_work(&mtd_concat_work); ++} ++ ++static void mtd_concat_remove(struct mtd_info *mtd) ++{ ++} ++ ++static void add_mtd_concat_notifier(void) ++{ ++ static struct mtd_notifier not = { ++ .add = mtd_concat_add, ++ .remove = mtd_concat_remove, ++ }; ++ ++ register_mtd_user(¬); ++} ++ ++void __init ath79_register_m25p80_multi(struct flash_platform_data *pdata) ++{ ++ multi_pdata = pdata; ++ add_mtd_concat_notifier(); ++ ath79_spi_data.bus_num = 0; ++ ath79_spi_data.num_chipselect = 2; ++ ath79_register_spi(&ath79_spi_data, ath79_spi_info, 2); ++} +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.h +new file mode 100644 +index 0000000000..637b41a7d8 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.h +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (C) 2009-2012 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 _ATH79_DEV_M25P80_H ++#define _ATH79_DEV_M25P80_H ++ ++#include ++ ++void ath79_register_m25p80(struct flash_platform_data *pdata) __init; ++void ath79_register_m25p80_multi(struct flash_platform_data *pdata) __init; ++ ++#endif /* _ATH79_DEV_M25P80_H */ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.c +new file mode 100644 +index 0000000000..9b5256ecc2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.c +@@ -0,0 +1,141 @@ ++/* ++ * Atheros AR934X SoCs built-in NAND flash controller support ++ * ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "dev-nfc.h" ++ ++static struct resource ath79_nfc_resources[2]; ++static u64 ar934x_nfc_dmamask = DMA_BIT_MASK(32); ++static struct ar934x_nfc_platform_data ath79_nfc_data; ++ ++static struct platform_device ath79_nfc_device = { ++ .name = AR934X_NFC_DRIVER_NAME, ++ .id = -1, ++ .resource = ath79_nfc_resources, ++ .num_resources = ARRAY_SIZE(ath79_nfc_resources), ++ .dev = { ++ .dma_mask = &ar934x_nfc_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ .platform_data = &ath79_nfc_data, ++ }, ++}; ++ ++static void __init ath79_nfc_init_resource(struct resource res[2], ++ unsigned long base, ++ unsigned long size, ++ int irq) ++{ ++ memset(res, 0, sizeof(struct resource) * 2); ++ ++ res[0].flags = IORESOURCE_MEM; ++ res[0].start = base; ++ res[0].end = base + size - 1; ++ ++ res[1].flags = IORESOURCE_IRQ; ++ res[1].start = irq; ++ res[1].end = irq; ++} ++ ++static void ar934x_nfc_hw_reset(bool active) ++{ ++ if (active) { ++ ath79_device_reset_set(AR934X_RESET_NANDF); ++ udelay(100); ++ ++ ath79_device_reset_set(AR934X_RESET_ETH_SWITCH_ANALOG); ++ udelay(250); ++ } else { ++ ath79_device_reset_clear(AR934X_RESET_ETH_SWITCH_ANALOG); ++ udelay(250); ++ ++ ath79_device_reset_clear(AR934X_RESET_NANDF); ++ udelay(100); ++ } ++} ++ ++static void ar934x_nfc_setup(void) ++{ ++ ath79_nfc_data.hw_reset = ar934x_nfc_hw_reset; ++ ++ ath79_nfc_init_resource(ath79_nfc_resources, ++ AR934X_NFC_BASE, AR934X_NFC_SIZE, ++ ATH79_MISC_IRQ(21)); ++ ++ platform_device_register(&ath79_nfc_device); ++} ++ ++static void qca955x_nfc_hw_reset(bool active) ++{ ++ if (active) { ++ ath79_device_reset_set(QCA955X_RESET_NANDF); ++ udelay(250); ++ } else { ++ ath79_device_reset_clear(QCA955X_RESET_NANDF); ++ udelay(100); ++ } ++} ++ ++static void qca955x_nfc_setup(void) ++{ ++ ath79_nfc_data.hw_reset = qca955x_nfc_hw_reset; ++ ++ ath79_nfc_init_resource(ath79_nfc_resources, ++ QCA955X_NFC_BASE, QCA955X_NFC_SIZE, ++ ATH79_MISC_IRQ(21)); ++ ++ platform_device_register(&ath79_nfc_device); ++} ++ ++void __init ath79_nfc_set_select_chip(void (*f)(int chip_no)) ++{ ++ ath79_nfc_data.select_chip = f; ++} ++ ++void __init ath79_nfc_set_scan_fixup(int (*f)(struct mtd_info *mtd)) ++{ ++ ath79_nfc_data.scan_fixup = f; ++} ++ ++void __init ath79_nfc_set_swap_dma(bool enable) ++{ ++ ath79_nfc_data.swap_dma = enable; ++} ++ ++void __init ath79_nfc_set_ecc_mode(enum ar934x_nfc_ecc_mode mode) ++{ ++ ath79_nfc_data.ecc_mode = mode; ++} ++ ++void __init ath79_nfc_set_parts(struct mtd_partition *parts, int nr_parts) ++{ ++ ath79_nfc_data.parts = parts; ++ ath79_nfc_data.nr_parts = nr_parts; ++} ++ ++void __init ath79_register_nfc(void) ++{ ++ if (soc_is_ar934x()) ++ ar934x_nfc_setup(); ++ else if (soc_is_qca955x()) ++ qca955x_nfc_setup(); ++ else ++ BUG(); ++} +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.h +new file mode 100644 +index 0000000000..3a1c88fe98 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-nfc.h +@@ -0,0 +1,34 @@ ++/* ++ * Atheros AR934X SoCs built-in NAND Flash Controller support ++ * ++ * Copyright (C) 2011-2012 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 _ATH79_DEV_NFC_H ++#define _ATH79_DEV_NFC_H ++ ++struct mtd_partition; ++enum ar934x_nfc_ecc_mode; ++ ++#ifdef CONFIG_ATH79_DEV_NFC ++void ath79_nfc_set_parts(struct mtd_partition *parts, int nr_parts); ++void ath79_nfc_set_select_chip(void (*f)(int chip_no)); ++void ath79_nfc_set_scan_fixup(int (*f)(struct mtd_info *mtd)); ++void ath79_nfc_set_swap_dma(bool enable); ++void ath79_nfc_set_ecc_mode(enum ar934x_nfc_ecc_mode mode); ++void ath79_register_nfc(void); ++#else ++static inline void ath79_nfc_set_parts(struct mtd_partition *parts, ++ int nr_parts) {} ++static inline void ath79_nfc_set_select_chip(void (*f)(int chip_no)) {} ++static inline void ath79_nfc_set_scan_fixup(int (*f)(struct mtd_info *mtd)) {} ++static inline void ath79_nfc_set_swap_dma(bool enable) {} ++static inline void ath79_nfc_set_ecc_mode(enum ar934x_nfc_ecc_mode mode) {} ++static inline void ath79_register_nfc(void) {} ++#endif ++ ++#endif /* _ATH79_DEV_NFC_H */ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-a60.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-a60.c +new file mode 100644 +index 0000000000..084a4e4cc0 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-a60.c +@@ -0,0 +1,181 @@ ++/* ++ * OpenMesh A60 support ++ * ++ * Copyright (C) 2013 Marek Lindner ++ * Copyright (C) 2014-2017 Sven Eckelmann ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-gpio-buttons.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-usb.h" ++ ++#define A60_GPIO_LED_RED 22 ++#define A60_GPIO_LED_GREEN 23 ++#define A60_GPIO_LED_BLUE 13 ++ ++#define A60_GPIO_BTN_RESET 17 ++ ++#define A60_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define A60_KEYS_DEBOUNCE_INTERVAL (3 * A60_KEYS_POLL_INTERVAL) ++ ++#define A60_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led a40_leds_gpio[] __initdata = { ++ { ++ .name = "a40:red:status", ++ .gpio = A60_GPIO_LED_RED, ++ }, { ++ .name = "a40:green:status", ++ .gpio = A60_GPIO_LED_GREEN, ++ }, { ++ .name = "a40:blue:status", ++ .gpio = A60_GPIO_LED_BLUE, ++ } ++}; ++ ++static struct gpio_led a60_leds_gpio[] __initdata = { ++ { ++ .name = "a60:red:status", ++ .gpio = A60_GPIO_LED_RED, ++ }, { ++ .name = "a60:green:status", ++ .gpio = A60_GPIO_LED_GREEN, ++ }, { ++ .name = "a60:blue:status", ++ .gpio = A60_GPIO_LED_BLUE, ++ } ++}; ++ ++static struct gpio_keys_button a60_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = A60_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = A60_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct at803x_platform_data a60_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info a60_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 1, ++ .platform_data = &a60_at803x_data, ++ }, ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 2, ++ .platform_data = &a60_at803x_data, ++ }, ++}; ++ ++static void __init a60_setup_qca955x_eth_cfg(u32 mask, ++ unsigned int rxd, ++ unsigned int rxdv, ++ unsigned int txd, ++ unsigned int txe) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ ++ t = mask; ++ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; ++ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; ++ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; ++ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; ++ ++ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++static void __init a60_setup_common(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_gpio_keys_polled(-1, A60_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(a60_gpio_keys), ++ a60_gpio_keys); ++ ++ ath79_init_mac(mac, art, 0x02); ++ ath79_register_wmac(art + A60_WMAC_CALDATA_OFFSET, mac); ++ ++ a60_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 3, 3, 0, 0); ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(a60_mdio0_info, ARRAY_SIZE(a60_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0x00); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art, 0x01); ++ ++ /* GMAC0 is connected to the PHY1 */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(1); ++ ath79_eth0_pll_data.pll_1000 = 0x82000101; ++ ath79_eth0_pll_data.pll_100 = 0x80000101; ++ ath79_eth0_pll_data.pll_10 = 0x80001313; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to MDIO1 in SGMII mode */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth1_data.phy_mask = BIT(2); ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ath79_eth1_pll_data.pll_100 = 0x80000101; ++ ath79_eth1_pll_data.pll_10 = 0x80001313; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++} ++ ++static void __init a40_setup(void) ++{ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(a40_leds_gpio), a40_leds_gpio); ++ a60_setup_common(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_A40, "A40", "OpenMesh A40", a40_setup); ++ ++static void __init a60_setup(void) ++{ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(a60_leds_gpio), a60_leds_gpio); ++ a60_setup_common(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_A60, "A60", "OpenMesh A60", a60_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-ap120c.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-ap120c.c +new file mode 100644 +index 0000000000..032261f751 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-ap120c.c +@@ -0,0 +1,147 @@ ++/* ++ * ALFA Network AP120C board support ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2016 Luka Perkov ++ * ++ * 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 ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-ap9x-pci.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define ALFA_AP120C_GPIO_LED 0 ++ ++#define ALFA_AP120C_GPIO_BUTTON_WIFI 16 ++ ++#define ALFA_AP120C_GPIO_WATCH_DOG 20 ++ ++#define ALFA_AP120C_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ALFA_AP120C_KEYS_DEBOUNCE_INTERVAL (3 * ALFA_AP120C_KEYS_POLL_INTERVAL) ++ ++#define ALFA_AP120C_MAC_OFFSET 0x1002 ++#define ALFA_AP120C_CAL0_OFFSET 0x1000 ++ ++static struct gpio_keys_button alfa_ap120c_gpio_keys[] __initdata = { ++ { ++ .desc = "Wireless button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = ALFA_AP120C_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ALFA_AP120C_GPIO_BUTTON_WIFI, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led alfa_ap120c_leds_gpio[] __initdata = { ++ { ++ .name = "ap120c:red:wlan", ++ .gpio = ALFA_AP120C_GPIO_LED, ++ .active_low = 0, ++ } ++}; ++ ++static struct ar8327_pad_cfg ap120c_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data ap120c_ar8327_data = { ++ .pad0_cfg = &ap120c_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info ap120c_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &ap120c_ar8327_data, ++ }, ++}; ++ ++static struct flash_platform_data flash __initdata = { NULL, NULL, 0 }; ++ ++#define ALFA_AP120C_LAN_PHYMASK BIT(5) ++#define ALFA_AP120C_MDIO_PHYMASK ALFA_AP120C_LAN_PHYMASK ++ ++static void __init alfa_ap120c_init(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 mac[ETH_ALEN]; ++ ++ struct ath9k_platform_data *pdata; ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(alfa_ap120c_leds_gpio), ++ alfa_ap120c_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, ALFA_AP120C_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(alfa_ap120c_gpio_keys), ++ alfa_ap120c_gpio_keys); ++ ++ ath79_gpio_function_enable(AR71XX_GPIO_FUNC_SPI_CS1_EN | ++ AR71XX_GPIO_FUNC_SPI_CS2_EN); ++ ++ ath79_register_m25p80_multi(&flash); ++ ++ ath79_init_mac(mac, art + ALFA_AP120C_MAC_OFFSET, 1); ++ ath79_register_wmac(art + ALFA_AP120C_CAL0_OFFSET, mac); ++ ++ ath79_init_mac(mac, art + ALFA_AP120C_MAC_OFFSET, 2); ++ ap91_pci_init(NULL, mac); ++ pdata = ap9x_pci_get_wmac_data(0); ++ if (!pdata) { ++ pr_err("ap120c: unable to get address of wlan data\n"); ++ return; ++ } ++ pdata->use_eeprom = true; ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ BIT(15) | BIT(17) | BIT(19) | BIT(21)); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + ALFA_AP120C_MAC_OFFSET, 0); ++ ++ mdiobus_register_board_info(ap120c_mdio0_info, ARRAY_SIZE(ap120c_mdio0_info)); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = ALFA_AP120C_LAN_PHYMASK; ++ ++ ath79_eth0_pll_data.pll_1000 = 0x42000000; ++ ath79_eth0_pll_data.pll_10 = 0x00001313; ++ ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ALFA_AP120C, "ALFA-AP120C", "ALFA Network AP120C", ++ alfa_ap120c_init); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-ap96.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-ap96.c +new file mode 100644 +index 0000000000..531e5fb18e +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-ap96.c +@@ -0,0 +1,132 @@ ++/* ++ * ALFA Network AP96 board support ++ * ++ * Copyright (C) 2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define ALFA_AP96_GPIO_PCIE_RESET 2 ++#define ALFA_AP96_GPIO_SIM_DETECT 3 ++#define ALFA_AP96_GPIO_MICROSD_CD 4 ++#define ALFA_AP96_GPIO_PCIE_W_DISABLE 5 ++ ++#define ALFA_AP96_GPIO_BUTTON_RESET 11 ++ ++#define ALFA_AP96_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ALFA_AP96_KEYS_DEBOUNCE_INTERVAL (3 * ALFA_AP96_KEYS_POLL_INTERVAL) ++ ++static struct gpio_keys_button alfa_ap96_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ALFA_AP96_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ALFA_AP96_GPIO_BUTTON_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct mmc_spi_platform_data alfa_ap96_mmc_data = { ++ .flags = MMC_SPI_USE_CD_GPIO, ++ .cd_gpio = ALFA_AP96_GPIO_MICROSD_CD, ++ .cd_debounce = 1, ++ .caps = MMC_CAP_NEEDS_POLL, ++ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, ++}; ++ ++static struct spi_board_info alfa_ap96_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ }, { ++ .bus_num = 0, ++ .chip_select = 1, ++ .max_speed_hz = 25000000, ++ .modalias = "mmc_spi", ++ .platform_data = &alfa_ap96_mmc_data, ++ }, { ++ .bus_num = 0, ++ .chip_select = 2, ++ .max_speed_hz = 6250000, ++ .modalias = "rtc-pcf2123", ++ }, ++}; ++ ++static struct ath79_spi_platform_data alfa_ap96_spi_data = { ++ .bus_num = 0, ++ .num_chipselect = 3, ++}; ++ ++static void __init alfa_ap96_gpio_setup(void) ++{ ++ ath79_gpio_function_enable(AR71XX_GPIO_FUNC_SPI_CS1_EN | ++ AR71XX_GPIO_FUNC_SPI_CS2_EN); ++ ++ gpio_request(ALFA_AP96_GPIO_MICROSD_CD, "microSD CD"); ++ gpio_direction_input(ALFA_AP96_GPIO_MICROSD_CD); ++ gpio_request(ALFA_AP96_GPIO_PCIE_RESET, "PCIe reset"); ++ gpio_direction_output(ALFA_AP96_GPIO_PCIE_RESET, 1); ++ gpio_request(ALFA_AP96_GPIO_PCIE_W_DISABLE, "PCIe write disable"); ++ gpio_direction_output(ALFA_AP96_GPIO_PCIE_W_DISABLE, 1); ++} ++ ++#define ALFA_AP96_WAN_PHYMASK BIT(4) ++#define ALFA_AP96_LAN_PHYMASK BIT(5) ++#define ALFA_AP96_MDIO_PHYMASK (ALFA_AP96_LAN_PHYMASK | ALFA_AP96_WAN_PHYMASK) ++ ++static void __init alfa_ap96_init(void) ++{ ++ alfa_ap96_gpio_setup(); ++ ++ ath79_register_mdio(0, ~ALFA_AP96_MDIO_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = ALFA_AP96_WAN_PHYMASK; ++ ath79_eth1_pll_data.pll_1000 = 0x110000; ++ ++ ath79_register_eth(0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = ALFA_AP96_LAN_PHYMASK; ++ ath79_eth1_pll_data.pll_1000 = 0x110000; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++ ath79_register_spi(&alfa_ap96_spi_data, alfa_ap96_spi_info, ++ ARRAY_SIZE(alfa_ap96_spi_info)); ++ ++ ath79_register_gpio_keys_polled(-1, ALFA_AP96_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(alfa_ap96_gpio_keys), ++ alfa_ap96_gpio_keys); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ALFA_AP96, "ALFA-AP96", "ALFA Network AP96", ++ alfa_ap96_init); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-nx.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-nx.c +new file mode 100644 +index 0000000000..a515f4f540 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-alfa-nx.c +@@ -0,0 +1,113 @@ ++/* ++ * ALFA Network N2/N5 board support ++ * ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define ALFA_NX_GPIO_LED_2 17 ++#define ALFA_NX_GPIO_LED_3 16 ++#define ALFA_NX_GPIO_LED_5 12 ++#define ALFA_NX_GPIO_LED_6 8 ++#define ALFA_NX_GPIO_LED_7 6 ++#define ALFA_NX_GPIO_LED_8 7 ++ ++#define ALFA_NX_GPIO_BTN_RESET 11 ++ ++#define ALFA_NX_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ALFA_NX_KEYS_DEBOUNCE_INTERVAL (3 * ALFA_NX_KEYS_POLL_INTERVAL) ++ ++#define ALFA_NX_MAC0_OFFSET 0 ++#define ALFA_NX_MAC1_OFFSET 6 ++#define ALFA_NX_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_keys_button alfa_nx_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ALFA_NX_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ALFA_NX_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led alfa_nx_leds_gpio[] __initdata = { ++ { ++ .name = "alfa:green:led_2", ++ .gpio = ALFA_NX_GPIO_LED_2, ++ .active_low = 1, ++ }, { ++ .name = "alfa:green:led_3", ++ .gpio = ALFA_NX_GPIO_LED_3, ++ .active_low = 1, ++ }, { ++ .name = "alfa:red:led_5", ++ .gpio = ALFA_NX_GPIO_LED_5, ++ .active_low = 1, ++ }, { ++ .name = "alfa:amber:led_6", ++ .gpio = ALFA_NX_GPIO_LED_6, ++ .active_low = 1, ++ }, { ++ .name = "alfa:green:led_7", ++ .gpio = ALFA_NX_GPIO_LED_7, ++ .active_low = 1, ++ }, { ++ .name = "alfa:green:led_8", ++ .gpio = ALFA_NX_GPIO_LED_8, ++ .active_low = 1, ++ } ++}; ++ ++static void __init alfa_nx_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE, ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(0, ARRAY_SIZE(alfa_nx_leds_gpio), ++ alfa_nx_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ALFA_NX_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(alfa_nx_gpio_keys), ++ alfa_nx_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + ALFA_NX_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, ++ art + ALFA_NX_MAC1_OFFSET, 0); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++ /* LAN port */ ++ ath79_register_eth(1); ++ ++ ap91_pci_init(art + ALFA_NX_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ALFA_NX, "ALFA-NX", "ALFA Network N2/N5", ++ alfa_nx_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-all0258n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-all0258n.c +new file mode 100644 +index 0000000000..2495bcba79 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-all0258n.c +@@ -0,0 +1,88 @@ ++/* ++ * Allnet ALL0258N support ++ * ++ * Copyright (C) 2011 Daniel Golle ++ * ++ * 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 "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++/* found via /sys/gpio/... try and error */ ++#define ALL0258N_GPIO_BTN_RESET 1 ++#define ALL0258N_GPIO_LED_RSSIHIGH 13 ++#define ALL0258N_GPIO_LED_RSSIMEDIUM 15 ++#define ALL0258N_GPIO_LED_RSSILOW 14 ++ ++/* defaults taken from others machs */ ++#define ALL0258N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ALL0258N_KEYS_DEBOUNCE_INTERVAL (3 * ALL0258N_KEYS_POLL_INTERVAL) ++ ++/* showed up in the original firmware's bootlog */ ++#define ALL0258N_SEC_PHYMASK BIT(3) ++ ++static struct gpio_led all0258n_leds_gpio[] __initdata = { ++ { ++ .name = "all0258n:green:rssihigh", ++ .gpio = ALL0258N_GPIO_LED_RSSIHIGH, ++ .active_low = 1, ++ }, { ++ .name = "all0258n:yellow:rssimedium", ++ .gpio = ALL0258N_GPIO_LED_RSSIMEDIUM, ++ .active_low = 1, ++ }, { ++ .name = "all0258n:red:rssilow", ++ .gpio = ALL0258N_GPIO_LED_RSSILOW, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button all0258n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ALL0258N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ALL0258N_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init all0258n_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f7f0000); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1f7f1000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(all0258n_leds_gpio), ++ all0258n_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ALL0258N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(all0258n_gpio_keys), ++ all0258n_gpio_keys); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ ath79_eth1_data.phy_mask = ALL0258N_SEC_PHYMASK; ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ap91_pci_init(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ALL0258N, "ALL0258N", "Allnet ALL0258N", ++ all0258n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-all0315n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-all0315n.c +new file mode 100644 +index 0000000000..387ee7f9ea +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-all0315n.c +@@ -0,0 +1,85 @@ ++/* ++ * Allnet ALL0315N support ++ * ++ * Copyright (C) 2012 Daniel Golle ++ * ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-m25p80.h" ++#include "dev-leds-gpio.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define ALL0315N_GPIO_BTN_RESET 0 ++#define ALL0315N_GPIO_LED_RSSIHIGH 14 ++#define ALL0315N_GPIO_LED_RSSIMEDIUM 15 ++#define ALL0315N_GPIO_LED_RSSILOW 16 ++ ++#define ALL0315N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ALL0315N_KEYS_DEBOUNCE_INTERVAL (3 * ALL0315N_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led all0315n_leds_gpio[] __initdata = { ++ { ++ .name = "all0315n:green:rssihigh", ++ .gpio = ALL0315N_GPIO_LED_RSSIHIGH, ++ .active_low = 1, ++ }, { ++ .name = "all0315n:yellow:rssimedium", ++ .gpio = ALL0315N_GPIO_LED_RSSIMEDIUM, ++ .active_low = 1, ++ }, { ++ .name = "all0315n:red:rssilow", ++ .gpio = ALL0315N_GPIO_LED_RSSILOW, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button all0315n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ALL0315N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ALL0315N_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init all0315n_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1ffc0000); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1ffc1000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(all0315n_leds_gpio), ++ all0315n_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ALL0315N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(all0315n_gpio_keys), ++ all0315n_gpio_keys); ++ ++ ap9x_pci_setup_wmac_led_pin(0, 1); ++ ap91_pci_init(ee, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ALL0315N, "ALL0315N", "Allnet ALL0315N", ++ all0315n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-antminer-s1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-antminer-s1.c +new file mode 100644 +index 0000000000..0a81227b51 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-antminer-s1.c +@@ -0,0 +1,98 @@ ++/* ++ * Bitmain Antminer S1 board support ++ * ++ * Copyright (C) 2015 L. D. Pinney ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "dev-usb.h" ++ ++#define ANTMINER_S1_GPIO_BTN_RESET 11 ++ ++#define ANTMINER_S1_GPIO_LED_SYSTEM 23 ++#define ANTMINER_S1_GPIO_LED_WLAN 0 ++#define ANTMINER_S1_GPIO_USB_POWER 26 ++ ++#define ANTMINER_S1_KEYSPOLL_INTERVAL 20 /* msecs */ ++#define ANTMINER_S1_KEYSDEBOUNCE_INTERVAL (3 * ANTMINER_S1_KEYSPOLL_INTERVAL) ++ ++static const char *ANTMINER_S1_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data ANTMINER_S1_flash_data = { ++ .part_probes = ANTMINER_S1_part_probes, ++}; ++ ++static struct gpio_led ANTMINER_S1_leds_gpio[] __initdata = { ++ { ++ .name = "antminer-s1:green:system", ++ .gpio = ANTMINER_S1_GPIO_LED_SYSTEM, ++ .active_low = 0, ++ },{ ++ .name = "antminer-s1:green:wlan", ++ .gpio = ANTMINER_S1_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button ANTMINER_S1_GPIO_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ANTMINER_S1_KEYSDEBOUNCE_INTERVAL, ++ .gpio = ANTMINER_S1_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init antminer_s1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ANTMINER_S1_leds_gpio), ++ ANTMINER_S1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ANTMINER_S1_KEYSPOLL_INTERVAL, ++ ARRAY_SIZE(ANTMINER_S1_GPIO_keys), ++ ANTMINER_S1_GPIO_keys); ++ ++ gpio_request_one(ANTMINER_S1_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(&ANTMINER_S1_flash_data); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ANTMINER_S1, "ANTMINER-S1", ++ "Antminer-S1", antminer_s1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-antminer-s3.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-antminer-s3.c +new file mode 100644 +index 0000000000..b77a6ccc4e +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-antminer-s3.c +@@ -0,0 +1,103 @@ ++/* ++ * Bitmain Antminer S3 board support ++ * ++ * Copyright (C) 2015 L. D. Pinney ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "dev-usb.h" ++ ++#define ANTMINER_S3_GPIO_LED_WLAN 0 ++#define ANTMINER_S3_GPIO_LED_SYSTEM 17 ++#define ANTMINER_S3_GPIO_LED_LAN 22 ++#define ANTMINER_S3_GPIO_USB_POWER 26 ++ ++#define ANTMINER_S3_GPIO_BTN_RESET 11 ++ ++#define ANTMINER_S3_KEYSPOLL_INTERVAL 88 /* msecs */ ++#define ANTMINER_S3_KEYSDEBOUNCE_INTERVAL (3 * ANTMINER_S3_KEYSPOLL_INTERVAL) ++ ++static const char *ANTMINER_S3_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data ANTMINER_S3_flash_data = { ++ .part_probes = ANTMINER_S3_part_probes, ++}; ++ ++static struct gpio_led ANTMINER_S3_leds_gpio[] __initdata = { ++ { ++ .name = "antminer-s3:green:wlan", ++ .gpio = ANTMINER_S3_GPIO_LED_WLAN, ++ .active_low = 0, ++ },{ ++ .name = "antminer-s3:green:system", ++ .gpio = ANTMINER_S3_GPIO_LED_SYSTEM, ++ .active_low = 0, ++ },{ ++ .name = "antminer-s3:yellow:lan", ++ .gpio = ANTMINER_S3_GPIO_LED_LAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button ANTMINER_S3_GPIO_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ANTMINER_S3_KEYSDEBOUNCE_INTERVAL, ++ .gpio = ANTMINER_S3_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init antminer_s3_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ANTMINER_S3_leds_gpio), ++ ANTMINER_S3_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ANTMINER_S3_KEYSPOLL_INTERVAL, ++ ARRAY_SIZE(ANTMINER_S3_GPIO_keys), ++ ANTMINER_S3_GPIO_keys); ++ ++ gpio_request_one(ANTMINER_S3_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(&ANTMINER_S3_flash_data); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ANTMINER_S3, "ANTMINER-S3", ++ "Antminer-S3", antminer_s3_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-antrouter-r1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-antrouter-r1.c +new file mode 100644 +index 0000000000..a8f7b5d687 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-antrouter-r1.c +@@ -0,0 +1,98 @@ ++/* ++ * Bitmain Antrouter R1 board support ++ * ++ * Copyright (C) 2015 L. D. Pinney ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "dev-usb.h" ++ ++#define ANTROUTER_R1_GPIO_BTN_RESET 11 ++ ++#define ANTROUTER_R1_GPIO_LED_WLAN 0 ++#define ANTROUTER_R1_GPIO_LED_BTC 22 ++#define ANTROUTER_R1_GPIO_USB_POWER 18 ++ ++#define ANTROUTER_R1_KEYSPOLL_INTERVAL 44 /* msecs */ ++#define ANTROUTER_R1_KEYSDEBOUNCE_INTERVAL (4 * ANTROUTER_R1_KEYSPOLL_INTERVAL) ++ ++static const char *ANTROUTER_R1_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data ANTROUTER_R1_flash_data = { ++ .part_probes = ANTROUTER_R1_part_probes, ++}; ++ ++static struct gpio_led ANTROUTER_R1_leds_gpio[] __initdata = { ++ { ++ .name = "antrouter-r1:green:wlan", ++ .gpio = ANTROUTER_R1_GPIO_LED_WLAN, ++ .active_low = 0, ++ },{ ++ .name = "antrouter-r1:green:system", ++ .gpio = ANTROUTER_R1_GPIO_LED_BTC, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button ANTROUTER_R1_GPIO_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ANTROUTER_R1_KEYSDEBOUNCE_INTERVAL, ++ .gpio = ANTROUTER_R1_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init antrouter_r1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ANTROUTER_R1_leds_gpio), ++ ANTROUTER_R1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ANTROUTER_R1_KEYSPOLL_INTERVAL, ++ ARRAY_SIZE(ANTROUTER_R1_GPIO_keys), ++ ANTROUTER_R1_GPIO_keys); ++ ++ gpio_request_one(ANTROUTER_R1_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(&ANTROUTER_R1_flash_data); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ANTROUTER_R1, "ANTROUTER-R1", ++ "Antrouter-R1", antrouter_r1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap121f.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap121f.c +new file mode 100644 +index 0000000000..955b7faf63 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap121f.c +@@ -0,0 +1,103 @@ ++/* ++ * ALFA Network AP121F board support ++ * ++ * Copyright (C) 2017 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define AP121F_GPIO_LED_LAN 17 ++#define AP121F_GPIO_LED_VPN 27 ++#define AP121F_GPIO_LED_WLAN 0 ++ ++#define AP121F_GPIO_MICROSD_EN 26 ++ ++#define AP121F_GPIO_BTN_RESET 12 ++#define AP121F_GPIO_BTN_SWITCH 21 ++ ++#define AP121F_KEYS_POLL_INTERVAL 20 ++#define AP121F_KEYS_DEBOUNCE_INTERVAL (3 * AP121F_KEYS_POLL_INTERVAL) ++ ++#define AP121F_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led ap121f_leds_gpio[] __initdata = { ++ { ++ .name = "ap121f:green:lan", ++ .gpio = AP121F_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "ap121f:green:vpn", ++ .gpio = AP121F_GPIO_LED_VPN, ++ .active_low = 1, ++ }, { ++ .name = "ap121f:green:wlan", ++ .gpio = AP121F_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button ap121f_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = AP121F_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP121F_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "switch", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = AP121F_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP121F_GPIO_BTN_SWITCH, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init ap121f_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f040000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ /* LAN */ ++ ath79_register_mdio(0, 0x0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap121f_leds_gpio), ++ ap121f_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, AP121F_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap121f_gpio_keys), ++ ap121f_gpio_keys); ++ ++ gpio_request_one(AP121F_GPIO_MICROSD_EN, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "microSD enable"); ++ ++ ath79_register_wmac(art + AP121F_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP121F, "AP121F", "ALFA Network AP121F", ap121f_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap132.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap132.c +new file mode 100644 +index 0000000000..2ebac057a7 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap132.c +@@ -0,0 +1,189 @@ ++/* ++ * Atheros AP132 reference board support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012 Gabor Juhos ++ * Copyright (c) 2013 Embedded Wireless GmbH ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define AP132_GPIO_LED_USB 4 ++#define AP132_GPIO_LED_WLAN_5G 12 ++#define AP132_GPIO_LED_WLAN_2G 13 ++#define AP132_GPIO_LED_STATUS_RED 14 ++#define AP132_GPIO_LED_WPS_RED 15 ++ ++#define AP132_GPIO_BTN_WPS 16 ++ ++#define AP132_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define AP132_KEYS_DEBOUNCE_INTERVAL (3 * AP132_KEYS_POLL_INTERVAL) ++ ++#define AP132_MAC0_OFFSET 0 ++#define AP132_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led ap132_leds_gpio[] __initdata = { ++ { ++ .name = "ap132:red:status", ++ .gpio = AP132_GPIO_LED_STATUS_RED, ++ .active_low = 1, ++ }, ++ { ++ .name = "ap132:red:wps", ++ .gpio = AP132_GPIO_LED_WPS_RED, ++ .active_low = 1, ++ }, ++ { ++ .name = "ap132:red:wlan-2g", ++ .gpio = AP132_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "ap132:red:usb", ++ .gpio = AP132_GPIO_LED_USB, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button ap132_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = AP132_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP132_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg ap132_ar8327_pad0_cfg; ++ ++static struct ar8327_platform_data ap132_ar8327_data = { ++ .pad0_cfg = &ap132_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info ap132_mdio1_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.1", ++ .mdio_addr = 0, ++ .platform_data = &ap132_ar8327_data, ++ }, ++}; ++ ++static void __init ap132_mdio_setup(void) ++{ ++ void __iomem *base; ++ u32 t; ++ ++#define GPIO_IN_ENABLE3_ADDRESS 0x0050 ++#define GPIO_IN_ENABLE3_MII_GE1_MDI_MASK 0x00ff0000 ++#define GPIO_IN_ENABLE3_MII_GE1_MDI_LSB 16 ++#define GPIO_IN_ENABLE3_MII_GE1_MDI_SET(x) (((x) << GPIO_IN_ENABLE3_MII_GE1_MDI_LSB) & GPIO_IN_ENABLE3_MII_GE1_MDI_MASK) ++#define GPIO_OUT_FUNCTION4_ADDRESS 0x003c ++#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_MASK 0xff000000 ++#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_LSB 24 ++#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_SET(x) (((x) << GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_LSB) & GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_MASK) ++#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_MASK 0x0000ff00 ++#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_LSB 8 ++#define GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_SET(x) (((x) << GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_LSB) & GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_MASK) ++ ++ base = ioremap(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); ++ ++ t = __raw_readl(base + GPIO_IN_ENABLE3_ADDRESS); ++ t &= ~GPIO_IN_ENABLE3_MII_GE1_MDI_MASK; ++ t |= GPIO_IN_ENABLE3_MII_GE1_MDI_SET(19); ++ __raw_writel(t, base + GPIO_IN_ENABLE3_ADDRESS); ++ ++ ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << 19), base + AR71XX_GPIO_REG_OE); ++ ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << 17), base + AR71XX_GPIO_REG_OE); ++ ++ ++ t = __raw_readl(base + GPIO_OUT_FUNCTION4_ADDRESS); ++ t &= ~(GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_MASK | GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_MASK); ++ t |= GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_SET(0x20) | GPIO_OUT_FUNCTION4_ENABLE_GPIO_17_SET(0x21); ++ __raw_writel(t, base + GPIO_OUT_FUNCTION4_ADDRESS); ++ ++ iounmap(base); ++ ++} ++ ++static void __init ap132_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap132_leds_gpio), ++ ap132_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, AP132_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap132_gpio_keys), ++ ap132_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + AP132_WMAC_CALDATA_OFFSET, NULL); ++ ++ /* GMAC0 of the AR8327 switch is connected to GMAC1 via SGMII */ ++ ap132_ar8327_pad0_cfg.mode = AR8327_PAD_MAC_SGMII; ++ ap132_ar8327_pad0_cfg.sgmii_delay_en = true; ++ ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ap132_mdio_setup(); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + AP132_MAC0_OFFSET, 0); ++ ++ mdiobus_register_board_info(ap132_mdio1_info, ++ ARRAY_SIZE(ap132_mdio1_info)); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_mask = BIT(0); ++ ath79_eth1_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP132, "AP132", ++ "Atheros AP132 reference board", ++ ap132_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap143.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap143.c +new file mode 100644 +index 0000000000..098420b92f +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap143.c +@@ -0,0 +1,142 @@ ++/* ++ * Atheros AP143 reference board support ++ * ++ * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define AP143_GPIO_LED_WLAN 12 ++#define AP143_GPIO_LED_WPS 13 ++#define AP143_GPIO_LED_STATUS 13 ++ ++#define AP143_GPIO_LED_WAN 4 ++#define AP143_GPIO_LED_LAN1 16 ++#define AP143_GPIO_LED_LAN2 15 ++#define AP143_GPIO_LED_LAN3 14 ++#define AP143_GPIO_LED_LAN4 11 ++ ++#define AP143_GPIO_BTN_WPS 17 ++ ++#define AP143_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define AP143_KEYS_DEBOUNCE_INTERVAL (3 * AP143_KEYS_POLL_INTERVAL) ++ ++#define AP143_MAC0_OFFSET 0 ++#define AP143_MAC1_OFFSET 6 ++#define AP143_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led ap143_leds_gpio[] __initdata = { ++ { ++ .name = "ap143:green:status", ++ .gpio = AP143_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "ap143:green:wlan", ++ .gpio = AP143_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button ap143_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = AP143_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP143_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init ap143_gpio_led_setup(void) ++{ ++ ath79_gpio_direction_select(AP143_GPIO_LED_WAN, true); ++ ath79_gpio_direction_select(AP143_GPIO_LED_LAN1, true); ++ ath79_gpio_direction_select(AP143_GPIO_LED_LAN2, true); ++ ath79_gpio_direction_select(AP143_GPIO_LED_LAN3, true); ++ ath79_gpio_direction_select(AP143_GPIO_LED_LAN4, true); ++ ++ ath79_gpio_output_select(AP143_GPIO_LED_WAN, ++ QCA953X_GPIO_OUT_MUX_LED_LINK5); ++ ath79_gpio_output_select(AP143_GPIO_LED_LAN1, ++ QCA953X_GPIO_OUT_MUX_LED_LINK1); ++ ath79_gpio_output_select(AP143_GPIO_LED_LAN2, ++ QCA953X_GPIO_OUT_MUX_LED_LINK2); ++ ath79_gpio_output_select(AP143_GPIO_LED_LAN3, ++ QCA953X_GPIO_OUT_MUX_LED_LINK3); ++ ath79_gpio_output_select(AP143_GPIO_LED_LAN4, ++ QCA953X_GPIO_OUT_MUX_LED_LINK4); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap143_leds_gpio), ++ ap143_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, AP143_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap143_gpio_keys), ++ ap143_gpio_keys); ++} ++ ++static void __init ap143_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ap143_gpio_led_setup(); ++ ++ ath79_register_usb(); ++ ++ ath79_wmac_set_led_pin(AP143_GPIO_LED_WLAN); ++ ath79_register_wmac(art + AP143_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + AP143_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + AP143_MAC1_OFFSET, 0); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP143, "AP143", "Qualcomm Atheros AP143 reference board", ++ ap143_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap147.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap147.c +new file mode 100644 +index 0000000000..7b45da4711 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap147.c +@@ -0,0 +1,125 @@ ++/* ++ * Atheros AP147 reference board support ++ * ++ * Copyright (C) 2014 Matthias Schiffer ++ * Copyright (C) 2015 Sven Eckelmann ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define AP147_GPIO_LED_WAN 4 ++#define AP147_GPIO_LED_LAN1 16 ++#define AP147_GPIO_LED_LAN2 15 ++#define AP147_GPIO_LED_LAN3 14 ++#define AP147_GPIO_LED_LAN4 11 ++#define AP147_GPIO_LED_STATUS 13 ++#define AP147_GPIO_LED_WLAN_2G 12 ++ ++#define AP147_GPIO_BTN_WPS 17 ++ ++#define AP147_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define AP147_KEYS_DEBOUNCE_INTERVAL (3 * AP147_KEYS_POLL_INTERVAL) ++ ++#define AP147_MAC0_OFFSET 0x1000 ++ ++static struct gpio_led ap147_leds_gpio[] __initdata = { ++ { ++ .name = "ap147:green:status", ++ .gpio = AP147_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "ap147:green:wlan-2g", ++ .gpio = AP147_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, { ++ .name = "ap147:green:lan1", ++ .gpio = AP147_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "ap147:green:lan2", ++ .gpio = AP147_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "ap147:green:lan3", ++ .gpio = AP147_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "ap147:green:lan4", ++ .gpio = AP147_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "ap147:green:wan", ++ .gpio = AP147_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button ap147_gpio_keys[] __initdata = { ++ { ++ .desc = "wps button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = AP147_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP147_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init ap147_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap147_leds_gpio), ++ ap147_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, AP147_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap147_gpio_keys), ++ ap147_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_pci(); ++ ++ ath79_register_wmac(art + AP147_MAC0_OFFSET, NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 1); ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP147_010, "AP147-010", "Atheros AP147-010 reference board", ap147_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap152.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap152.c +new file mode 100644 +index 0000000000..277a934a18 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap152.c +@@ -0,0 +1,140 @@ ++ ++/* ++ * Qualcomm Atheros AP152 reference board support ++ * ++ * Copyright (c) 2015 Qualcomm Atheros ++ * Copyright (c) 2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++#define AP152_GPIO_LED_USB0 7 ++#define AP152_GPIO_LED_USB1 8 ++ ++#define AP152_GPIO_BTN_RESET 2 ++#define AP152_GPIO_BTN_WPS 1 ++#define AP152_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define AP152_KEYS_DEBOUNCE_INTERVAL (3 * AP152_KEYS_POLL_INTERVAL) ++ ++#define AP152_MAC0_OFFSET 0 ++#define AP152_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led ap152_leds_gpio[] __initdata = { ++ { ++ .name = "ap152:green:usb0", ++ .gpio = AP152_GPIO_LED_USB0, ++ .active_low = 1, ++ }, ++ { ++ .name = "ap152:green:usb1", ++ .gpio = AP152_GPIO_LED_USB1, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button ap152_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = AP152_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP152_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = AP152_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP152_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg ap152_ar8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data ap152_ar8337_data = { ++ .pad0_cfg = &ap152_ar8337_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info ap152_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &ap152_ar8337_data, ++ }, ++}; ++ ++static void __init ap152_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap152_leds_gpio), ++ ap152_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, AP152_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap152_gpio_keys), ++ ap152_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ platform_device_register(&ath79_mdio0_device); ++ ++ mdiobus_register_board_info(ap152_mdio0_info, ++ ARRAY_SIZE(ap152_mdio0_info)); ++ ++ ath79_register_wmac(art + AP152_WMAC_CALDATA_OFFSET, NULL); ++ ath79_register_pci(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + AP152_MAC0_OFFSET, 0); ++ ++ /* GMAC0 is connected to an AR8337 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP152, "AP152", "Qualcomm Atheros AP152 reference board", ++ ap152_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap531b0.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap531b0.c +new file mode 100644 +index 0000000000..3cb2697955 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap531b0.c +@@ -0,0 +1,112 @@ ++/* ++ * Rockeetech AP531B0 11ng wireless AP board support ++ * ++ * Copyright (C) 2013 Gabor Juhos ++ * Copyright (C) 2016 Shuanglin Liu ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++ ++#define AP531B0_GPIO_LED_WLAN 12 ++#define AP531B0_GPIO_LED_STATUS 11 ++ ++#define AP531B0_GPIO_RST_BTN 17 ++ ++#define AP531B0_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define AP531B0_KEYS_DEBOUNCE_INTERVAL (3 * AP531B0_KEYS_POLL_INTERVAL) ++ ++#define AP531B0_WMAC_CALDATA_OFFSET 0x1000 ++ ++ ++static struct gpio_led ap531b0_leds_gpio[] __initdata = { ++ { ++ .name = "ap531b0:green:status", ++ .gpio = AP531B0_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "ap531b0:green:wlan", ++ .gpio = AP531B0_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button ap531b0_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = AP531B0_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP531B0_GPIO_RST_BTN, ++ .active_low = 1, ++ }, ++}; ++ ++ ++static void __init ap531b0_gpio_led_setup(void) ++{ ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap531b0_leds_gpio), ++ ap531b0_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, AP531B0_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap531b0_gpio_keys), ++ ap531b0_gpio_keys); ++} ++ ++static void __init ap531b0_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *pmac; ++ ++ ath79_register_m25p80(NULL); ++ ap531b0_gpio_led_setup(); ++ ath79_register_usb(); ++ ath79_register_pci(); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ pmac = art + AP531B0_WMAC_CALDATA_OFFSET + 2; ++ ath79_init_mac(ath79_eth0_data.mac_addr, pmac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, pmac, 2); ++ ++ ath79_register_wmac(art + AP531B0_WMAC_CALDATA_OFFSET, pmac); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP531B0, "AP531B0", "Rockeetech AP531B0", ++ ap531b0_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap90q.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap90q.c +new file mode 100644 +index 0000000000..99fceca3a0 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap90q.c +@@ -0,0 +1,201 @@ ++/* ++ * Support for YunCore boards: ++ * - AP80Q/AP90Q ++ * - CPE830 ++ * ++ * Copyright (C) 2016 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++/* AP90Q */ ++#define AP90Q_GPIO_LED_WAN 4 ++#define AP90Q_GPIO_LED_WLAN 12 ++#define AP90Q_GPIO_LED_LAN 16 ++ ++#define AP90Q_GPIO_BTN_RESET 17 ++ ++#define AP90Q_KEYS_POLL_INTERVAL 20 ++#define AP90Q_KEYS_DEBOUNCE_INTERVAL (3 * AP90Q_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led ap90q_leds_gpio[] __initdata = { ++ { ++ .name = "ap90q:green:lan", ++ .gpio = AP90Q_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "ap90q:green:wan", ++ .gpio = AP90Q_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "ap90q:green:wlan", ++ .gpio = AP90Q_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button ap90q_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = AP90Q_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP90Q_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++/* CPE830 */ ++#define CPE830_GPIO_LED_LINK4 0 ++#define CPE830_GPIO_LED_LINK1 1 ++#define CPE830_GPIO_LED_LINK2 2 ++#define CPE830_GPIO_LED_LINK3 3 ++#define CPE830_GPIO_LED_WAN 4 ++#define CPE830_GPIO_LED_WLAN 12 ++#define CPE830_GPIO_LED_LAN 16 ++ ++#define CPE830_GPIO_BTN_RESET 17 ++ ++static struct gpio_led cpe830_leds_gpio[] __initdata = { ++ { ++ .name = "cpe830:green:lan", ++ .gpio = CPE830_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe830:green:wan", ++ .gpio = CPE830_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe830:green:wlan", ++ .gpio = CPE830_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe830:green:link1", ++ .gpio = CPE830_GPIO_LED_LINK1, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe830:green:link2", ++ .gpio = CPE830_GPIO_LED_LINK2, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe830:green:link3", ++ .gpio = CPE830_GPIO_LED_LINK3, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe830:green:link4", ++ .gpio = CPE830_GPIO_LED_LINK4, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init ap90q_cpe830_common_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art, NULL); ++ ++ /* For LED on GPIO4 */ ++ ath79_gpio_function_disable(AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ ath79_gpio_direction_select(AP90Q_GPIO_LED_LAN, true); ++ ath79_gpio_direction_select(AP90Q_GPIO_LED_WAN, true); ++ ath79_gpio_direction_select(AP90Q_GPIO_LED_WLAN, true); ++ ++ /* Mute LEDs on boot */ ++ gpio_set_value(AP90Q_GPIO_LED_LAN, 1); ++ gpio_set_value(AP90Q_GPIO_LED_WAN, 1); ++ ++ ath79_gpio_output_select(AP90Q_GPIO_LED_LAN, 0); ++ ath79_gpio_output_select(AP90Q_GPIO_LED_WAN, 0); ++ ath79_gpio_output_select(AP90Q_GPIO_LED_WLAN, 0); ++ ++ ath79_register_gpio_keys_polled(-1, AP90Q_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap90q_gpio_keys), ++ ap90q_gpio_keys); ++} ++ ++static void __init ap90q_setup(void) ++{ ++ ap90q_cpe830_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap90q_leds_gpio), ++ ap90q_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP90Q, "AP90Q", "YunCore AP80Q/AP90Q", ap90q_setup); ++ ++static void __init cpe830_setup(void) ++{ ++ ap90q_cpe830_common_setup(); ++ ++ ath79_gpio_direction_select(CPE830_GPIO_LED_LINK1, true); ++ ath79_gpio_direction_select(CPE830_GPIO_LED_LINK2, true); ++ ath79_gpio_direction_select(CPE830_GPIO_LED_LINK3, true); ++ ath79_gpio_direction_select(CPE830_GPIO_LED_LINK4, true); ++ ++ /* Mute LEDs on boot */ ++ gpio_set_value(CPE830_GPIO_LED_LINK1, 1); ++ gpio_set_value(CPE830_GPIO_LED_LINK2, 1); ++ gpio_set_value(CPE830_GPIO_LED_LINK3, 1); ++ gpio_set_value(CPE830_GPIO_LED_LINK4, 1); ++ ++ ath79_gpio_output_select(CPE830_GPIO_LED_LINK1, 0); ++ ath79_gpio_output_select(CPE830_GPIO_LED_LINK2, 0); ++ ath79_gpio_output_select(CPE830_GPIO_LED_LINK3, 0); ++ ath79_gpio_output_select(CPE830_GPIO_LED_LINK4, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe830_leds_gpio), ++ cpe830_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CPE830, "CPE830", "YunCore CPE830", cpe830_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap91-5g.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap91-5g.c +new file mode 100644 +index 0000000000..64b9430381 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap91-5g.c +@@ -0,0 +1,118 @@ ++/* ++ * ALFA Network AP91-5G board support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define AP91_5G_GPIO_LED_LAN 17 ++#define AP91_5G_GPIO_LED_SIGNAL1 12 ++#define AP91_5G_GPIO_LED_SIGNAL2 8 ++#define AP91_5G_GPIO_LED_SIGNAL3 6 ++#define AP91_5G_GPIO_LED_SIGNAL4 7 ++ ++#define AP91_5G_GPIO_WDT_EN 1 ++#define AP91_5G_GPIO_WDT_IN 0 ++ ++#define AP91_5G_GPIO_BTN_RESET 11 ++ ++#define AP91_5G_KEYS_POLL_INTERVAL 20 ++#define AP91_5G_KEYS_DEBOUNCE_INTERVAL (3 * AP91_5G_KEYS_POLL_INTERVAL) ++ ++#define AP91_5G_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led ap91_5g_leds_gpio[] __initdata = { ++ { ++ .name = "ap91-5g:green:lan", ++ .gpio = AP91_5G_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "ap91-5g:red:signal1", ++ .gpio = AP91_5G_GPIO_LED_SIGNAL1, ++ .active_low = 1, ++ }, { ++ .name = "ap91-5g:orange:signal2", ++ .gpio = AP91_5G_GPIO_LED_SIGNAL2, ++ .active_low = 1, ++ }, { ++ .name = "ap91-5g:green:signal3", ++ .gpio = AP91_5G_GPIO_LED_SIGNAL3, ++ .active_low = 1, ++ }, { ++ .name = "ap91-5g:green:signal4", ++ .gpio = AP91_5G_GPIO_LED_SIGNAL4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button ap91_5g_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = AP91_5G_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP91_5G_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init ap91_5g_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE, ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ gpio_set_value(AP91_5G_GPIO_LED_LAN, 1); ++ gpio_set_value(AP91_5G_GPIO_LED_SIGNAL3, 1); ++ gpio_set_value(AP91_5G_GPIO_LED_SIGNAL4, 1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap91_5g_leds_gpio), ++ ap91_5g_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, AP91_5G_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap91_5g_gpio_keys), ++ ap91_5g_gpio_keys); ++ ++ gpio_request_one(AP91_5G_GPIO_WDT_IN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "WDT input"); ++ ++ gpio_request_one(AP91_5G_GPIO_WDT_EN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "WDT enable"); ++ ++ ap91_pci_init(art + AP91_5G_WMAC_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP91_5G, "AP91-5G", "ALFA Network AP91-5G", ++ ap91_5g_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ap96.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap96.c +new file mode 100644 +index 0000000000..35120d3e2e +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ap96.c +@@ -0,0 +1,142 @@ ++/* ++ * Atheros AP96 board support ++ * ++ * Copyright (C) 2009 Marco Porsch ++ * Copyright (C) 2009-2012 Gabor Juhos ++ * Copyright (C) 2010 Atheros Communications ++ * ++ * 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 "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define AP96_GPIO_LED_12_GREEN 0 ++#define AP96_GPIO_LED_3_GREEN 1 ++#define AP96_GPIO_LED_2_GREEN 2 ++#define AP96_GPIO_LED_WPS_GREEN 4 ++#define AP96_GPIO_LED_5_GREEN 5 ++#define AP96_GPIO_LED_4_ORANGE 6 ++ ++/* Reset button - next to the power connector */ ++#define AP96_GPIO_BTN_RESET 3 ++/* WPS button - next to a led on right */ ++#define AP96_GPIO_BTN_WPS 8 ++ ++#define AP96_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define AP96_KEYS_DEBOUNCE_INTERVAL (3 * AP96_KEYS_POLL_INTERVAL) ++ ++#define AP96_WMAC0_MAC_OFFSET 0x120c ++#define AP96_WMAC1_MAC_OFFSET 0x520c ++#define AP96_CALDATA0_OFFSET 0x1000 ++#define AP96_CALDATA1_OFFSET 0x5000 ++ ++/* ++ * AP96 has 12 unlabeled leds in the front; these are numbered from 1 to 12 ++ * below (from left to right on the board). Led 1 seems to be on whenever the ++ * board is powered. Led 11 shows LAN link activity actity. Led 3 is orange; ++ * others are green. ++ * ++ * In addition, there is one led next to a button on the right side for WPS. ++ */ ++static struct gpio_led ap96_leds_gpio[] __initdata = { ++ { ++ .name = "ap96:green:led2", ++ .gpio = AP96_GPIO_LED_2_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "ap96:green:led3", ++ .gpio = AP96_GPIO_LED_3_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "ap96:orange:led4", ++ .gpio = AP96_GPIO_LED_4_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "ap96:green:led5", ++ .gpio = AP96_GPIO_LED_5_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "ap96:green:led12", ++ .gpio = AP96_GPIO_LED_12_GREEN, ++ .active_low = 1, ++ }, { /* next to a button on right */ ++ .name = "ap96:green:wps", ++ .gpio = AP96_GPIO_LED_WPS_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button ap96_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = AP96_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP96_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = AP96_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AP96_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++#define AP96_WAN_PHYMASK 0x10 ++#define AP96_LAN_PHYMASK 0x0f ++ ++static void __init ap96_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_mdio(0, ~(AP96_WAN_PHYMASK | AP96_LAN_PHYMASK)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = AP96_LAN_PHYMASK; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = AP96_WAN_PHYMASK; ++ ++ ath79_eth1_pll_data.pll_1000 = 0x1f000000; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap96_leds_gpio), ++ ap96_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, AP96_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap96_gpio_keys), ++ ap96_gpio_keys); ++ ++ ap94_pci_init(art + AP96_CALDATA0_OFFSET, ++ art + AP96_WMAC0_MAC_OFFSET, ++ art + AP96_CALDATA1_OFFSET, ++ art + AP96_WMAC1_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AP96, "AP96", "Atheros AP96", ap96_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c25-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c25-v1.c +new file mode 100644 +index 0000000000..c6c6463224 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c25-v1.c +@@ -0,0 +1,227 @@ ++/* ++ * TP-Link Archer C25 v1 board support ++ * ++ * Copyright (C) 2017 Ludwig Thomeczek ++ * based on mach-archer-c60/C59-v1.c ++ * Copyright (C) 2016 Henryk Heisig ++ * ++ * 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 "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include ++#include ++ ++#define ARCHER_C25_GPIO_SHIFT_OE 21 /* OE, Output Enable */ ++#define ARCHER_C25_GPIO_SHIFT_SER 14 /* DS, Data Serial Input */ ++#define ARCHER_C25_GPIO_SHIFT_SRCLK 15 /* SHCP, Shift Reg Clock Input */ ++#define ARCHER_C25_GPIO_SHIFT_SRCLR 19 /* MR, Master Reset */ ++#define ARCHER_C25_GPIO_SHIFT_RCLK 16 /* STCP, Storage Reg Clock Input */ ++ ++#define ARCHER_C25_74HC_GPIO_BASE 32 ++#define ARCHER_C25_74HC_GPIO_LED_WAN_AMBER (ARCHER_C25_74HC_GPIO_BASE + 4) ++#define ARCHER_C25_74HC_GPIO_LED_WAN_GREEN (ARCHER_C25_74HC_GPIO_BASE + 5) ++#define ARCHER_C25_74HC_GPIO_LED_WLAN2 (ARCHER_C25_74HC_GPIO_BASE + 6) ++#define ARCHER_C25_74HC_GPIO_LED_WLAN5 (ARCHER_C25_74HC_GPIO_BASE + 7) ++#define ARCHER_C25_74HC_GPIO_LED_LAN1 (ARCHER_C25_74HC_GPIO_BASE + 0) ++#define ARCHER_C25_74HC_GPIO_LED_LAN2 (ARCHER_C25_74HC_GPIO_BASE + 1) ++#define ARCHER_C25_74HC_GPIO_LED_LAN3 (ARCHER_C25_74HC_GPIO_BASE + 2) ++#define ARCHER_C25_74HC_GPIO_LED_LAN4 (ARCHER_C25_74HC_GPIO_BASE + 3) ++ ++#define ARCHER_C25_V1_SSR_BIT_0 0 ++#define ARCHER_C25_V1_SSR_BIT_1 1 ++#define ARCHER_C25_V1_SSR_BIT_2 2 ++#define ARCHER_C25_V1_SSR_BIT_3 3 ++#define ARCHER_C25_V1_SSR_BIT_4 4 ++#define ARCHER_C25_V1_SSR_BIT_5 5 ++#define ARCHER_C25_V1_SSR_BIT_6 6 ++#define ARCHER_C25_V1_SSR_BIT_7 7 ++ ++ ++#define ARCHER_C25_V1_KEYS_POLL_INTERVAL 20 ++#define ARCHER_C25_V1_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * ARCHER_C25_V1_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C25_V1_GPIO_BTN_RESET 1 ++#define ARCHER_C25_V1_GPIO_BTN_RFKILL 22 ++ ++#define ARCHER_C25_V1_GPIO_LED_POWER 17 ++#define ARCHER_C25_V1_GPIO_LED_WPS 2 ++ ++#define ARCHER_C25_V1_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct spi_gpio_platform_data archer_c25_v1_spi_data = { ++ .sck = ARCHER_C25_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = ARCHER_C25_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 archer_c25_v1_ssr_initdata[] = { ++ BIT(ARCHER_C25_V1_SSR_BIT_7) | ++ BIT(ARCHER_C25_V1_SSR_BIT_6) | ++ BIT(ARCHER_C25_V1_SSR_BIT_5) | ++ BIT(ARCHER_C25_V1_SSR_BIT_4) | ++ BIT(ARCHER_C25_V1_SSR_BIT_3) | ++ BIT(ARCHER_C25_V1_SSR_BIT_2) | ++ BIT(ARCHER_C25_V1_SSR_BIT_1) ++}; ++ ++static struct gen_74x164_chip_platform_data archer_c25_v1_ssr_data = { ++ .base = ARCHER_C25_74HC_GPIO_BASE, ++ .num_registers = ARRAY_SIZE(archer_c25_v1_ssr_initdata), ++ .init_data = archer_c25_v1_ssr_initdata, ++}; ++ ++static struct platform_device archer_c25_v1_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &archer_c25_v1_spi_data, ++ }, ++}; ++ ++static struct spi_board_info archer_c25_v1_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &archer_c25_v1_ssr_data, ++ .controller_data = (void *) ARCHER_C25_GPIO_SHIFT_RCLK, ++ }, ++}; ++ ++static struct gpio_led archer_c25_v1_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c25-v1:green:power", ++ .gpio = ARCHER_C25_V1_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:wps", ++ .gpio = ARCHER_C25_V1_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:wlan2g", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:wlan5g", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:lan1", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:lan2", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:lan3", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:lan4", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:wan", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:amber:wan", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c25_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C25_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C25_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = ARCHER_C25_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C25_V1_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init archer_c25_v1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f7e0008); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f7f0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ spi_register_board_info(archer_c25_v1_spi_info, ++ ARRAY_SIZE(archer_c25_v1_spi_info)); ++ ++ platform_device_register(&archer_c25_v1_spi_device); ++ ++ gpio_request_one(ARCHER_C25_GPIO_SHIFT_OE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "LED control"); ++ ++ gpio_request_one(ARCHER_C25_GPIO_SHIFT_SRCLR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LED reset"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c25_v1_leds_gpio), ++ archer_c25_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C25_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c25_v1_gpio_keys), ++ archer_c25_v1_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + ARCHER_C25_V1_WMAC_CALDATA_OFFSET, mac); ++ ap91_pci_init(NULL, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C25_V1, "ARCHER-C25-V1", "TP-LINK Archer C25 v1", ++ archer_c25_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +new file mode 100644 +index 0000000000..6cc40e6a7b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +@@ -0,0 +1,342 @@ ++/* ++ * TP-Link Archer C58/C59 v1 board support ++ * ++ * Copyright (C) 2017 Henryk Heisig ++ * ++ * 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 ++#include ++ ++#include "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++#define ARCHER_C59_V1_KEYS_POLL_INTERVAL 20 ++#define ARCHER_C59_V1_KEYS_DEBOUNCE_INTERVAL (3 * ARCHER_C59_V1_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C59_V1_GPIO_BTN_RESET 21 ++#define ARCHER_C59_V1_GPIO_BTN_RFKILL 2 ++#define ARCHER_C59_V1_GPIO_BTN_WPS 1 ++ ++#define ARCHER_C59_V1_GPIO_USB_POWER 22 ++ ++#define ARCHER_C59_GPIO_SHIFT_OE 16 ++#define ARCHER_C59_GPIO_SHIFT_SER 17 ++#define ARCHER_C59_GPIO_SHIFT_SRCLK 18 ++#define ARCHER_C59_GPIO_SHIFT_SRCLR 19 ++#define ARCHER_C59_GPIO_SHIFT_RCLK 20 ++ ++#define ARCHER_C59_74HC_GPIO_BASE 32 ++#define ARCHER_C59_74HC_GPIO_LED_POWER (ARCHER_C59_74HC_GPIO_BASE + 0) ++#define ARCHER_C59_74HC_GPIO_LED_WLAN2 (ARCHER_C59_74HC_GPIO_BASE + 1) ++#define ARCHER_C59_74HC_GPIO_LED_WLAN5 (ARCHER_C59_74HC_GPIO_BASE + 2) ++#define ARCHER_C59_74HC_GPIO_LED_LAN (ARCHER_C59_74HC_GPIO_BASE + 3) ++#define ARCHER_C59_74HC_GPIO_LED_WAN_GREEN (ARCHER_C59_74HC_GPIO_BASE + 4) ++#define ARCHER_C59_74HC_GPIO_LED_WAN_AMBER (ARCHER_C59_74HC_GPIO_BASE + 5) ++#define ARCHER_C59_74HC_GPIO_LED_WPS (ARCHER_C59_74HC_GPIO_BASE + 6) ++#define ARCHER_C59_74HC_GPIO_LED_USB (ARCHER_C59_74HC_GPIO_BASE + 7) ++ ++#define ARCHER_C59_V1_SSR_BIT_0 0 ++#define ARCHER_C59_V1_SSR_BIT_1 1 ++#define ARCHER_C59_V1_SSR_BIT_2 2 ++#define ARCHER_C59_V1_SSR_BIT_3 3 ++#define ARCHER_C59_V1_SSR_BIT_4 4 ++#define ARCHER_C59_V1_SSR_BIT_5 5 ++#define ARCHER_C59_V1_SSR_BIT_6 6 ++#define ARCHER_C59_V1_SSR_BIT_7 7 ++ ++#define ARCHER_C59_V1_WMAC_CALDATA_OFFSET 0x1000 ++#define ARCHER_C59_V1_PCI_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led archer_c58_v1_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c58-v1:green:power", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:wlan2g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:wlan5g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:lan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:amber:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:wps", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led archer_c59_v1_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c59-v1:green:power", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:wlan2g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:wlan5g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:lan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:amber:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:wps", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:usb", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led archer_c59_v2_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c59-v2:green:power", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v2:green:wlan2g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v2:green:wlan5g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v2:green:lan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v2:green:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v2:amber:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v2:green:wps", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v2:green:usb", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c59_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C59_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C59_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = ARCHER_C59_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C59_V1_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ARCHER_C59_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C59_V1_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct spi_gpio_platform_data archer_c59_v1_spi_data = { ++ .sck = ARCHER_C59_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = ARCHER_C59_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 archer_c59_v1_ssr_initdata[] = { ++ BIT(ARCHER_C59_V1_SSR_BIT_7) | ++ BIT(ARCHER_C59_V1_SSR_BIT_6) | ++ BIT(ARCHER_C59_V1_SSR_BIT_5) | ++ BIT(ARCHER_C59_V1_SSR_BIT_4) | ++ BIT(ARCHER_C59_V1_SSR_BIT_3) | ++ BIT(ARCHER_C59_V1_SSR_BIT_2) | ++ BIT(ARCHER_C59_V1_SSR_BIT_1) ++}; ++ ++static struct gen_74x164_chip_platform_data archer_c59_v1_ssr_data = { ++ .base = ARCHER_C59_74HC_GPIO_BASE, ++ .num_registers = ARRAY_SIZE(archer_c59_v1_ssr_initdata), ++ .init_data = archer_c59_v1_ssr_initdata, ++}; ++ ++static struct platform_device archer_c59_v1_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &archer_c59_v1_spi_data, ++ }, ++}; ++ ++static struct spi_board_info archer_c59_v1_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &archer_c59_v1_ssr_data, ++ .controller_data = (void *) ARCHER_C59_GPIO_SHIFT_RCLK, ++ }, ++}; ++ ++static void __init archer_c5x_v1_setup(u32 macLocation) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(macLocation); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ spi_register_board_info(archer_c59_v1_spi_info, ++ ARRAY_SIZE(archer_c59_v1_spi_info)); ++ platform_device_register(&archer_c59_v1_spi_device); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C59_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c59_v1_gpio_keys), ++ archer_c59_v1_gpio_keys); ++ ++ ath79_setup_qca956x_eth_cfg(QCA956X_ETH_CFG_SW_PHY_SWAP | ++ QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(0); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + ARCHER_C59_V1_WMAC_CALDATA_OFFSET, mac); ++ ap91_pci_init(art + ARCHER_C59_V1_PCI_CALDATA_OFFSET, NULL); ++ ++ ath79_register_usb(); ++ gpio_request_one(ARCHER_C59_V1_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ gpio_request_one(ARCHER_C59_GPIO_SHIFT_OE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "LED control"); ++ gpio_request_one(ARCHER_C59_GPIO_SHIFT_SRCLR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LED reset"); ++} ++ ++static void __init archer_c58_v1_setup(void) ++{ ++ archer_c5x_v1_setup(0x1f010008); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c58_v1_leds_gpio), ++ archer_c58_v1_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C58_V1, "ARCHER-C58-V1", ++ "TP-LINK Archer C58 v1", archer_c58_v1_setup); ++ ++static void __init archer_c59_v1_setup(void) ++{ ++ archer_c5x_v1_setup(0x1f010008); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c59_v1_leds_gpio), ++ archer_c59_v1_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C59_V1, "ARCHER-C59-V1", ++ "TP-LINK Archer C59 v1", archer_c59_v1_setup); ++ ++static void __init archer_c59_v2_setup(void) ++{ ++ archer_c5x_v1_setup(0x1f030008); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c59_v2_leds_gpio), ++ archer_c59_v2_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C59_V2, "ARCHER-C59-V2", ++ "TP-LINK Archer C59 v2", archer_c59_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c +new file mode 100644 +index 0000000000..a0839e6bca +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c +@@ -0,0 +1,225 @@ ++/* ++ * TP-Link Archer C60 v1 board support ++ * ++ * Copyright (C) 2017 Henryk Heisig ++ * ++ * 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 "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++#define ARCHER_C60_V1_GPIO_LED_LAN 2 ++#define ARCHER_C60_V1_GPIO_LED_POWER 16 ++#define ARCHER_C60_V1_GPIO_LED_WLAN2 17 ++#define ARCHER_C60_V1_GPIO_LED_WLAN5 18 ++#define ARCHER_C60_V1_GPIO_LED_WPS 19 ++#define ARCHER_C60_V1_GPIO_LED_WAN_GREEN 20 ++#define ARCHER_C60_V1_GPIO_LED_WAN_AMBER 22 ++ ++ ++#define ARCHER_C60_V1_KEYS_POLL_INTERVAL 20 ++#define ARCHER_C60_V1_KEYS_DEBOUNCE_INTERVAL (3 * ARCHER_C60_V1_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C60_V1_GPIO_BTN_RESET 21 ++#define ARCHER_C60_V1_GPIO_BTN_RFKILL 1 ++ ++ ++ ++#define ARCHER_C60_V1_WMAC_CALDATA_OFFSET 0x1000 ++#define ARCHER_C60_V1_PCI_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led archer_c60_v1_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c60-v1:green:power", ++ .gpio = ARCHER_C60_V1_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:wlan2g", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:wlan5g", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:lan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:wan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:amber:wan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:wps", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led archer_c60_v2_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c60-v2:green:power", ++ .gpio = ARCHER_C60_V1_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v2:green:wlan2g", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v2:green:wlan5g", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v2:green:lan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v2:green:wan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v2:amber:wan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v2:green:wps", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c60_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C60_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C60_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = ARCHER_C60_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C60_V1_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init archer_c60_v1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f010008); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f7f0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c60_v1_leds_gpio), ++ archer_c60_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C60_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c60_v1_gpio_keys), ++ archer_c60_v1_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + ARCHER_C60_V1_WMAC_CALDATA_OFFSET, mac); ++ ap91_pci_init(art + ARCHER_C60_V1_PCI_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C60_V1, "ARCHER-C60-V1", ++ "TP-LINK Archer C60 v1", archer_c60_v1_setup); ++ ++static void __init archer_c60_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fb08); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f7f0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c60_v2_leds_gpio), ++ archer_c60_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C60_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c60_v1_gpio_keys), ++ archer_c60_v1_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + ARCHER_C60_V1_WMAC_CALDATA_OFFSET, mac); ++ ap91_pci_init(art + ARCHER_C60_V1_PCI_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C60_V2, "ARCHER-C60-V2", ++ "TP-LINK Archer C60 v2", archer_c60_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c +new file mode 100644 +index 0000000000..ee9ce49bcf +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c +@@ -0,0 +1,260 @@ ++ ++/* ++ * Atheros ARCHER_C7 reference board support ++ * ++ * Copyright (c) 2017 Felix Fietkau ++ * Copyright (c) 2014 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++ ++#define ARCHER_C7_GPIO_SHIFT_OE 1 ++#define ARCHER_C7_GPIO_SHIFT_SER 14 ++#define ARCHER_C7_GPIO_SHIFT_SRCLK 15 ++#define ARCHER_C7_GPIO_SHIFT_RCLK 16 ++#define ARCHER_C7_GPIO_SHIFT_SRCLR 21 ++ ++#define ARCHER_C7_GPIO_BTN_RESET 5 ++#define ARCHER_C7_GPIO_BTN_WPS_WIFI 2 ++ ++#define ARCHER_C7_GPIO_LED_WLAN5 9 ++#define ARCHER_C7_GPIO_LED_POWER 6 ++#define ARCHER_C7_GPIO_LED_USB1 7 ++#define ARCHER_C7_GPIO_LED_USB2 8 ++ ++#define ARCHER_C7_74HC_GPIO_BASE 32 ++#define ARCHER_C7_GPIO_LED_WPS (ARCHER_C7_74HC_GPIO_BASE + 0) ++#define ARCHER_C7_GPIO_LED_LAN1 (ARCHER_C7_74HC_GPIO_BASE + 1) ++#define ARCHER_C7_GPIO_LED_LAN2 (ARCHER_C7_74HC_GPIO_BASE + 2) ++#define ARCHER_C7_GPIO_LED_LAN3 (ARCHER_C7_74HC_GPIO_BASE + 3) ++#define ARCHER_C7_GPIO_LED_LAN4 (ARCHER_C7_74HC_GPIO_BASE + 4) ++#define ARCHER_C7_GPIO_LED_WAN_GREEN (ARCHER_C7_74HC_GPIO_BASE + 5) ++#define ARCHER_C7_GPIO_LED_WAN_AMBER (ARCHER_C7_74HC_GPIO_BASE + 6) ++#define ARCHER_C7_GPIO_LED_WLAN2 (ARCHER_C7_74HC_GPIO_BASE + 7) ++ ++#define ARCHER_C7_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ARCHER_C7_KEYS_DEBOUNCE_INTERVAL (3 * ARCHER_C7_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C7_MAC0_OFFSET 0 ++#define ARCHER_C7_MAC1_OFFSET 6 ++#define ARCHER_C7_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define ARCHER_C7_GPIO_MDC 3 ++#define ARCHER_C7_GPIO_MDIO 4 ++ ++static struct spi_gpio_platform_data archer_c7_v4_spi_data = { ++ .sck = ARCHER_C7_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = ARCHER_C7_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 archer_c7_v4_ssr_initdata = 0xff; ++ ++static struct gen_74x164_chip_platform_data archer_c7_v4_ssr_data = { ++ .base = ARCHER_C7_74HC_GPIO_BASE, ++ .num_registers = 1, ++ .init_data = &archer_c7_v4_ssr_initdata, ++}; ++ ++static struct platform_device archer_c7_v4_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &archer_c7_v4_spi_data, ++ }, ++}; ++ ++static struct spi_board_info archer_c7_v4_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &archer_c7_v4_ssr_data, ++ .controller_data = (void *) ARCHER_C7_GPIO_SHIFT_RCLK, ++ }, ++}; ++ ++static struct gpio_led archer_c7_v4_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c7-v4:green:power", ++ .gpio = ARCHER_C7_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:wps", ++ .gpio = ARCHER_C7_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:wlan2g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:wlan5g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:lan1", ++ .gpio = ARCHER_C7_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:lan2", ++ .gpio = ARCHER_C7_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:lan3", ++ .gpio = ARCHER_C7_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:lan4", ++ .gpio = ARCHER_C7_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:wan", ++ .gpio = ARCHER_C7_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:amber:wan", ++ .gpio = ARCHER_C7_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:usb1", ++ .gpio = ARCHER_C7_GPIO_LED_USB1, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:usb2", ++ .gpio = ARCHER_C7_GPIO_LED_USB2, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c7_v4_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS and WIFI button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_WPS_WIFI, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg archer_c7_v4_ar8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data archer_c7_v4_ar8337_data = { ++ .pad0_cfg = &archer_c7_v4_ar8337_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info archer_c7_v4_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &archer_c7_v4_ar8337_data, ++ }, ++}; ++ ++ ++static void __init archer_c7_v4_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1ff00008); ++ ++ ath79_register_m25p80(NULL); ++ ++ spi_register_board_info(archer_c7_v4_spi_info, ++ ARRAY_SIZE(archer_c7_v4_spi_info)); ++ ++ platform_device_register(&archer_c7_v4_spi_device); ++ ++ gpio_request_one(ARCHER_C7_GPIO_SHIFT_OE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "LED control"); ++ ++ gpio_request_one(ARCHER_C7_GPIO_SHIFT_SRCLR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LED reset"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c7_v4_leds_gpio), ++ archer_c7_v4_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C7_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c7_v4_gpio_keys), ++ archer_c7_v4_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_gpio_output_select(ARCHER_C7_GPIO_MDC, QCA956X_GPIO_OUT_MUX_GE0_MDC); ++ ath79_gpio_output_select(ARCHER_C7_GPIO_MDIO, QCA956X_GPIO_OUT_MUX_GE0_MDO); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(archer_c7_v4_mdio0_info, ++ ARRAY_SIZE(archer_c7_v4_mdio0_info)); ++ ++ ath79_register_wmac(art + ARCHER_C7_WMAC_CALDATA_OFFSET, mac); ++ ath79_register_pci(); ++ ++ /* GMAC0 is connected to an AR8337 switch */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C7_V4, "ARCHER-C7-V4", "TP-LINK Archer C7 v4", ++ archer_c7_v4_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v5.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v5.c +new file mode 100644 +index 0000000000..0dec008314 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v5.c +@@ -0,0 +1,207 @@ ++/* ++ * Atheros ARCHER_C7 reference board support ++ * ++ * Copyright (c) 2018 Arvid E. Picciani ++ * Copyright (c) 2017 Felix Fietkau ++ * Copyright (c) 2014 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++ ++#define ARCHER_C7_GPIO_BTN_RESET 5 ++#define ARCHER_C7_GPIO_BTN_WPS_WIFI 2 ++ ++#define ARCHER_C7_GPIO_LED_WLAN5 9 ++#define ARCHER_C7_GPIO_LED_POWER 6 ++#define ARCHER_C7_GPIO_LED_USB 7 ++#define ARCHER_C7_GPIO_LED_WPS 1 ++#define ARCHER_C7_GPIO_LED_LAN1 8 ++#define ARCHER_C7_GPIO_LED_LAN2 17 ++#define ARCHER_C7_GPIO_LED_LAN3 16 ++#define ARCHER_C7_GPIO_LED_LAN4 15 ++#define ARCHER_C7_GPIO_LED_WAN_GREEN 21 ++#define ARCHER_C7_GPIO_LED_WAN_AMBER 20 ++#define ARCHER_C7_GPIO_LED_WLAN2 14 ++#define ARCHER_C7_GPIO_USB_PWR 19 ++ ++#define ARCHER_C7_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ARCHER_C7_KEYS_DEBOUNCE_INTERVAL (3 * ARCHER_C7_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C7_MAC0_OFFSET 0 ++#define ARCHER_C7_MAC1_OFFSET 6 ++#define ARCHER_C7_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define ARCHER_C7_GPIO_MDC 3 ++#define ARCHER_C7_GPIO_MDIO 4 ++ ++static struct gpio_led archer_c7_v5_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c7-v5:green:power", ++ .gpio = ARCHER_C7_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:wps", ++ .gpio = ARCHER_C7_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:wlan2g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:wlan5g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:lan1", ++ .gpio = ARCHER_C7_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:lan2", ++ .gpio = ARCHER_C7_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:lan3", ++ .gpio = ARCHER_C7_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:lan4", ++ .gpio = ARCHER_C7_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:wan", ++ .gpio = ARCHER_C7_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:amber:wan", ++ .gpio = ARCHER_C7_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v5:green:usb", ++ .gpio = ARCHER_C7_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c7_v5_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS and WIFI button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_WPS_WIFI, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++ ++static struct ar8327_pad_cfg archer_c7_v5_ar8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data archer_c7_v5_ar8337_data = { ++ .pad0_cfg = &archer_c7_v5_ar8337_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info archer_c7_v5_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &archer_c7_v5_ar8337_data, ++ }, ++}; ++ ++ ++static void __init archer_c7_v5_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f050000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f060008); ++ ++ ath79_register_m25p80(NULL); ++ ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c7_v5_leds_gpio), ++ archer_c7_v5_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C7_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c7_v5_gpio_keys), ++ archer_c7_v5_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_gpio_output_select(ARCHER_C7_GPIO_MDC, QCA956X_GPIO_OUT_MUX_GE0_MDC); ++ ath79_gpio_output_select(ARCHER_C7_GPIO_MDIO, QCA956X_GPIO_OUT_MUX_GE0_MDO); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(archer_c7_v5_mdio0_info, ++ ARRAY_SIZE(archer_c7_v5_mdio0_info)); ++ ++ gpio_request_one(ARCHER_C7_GPIO_USB_PWR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ ath79_register_wmac(art + ARCHER_C7_WMAC_CALDATA_OFFSET, mac); ++ ath79_register_pci(); ++ ++ /* GMAC0 is connected to an AR8337 switch */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C7_V5, "ARCHER-C7-V5", "TP-LINK Archer C7 v5", ++ archer_c7_v5_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7.c +new file mode 100644 +index 0000000000..53c539f85a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7.c +@@ -0,0 +1,349 @@ ++/* ++ * TP-LINK Archer C5/C7/TL-WDR4900 v2 board support ++ * ++ * Copyright (c) 2013 Gabor Juhos ++ * Copyright (c) 2014 施康成 ++ * Copyright (c) 2014 Imre Kaloz ++ * ++ * Based on the Qualcomm Atheros AP135/AP136 reference board support code ++ * Copyright (c) 2012 Qualcomm Atheros ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define ARCHER_C7_GPIO_LED_WLAN2G 12 ++#define ARCHER_C7_GPIO_LED_SYSTEM 14 ++#define ARCHER_C7_GPIO_LED_QSS 15 ++#define ARCHER_C7_GPIO_LED_WLAN5G 17 ++#define ARCHER_C7_GPIO_LED_USB1 18 ++#define ARCHER_C7_GPIO_LED_USB2 19 ++ ++#define ARCHER_C7_GPIO_BTN_RFKILL 23 ++#define ARCHER_C7_V2_GPIO_BTN_RFKILL 23 ++#define ARCHER_C7_GPIO_BTN_RESET 16 ++ ++#define ARCHER_C7_GPIO_USB1_POWER 22 ++#define ARCHER_C7_GPIO_USB2_POWER 21 ++ ++#define ARCHER_C7_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ARCHER_C7_KEYS_DEBOUNCE_INTERVAL (3 * ARCHER_C7_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C7_WMAC_CALDATA_OFFSET 0x1000 ++#define ARCHER_C7_PCIE_CALDATA_OFFSET 0x5000 ++ ++static const char *archer_c7_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data archer_c7_flash_data = { ++ .part_probes = archer_c7_part_probes, ++}; ++ ++static struct gpio_led archer_c7_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:qss", ++ .gpio = ARCHER_C7_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:system", ++ .gpio = ARCHER_C7_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan2g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan5g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb1", ++ .gpio = ARCHER_C7_GPIO_LED_USB1, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb2", ++ .gpio = ARCHER_C7_GPIO_LED_USB2, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led wdr4900_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:qss", ++ .gpio = ARCHER_C7_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:system", ++ .gpio = ARCHER_C7_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:wlan2g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb1", ++ .gpio = ARCHER_C7_GPIO_LED_USB1, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb2", ++ .gpio = ARCHER_C7_GPIO_LED_USB2, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c7_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL switch", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_RFKILL, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c7_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL switch", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_V2_GPIO_BTN_RFKILL, ++ }, ++}; ++ ++static struct gpio_keys_button wdr4900_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info archer_c7_leds_ar8327[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "tp-link:green:wan"), ++ AR8327_LED_INFO(PHY1_0, HW, "tp-link:green:lan1"), ++ AR8327_LED_INFO(PHY2_0, HW, "tp-link:green:lan2"), ++ AR8327_LED_INFO(PHY3_0, HW, "tp-link:green:lan3"), ++ AR8327_LED_INFO(PHY4_0, HW, "tp-link:green:lan4"), ++}; ++ ++/* GMAC0 of the AR8327 switch is connected to the QCA9558 SoC via SGMII */ ++static struct ar8327_pad_cfg archer_c7_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++/* GMAC6 of the AR8327 switch is connected to the QCA9558 SoC via RGMII */ ++static struct ar8327_pad_cfg archer_c7_ar8327_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg archer_c7_ar8327_led_cfg = { ++ .led_ctrl0 = 0xc737c737, ++ .led_ctrl1 = 0x00000000, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x0030c300, ++ .open_drain = false, ++}; ++ ++static struct ar8327_platform_data archer_c7_ar8327_data = { ++ .pad0_cfg = &archer_c7_ar8327_pad0_cfg, ++ .pad6_cfg = &archer_c7_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &archer_c7_ar8327_led_cfg, ++ .num_leds = ARRAY_SIZE(archer_c7_leds_ar8327), ++ .leds = archer_c7_leds_ar8327, ++}; ++ ++static struct mdio_board_info archer_c7_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &archer_c7_ar8327_data, ++ }, ++}; ++ ++static void __init common_setup(bool pcie_slot) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ u8 tmpmac2[ETH_ALEN]; ++ ++ ath79_register_m25p80(&archer_c7_flash_data); ++ ++ if (pcie_slot) { ++ ath79_register_wmac(art + ARCHER_C7_WMAC_CALDATA_OFFSET, mac); ++ ath79_register_pci(); ++ } else { ++ ath79_init_mac(tmpmac, mac, -1); ++ ath79_register_wmac(art + ARCHER_C7_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_init_mac(tmpmac2, mac, -2); ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++ ap91_pci_init(art + ARCHER_C7_PCIE_CALDATA_OFFSET, tmpmac2); ++ } ++ ++ mdiobus_register_board_info(archer_c7_mdio0_info, ++ ARRAY_SIZE(archer_c7_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ gpio_request_one(ARCHER_C7_GPIO_USB1_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB1 power"); ++ gpio_request_one(ARCHER_C7_GPIO_USB2_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB2 power"); ++ ath79_register_usb(); ++} ++ ++static void __init archer_c5_setup(void) ++{ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C7_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c7_gpio_keys), ++ archer_c7_gpio_keys); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c7_leds_gpio), ++ archer_c7_leds_gpio); ++ common_setup(true); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C5, "ARCHER-C5", "TP-LINK Archer C5", ++ archer_c5_setup); ++ ++static void __init archer_c7_setup(void) ++{ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C7_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c7_gpio_keys), ++ archer_c7_gpio_keys); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c7_leds_gpio), ++ archer_c7_leds_gpio); ++ common_setup(true); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C7, "ARCHER-C7", "TP-LINK Archer C7", ++ archer_c7_setup); ++ ++static void __init archer_c7_v2_setup(void) ++{ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C7_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c7_v2_gpio_keys), ++ archer_c7_v2_gpio_keys); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c7_leds_gpio), ++ archer_c7_leds_gpio); ++ common_setup(true); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C7_V2, "ARCHER-C7-V2", "TP-LINK Archer C7", ++ archer_c7_v2_setup); ++ ++static void __init tl_wdr4900_v2_setup(void) ++{ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C7_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wdr4900_gpio_keys), ++ wdr4900_gpio_keys); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wdr4900_leds_gpio), ++ wdr4900_leds_gpio); ++ common_setup(false); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WDR4900_V2, "TL-WDR4900-v2", "TP-LINK TL-WDR4900 v2", ++ tl_wdr4900_v2_setup) ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-arduino-yun.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-arduino-yun.c +new file mode 100644 +index 0000000000..8ab07d514b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-arduino-yun.c +@@ -0,0 +1,156 @@ ++/* ++ * Arduino Yun support ++ * ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2015 Hauke Mehrtens ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include ++#include ++#include ++#include "common.h" ++ ++// Uncomment to have reset on gpio18 instead of gipo7 ++#define DS2_B ++ ++#define DS_GPIO_LED_WLAN 0 ++#define DS_GPIO_LED_USB 1 ++ ++#define DS_GPIO_OE 21 ++#define DS_GPIO_AVR_RESET 18 ++ ++// Maintained to have the console in the previous version of DS2 working ++#define DS_GPIO_AVR_RESET_DS2 7 ++ ++#define DS_GPIO_OE2 22 ++#define DS_GPIO_UART_ENA 23 ++#define DS_GPIO_CONF_BTN 20 ++ ++#define DS_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DS_KEYS_DEBOUNCE_INTERVAL (3 * DS_KEYS_POLL_INTERVAL) ++ ++#define DS_MAC0_OFFSET 0x0000 ++#define DS_MAC1_OFFSET 0x0006 ++#define DS_CALDATA_OFFSET 0x1000 ++#define DS_WMAC_MAC_OFFSET 0x1002 ++ ++ ++static struct gpio_led ds_leds_gpio[] __initdata = { ++ { ++ .name = "arduino:white:usb", ++ .gpio = DS_GPIO_LED_USB, ++ .active_low = 0, ++ }, ++ { ++ .name = "arduino:blue:wlan", ++ .gpio = DS_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button ds_gpio_keys[] __initdata = { ++ { ++ .desc = "configuration button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DS_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DS_GPIO_CONF_BTN, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init ds_common_setup(void) ++{ ++ static u8 mac[6]; ++ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ath79_register_m25p80(NULL); ++ ++ if (ar93xx_wmac_read_mac_address(mac)) { ++ ath79_register_wmac(NULL, NULL); ++ } else { ++ ath79_register_wmac(art + DS_CALDATA_OFFSET, ++ art + DS_WMAC_MAC_OFFSET); ++ memcpy(mac, art + DS_WMAC_MAC_OFFSET, sizeof(mac)); ++ } ++ ++ mac[3] |= 0x08; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ mac[3] &= 0xF7; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++} ++ ++static void __init ds_setup(void) ++{ ++ u32 t; ++ ++ ds_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ds_leds_gpio), ++ ds_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DS_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ds_gpio_keys), ++ ds_gpio_keys); ++ ath79_register_usb(); ++ ++ /* use the swtich_led directly form sysfs */ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN); ++ ++ //Disable the Function for some pins to have GPIO functionality active ++ // GPIO6-7-8 and GPIO11 ++ ath79_gpio_function_setup(AR933X_GPIO_FUNC_JTAG_DISABLE | AR933X_GPIO_FUNC_I2S_MCK_EN, 0); ++ ++ ath79_gpio_function2_setup(AR933X_GPIO_FUNC2_JUMPSTART_DISABLE, 0); ++ ++ printk("Setting DogStick2 GPIO\n"); ++ ++ t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ t |= AR933X_BOOTSTRAP_MDIO_GPIO_EN; ++ ath79_reset_wr(AR933X_RESET_REG_BOOTSTRAP, t); ++ ++ // Put the avr reset to high ++ if (gpio_request_one(DS_GPIO_AVR_RESET_DS2, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, "OE-1") != 0) ++ printk("Error setting GPIO OE\n"); ++ gpio_unexport(DS_GPIO_AVR_RESET_DS2); ++ gpio_free(DS_GPIO_AVR_RESET_DS2); ++ ++ // enable OE of level shifter ++ if (gpio_request_one(DS_GPIO_OE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, "OE-1") != 0) ++ printk("Error setting GPIO OE\n"); ++ ++ if (gpio_request_one(DS_GPIO_UART_ENA, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, "UART-ENA") != 0) ++ printk("Error setting GPIO Uart Enable\n"); ++ ++ // enable OE of level shifter ++ if (gpio_request_one(DS_GPIO_OE2, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, "OE-2") != 0) ++ printk("Error setting GPIO OE2\n"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARDUINO_YUN, "Yun", "Arduino Yun", ds_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-aw-nr580.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-aw-nr580.c +new file mode 100644 +index 0000000000..281129b787 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-aw-nr580.c +@@ -0,0 +1,107 @@ ++/* ++ * AzureWave AW-NR580 board support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define AW_NR580_GPIO_LED_READY_RED 0 ++#define AW_NR580_GPIO_LED_WLAN 1 ++#define AW_NR580_GPIO_LED_READY_GREEN 2 ++#define AW_NR580_GPIO_LED_WPS_GREEN 4 ++#define AW_NR580_GPIO_LED_WPS_AMBER 5 ++ ++#define AW_NR580_GPIO_BTN_WPS 3 ++#define AW_NR580_GPIO_BTN_RESET 11 ++ ++#define AW_NR580_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define AW_NR580_KEYS_DEBOUNCE_INTERVAL (3 * AW_NR580_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led aw_nr580_leds_gpio[] __initdata = { ++ { ++ .name = "aw-nr580:red:ready", ++ .gpio = AW_NR580_GPIO_LED_READY_RED, ++ .active_low = 0, ++ }, { ++ .name = "aw-nr580:green:ready", ++ .gpio = AW_NR580_GPIO_LED_READY_GREEN, ++ .active_low = 0, ++ }, { ++ .name = "aw-nr580:green:wps", ++ .gpio = AW_NR580_GPIO_LED_WPS_GREEN, ++ .active_low = 0, ++ }, { ++ .name = "aw-nr580:amber:wps", ++ .gpio = AW_NR580_GPIO_LED_WPS_AMBER, ++ .active_low = 0, ++ }, { ++ .name = "aw-nr580:green:wlan", ++ .gpio = AW_NR580_GPIO_LED_WLAN, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button aw_nr580_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = AW_NR580_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AW_NR580_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = AW_NR580_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AW_NR580_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static const char *aw_nr580_part_probes[] = { ++ "RedBoot", ++ NULL, ++}; ++ ++static struct flash_platform_data aw_nr580_flash_data = { ++ .part_probes = aw_nr580_part_probes, ++}; ++ ++static void __init aw_nr580_setup(void) ++{ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ++ ath79_register_pci(); ++ ++ ath79_register_m25p80(&aw_nr580_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(aw_nr580_leds_gpio), ++ aw_nr580_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, AW_NR580_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(aw_nr580_gpio_keys), ++ aw_nr580_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_AW_NR580, "AW-NR580", "AzureWave AW-NR580", ++ aw_nr580_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-bhr-4grv2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-bhr-4grv2.c +new file mode 100644 +index 0000000000..1630845cf8 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-bhr-4grv2.c +@@ -0,0 +1,171 @@ ++/* ++ * Buffalo BHR-4GRV2 board support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * Copyright (c) 2016 FUKAUMI Naoki ++ * ++ * Based on mach-ap136.c and mach-wzr-450hp2.c ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define BHR_4GRV2_GPIO_LED_VPN_RED 3 ++#define BHR_4GRV2_GPIO_LED_VPN_GREEN 18 ++#define BHR_4GRV2_GPIO_LED_POWER_GREEN 19 ++#define BHR_4GRV2_GPIO_LED_DIAG_RED 20 ++ ++#define BHR_4GRV2_GPIO_BTN_RESET 17 ++#define BHR_4GRV2_GPIO_BTN_ECO 21 ++ ++#define BHR_4GRV2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define BHR_4GRV2_KEYS_DEBOUNCE_INTERVAL (3 * BHR_4GRV2_KEYS_POLL_INTERVAL) ++#define BHR_4GRV2_MAC0_OFFSET 0 ++#define BHR_4GRV2_MAC1_OFFSET 6 ++ ++static struct gpio_led bhr_4grv2_leds_gpio[] __initdata = { ++ { ++ .name = "buffalo:red:vpn", ++ .gpio = BHR_4GRV2_GPIO_LED_VPN_RED, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:vpn", ++ .gpio = BHR_4GRV2_GPIO_LED_VPN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:power", ++ .gpio = BHR_4GRV2_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:red:diag", ++ .gpio = BHR_4GRV2_GPIO_LED_DIAG_RED, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button bhr_4grv2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = BHR_4GRV2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = BHR_4GRV2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "ECO button", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = BHR_4GRV2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = BHR_4GRV2_GPIO_BTN_ECO, ++ .active_low = 1, ++ }, ++}; ++ ++/* GMAC0 of the AR8327 switch is connected to GMAC1 via SGMII */ ++static struct ar8327_pad_cfg bhr_4grv2_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++/* GMAC6 of the AR8327 switch is connected to GMAC0 via RGMII */ ++static struct ar8327_pad_cfg bhr_4grv2_ar8327_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data bhr_4grv2_ar8327_data = { ++ .pad0_cfg = &bhr_4grv2_ar8327_pad0_cfg, ++ .pad6_cfg = &bhr_4grv2_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info bhr_4grv2_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &bhr_4grv2_ar8327_data, ++ }, ++}; ++ ++static void __init bhr_4grv2_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(bhr_4grv2_leds_gpio), ++ bhr_4grv2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, BHR_4GRV2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(bhr_4grv2_gpio_keys), ++ bhr_4grv2_gpio_keys); ++ ++ mdiobus_register_board_info(bhr_4grv2_mdio0_info, ++ ARRAY_SIZE(bhr_4grv2_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* GMAC0 is connected to the RGMII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + BHR_4GRV2_MAC0_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + BHR_4GRV2_MAC1_OFFSET, 0); ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_BHR_4GRV2, "BHR-4GRV2", ++ "Buffalo BHR-4GRV2", bhr_4grv2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-bhu-bxu2000n2-a.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-bhu-bxu2000n2-a.c +new file mode 100644 +index 0000000000..8d7c6112d7 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-bhu-bxu2000n2-a.c +@@ -0,0 +1,120 @@ ++/* ++ * BHU BXU2000n-2 A1 board support ++ * ++ * Copyright (C) 2013 Terry Yang ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define BHU_BXU2000N2_A1_GPIO_LED_WLAN 13 ++#define BHU_BXU2000N2_A1_GPIO_LED_WAN 19 ++#define BHU_BXU2000N2_A1_GPIO_LED_LAN 21 ++#define BHU_BXU2000N2_A1_GPIO_LED_SYSTEM 14 ++ ++#define BHU_BXU2000N2_A1_GPIO_BTN_RESET 17 ++ ++#define BHU_BXU2000N2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define BHU_BXU2000N2_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * BHU_BXU2000N2_KEYS_POLL_INTERVAL) ++ ++static const char *bhu_bxu2000n2_part_probes[] = { ++ "cmdlinepart", ++ NULL, ++}; ++ ++static struct flash_platform_data bhu_bxu2000n2_flash_data = { ++ .part_probes = bhu_bxu2000n2_part_probes, ++}; ++ ++static struct gpio_led bhu_bxu2000n2_a1_leds_gpio[] __initdata = { ++ { ++ .name = "bhu:green:status", ++ .gpio = BHU_BXU2000N2_A1_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "bhu:green:lan", ++ .gpio = BHU_BXU2000N2_A1_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "bhu:green:wan", ++ .gpio = BHU_BXU2000N2_A1_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "bhu:green:wlan", ++ .gpio = BHU_BXU2000N2_A1_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button bhu_bxu2000n2_a1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = BHU_BXU2000N2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = BHU_BXU2000N2_A1_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init bhu_ap123_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&bhu_bxu2000n2_flash_data); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ /* GMAC0 is connected to the PHY4 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch. Only use PHY3 */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.phy_mask = BIT(3); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, ee+2); ++} ++ ++static void __init bhu_bxu2000n2_a1_setup(void) ++{ ++ bhu_ap123_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(bhu_bxu2000n2_a1_leds_gpio), ++ bhu_bxu2000n2_a1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, BHU_BXU2000N2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(bhu_bxu2000n2_a1_gpio_keys), ++ bhu_bxu2000n2_a1_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_BHU_BXU2000N2_A1, "BXU2000n-2-A1", ++ "BHU BXU2000n-2 rev. A1", ++ bhu_bxu2000n2_a1_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-bsb.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-bsb.c +new file mode 100644 +index 0000000000..9f9be02eb3 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-bsb.c +@@ -0,0 +1,83 @@ ++/* ++ * Smart Electronics Black Swift board support ++ * ++ * Copyright (C) 2014 Dmitriy Zherebkov dzh@black-swift.com ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define BSB_GPIO_LED_SYS 27 ++ ++#define BSB_GPIO_BTN_RESET 11 ++ ++#define BSB_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define BSB_KEYS_DEBOUNCE_INTERVAL (3 * BSB_KEYS_POLL_INTERVAL) ++ ++#define BSB_MAC_OFFSET 0x0000 ++#define BSB_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led bsb_leds_gpio[] __initdata = { ++ { ++ .name = "bsb:red:sys", ++ .gpio = BSB_GPIO_LED_SYS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button bsb_gpio_keys[] __initdata = { ++ { ++ .desc = "reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = BSB_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = BSB_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init bsb_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false,false); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(bsb_leds_gpio), ++ bsb_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, BSB_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(bsb_gpio_keys), ++ bsb_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + BSB_MAC_OFFSET, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + BSB_MAC_OFFSET, 2); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + BSB_CALDATA_OFFSET, ++ art + BSB_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(ATH79_MACH_BSB, "BSB", "Smart Electronics Black Swift board", ++ bsb_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-c55.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-c55.c +new file mode 100644 +index 0000000000..8aa5ecb6a8 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-c55.c +@@ -0,0 +1,132 @@ ++/* ++ * AirTight Networks C-55 board support ++ * ++ * Copyright (C) 2014-2015 Chris Blake ++ * ++ * Based on Senao CAP4200AG board support ++ * ++ * Copyright (C) 2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define C55_GPIO_LED_PWR_GREEN 12 ++#define C55_GPIO_LED_PWR_AMBER 13 ++#define C55_GPIO_LED_LAN_GREEN 14 ++#define C55_GPIO_LED_LAN_AMBER 15 ++#define C55_GPIO_LED_WLAN_GREEN 18 ++#define C55_GPIO_LED_WLAN_AMBER 19 ++ ++#define C55_GPIO_BTN_RESET 17 ++ ++#define C55_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define C55_KEYS_DEBOUNCE_INTERVAL (3 * C55_KEYS_POLL_INTERVAL) ++ ++#define C55_MAC_OFFSET 0 ++#define C55_WMAC_CALDATA_OFFSET 0x1000 ++#define C55_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led c55_leds_gpio[] __initdata = { ++ { ++ .name = "c-55:green:pwr", ++ .gpio = C55_GPIO_LED_PWR_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-55:amber:pwr", ++ .gpio = C55_GPIO_LED_PWR_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-55:green:lan", ++ .gpio = C55_GPIO_LED_LAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-55:amber:lan", ++ .gpio = C55_GPIO_LED_LAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-55:green:wlan", ++ .gpio = C55_GPIO_LED_WLAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-55:amber:wlan", ++ .gpio = C55_GPIO_LED_WLAN_AMBER, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button c55_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = C55_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = C55_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init c55_setup(void) ++{ ++ /* SPI Storage*/ ++ ath79_register_m25p80(NULL); ++ ++ /* MDIO Interface */ ++ ath79_register_mdio(0, 0x0); ++ ++ /* AR8035-A Ethernet */ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ath79_init_mac(ath79_eth0_data.mac_addr, NULL, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++ ++ /* LEDs & GPIO */ ++ ath79_gpio_output_select(C55_GPIO_LED_LAN_GREEN, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(C55_GPIO_LED_LAN_AMBER, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(c55_leds_gpio), ++ c55_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, C55_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(c55_gpio_keys), ++ c55_gpio_keys); ++ ++ /* WiFi */ ++ ath79_wmac_disable_2ghz(); ++ ath79_register_wmac_simple(); ++ ap91_pci_init_simple(); ++ ++} ++MIPS_MACHINE(ATH79_MACH_C55, "C-55", "AirTight Networks C-55", ++ c55_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-c60.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-c60.c +new file mode 100644 +index 0000000000..bccf2e5873 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-c60.c +@@ -0,0 +1,265 @@ ++/* ++ * AirTight Networks C-60 board support ++ * ++ * Copyright (C) 2016 Christian Lamparter ++ * ++ * Based on AirTight Networks C-55 board support ++ * ++ * Copyright (C) 2014-2015 Chris Blake ++ * ++ * 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 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "dev-usb.h" ++#include "dev-nfc.h" ++#include "machtypes.h" ++ ++#define C60_GPIO_LED_PWR_AMBER 11 ++#define C60_GPIO_LED_WLAN2_GREEN 12 ++#define C60_GPIO_LED_WLAN2_AMBER 13 ++#define C60_GPIO_LED_PWR_GREEN 16 ++ ++#define C60_GPIO_BTN_RESET 17 ++ ++/* GPIOs of the AR9300 PCIe chip */ ++#define C60_GPIO_WMAC_LED_WLAN1_AMBER 0 ++#define C60_GPIO_WMAC_LED_WLAN1_GREEN 3 ++ ++#define C60_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define C60_KEYS_DEBOUNCE_INTERVAL (3 * C60_KEYS_POLL_INTERVAL) ++ ++#define C60_ART_ADDR 0x1f7f0000 ++#define C60_ART_SIZE 0xffff ++#define C60_MAC_OFFSET 0 ++#define C60_WMAC_CALDATA_OFFSET 0x1000 ++#define C60_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led c60_leds_gpio[] __initdata = { ++ { ++ .name = "c-60:amber:pwr", ++ .gpio = C60_GPIO_LED_PWR_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-60:green:pwr", ++ .gpio = C60_GPIO_LED_PWR_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-60:green:wlan2", ++ .gpio = C60_GPIO_LED_WLAN2_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-60:amber:wlan2", ++ .gpio = C60_GPIO_LED_WLAN2_AMBER, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button c60_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = C60_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = C60_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg c60_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data c60_ar8327_data = { ++ .pad0_cfg = &c60_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ } ++}; ++ ++static struct mdio_board_info c60_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &c60_ar8327_data, ++ }, ++}; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++static struct nand_ecclayout c60_nand_ecclayout = { ++ .eccbytes = 7, ++ .eccpos = { 4, 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 3 }, { 6, 2 }, { 11, 2 }, } ++}; ++ ++#else ++ ++static int c60_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 4; ++ oobregion->length = 1; ++ return 0; ++ case 1: ++ oobregion->offset = 8; ++ oobregion->length = 3; ++ return 0; ++ case 2: ++ oobregion->offset = 13; ++ oobregion->length = 3; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static int c60_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = 3; ++ return 0; ++ case 1: ++ oobregion->offset = 6; ++ oobregion->length = 2; ++ return 0; ++ case 2: ++ oobregion->offset = 11; ++ oobregion->length = 2; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops c60_nand_ecclayout_ops = { ++ .ecc = c60_ooblayout_ecc, ++ .free = c60_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static int c60_nand_scan_fixup(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct nand_chip *chip = mtd->priv; ++#else ++ struct nand_chip *chip = mtd_to_nand(mtd); ++#endif ++ ++ chip->ecc.size = 512; ++ chip->ecc.strength = 4; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ chip->ecc.layout = &c60_nand_ecclayout; ++#else ++ mtd_set_ooblayout(mtd, &c60_nand_ecclayout_ops); ++#endif ++ return 0; ++} ++ ++static struct gpio_led c60_wmac0_leds_gpio[] = { ++ { ++ .name = "c-60:amber:wlan1", ++ .gpio = C60_GPIO_WMAC_LED_WLAN1_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "c-60:green:wlan1", ++ .gpio = C60_GPIO_WMAC_LED_WLAN1_GREEN, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init c60_setup(void) ++{ ++ u8 tmpmac[6]; ++ u8 *art = (u8 *) KSEG1ADDR(C60_ART_ADDR); ++ ++ /* NAND */ ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_SOFT_BCH); ++ ath79_nfc_set_scan_fixup(c60_nand_scan_fixup); ++ ath79_register_nfc(); ++ ++ /* SPI Storage*/ ++ ath79_register_m25p80(NULL); ++ ++ /* AR8327 Switch Ethernet */ ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ++ mdiobus_register_board_info(c60_mdio0_info, ++ ARRAY_SIZE(c60_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* GMAC0 is connected to an AR8327N switch */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + C60_MAC_OFFSET, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++ ++ /* LEDs & GPIO */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(c60_leds_gpio), ++ c60_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, C60_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(c60_gpio_keys), ++ c60_gpio_keys); ++ ap9x_pci_setup_wmac_leds(0, c60_wmac0_leds_gpio, ++ ARRAY_SIZE(c60_wmac0_leds_gpio)); ++ /* USB */ ++ ath79_register_usb(); ++ ++ /* WiFi */ ++ ath79_init_mac(tmpmac, art + C60_MAC_OFFSET, 1); ++ ap91_pci_init(art + C60_PCIE_CALDATA_OFFSET, tmpmac); ++ ath79_init_mac(tmpmac, art + C60_MAC_OFFSET, 2); ++ ath79_register_wmac(art + C60_WMAC_CALDATA_OFFSET, tmpmac); ++} ++MIPS_MACHINE(ATH79_MACH_C60, "C-60", "AirTight Networks C-60", ++ c60_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cap324.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cap324.c +new file mode 100644 +index 0000000000..dffbb81bd4 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cap324.c +@@ -0,0 +1,133 @@ ++/* ++ * PowerCloud Systems CAP324 board support ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2012-2013 PowerCloud Systems ++ * Copyright (C) 2015 Daniel Dickinson ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define CAP324_GPIO_LED_POWER_GREEN 12 ++#define CAP324_GPIO_LED_POWER_AMBER 13 ++#define CAP324_GPIO_LED_LAN_GREEN 14 ++#define CAP324_GPIO_LED_LAN_AMBER 15 ++#define CAP324_GPIO_LED_WLAN_GREEN 18 ++#define CAP324_GPIO_LED_WLAN_AMBER 19 ++ ++#define CAP324_GPIO_BTN_RESET 17 ++ ++#define CAP324_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define CAP324_KEYS_DEBOUNCE_INTERVAL (3 * CAP324_KEYS_POLL_INTERVAL) ++ ++#define CAP324_MAC_OFFSET 0 ++#define CAP324_WMAC_CALDATA_OFFSET 0x1000 ++#define CAP324_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led cap324_leds_gpio[] __initdata = { ++ { ++ .name = "pcs:green:power", ++ .gpio = CAP324_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:amber:power", ++ .gpio = CAP324_GPIO_LED_POWER_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:green:lan", ++ .gpio = CAP324_GPIO_LED_LAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:amber:lan", ++ .gpio = CAP324_GPIO_LED_LAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:green:wlan", ++ .gpio = CAP324_GPIO_LED_WLAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:amber:wlan", ++ .gpio = CAP324_GPIO_LED_WLAN_AMBER, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button cap324_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CAP324_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CAP324_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init cap324_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ ath79_gpio_output_select(CAP324_GPIO_LED_LAN_GREEN, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(CAP324_GPIO_LED_LAN_AMBER, ++ AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cap324_leds_gpio), ++ cap324_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, CAP324_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cap324_gpio_keys), ++ cap324_gpio_keys); ++ ++ ath79_init_mac(mac, art + CAP324_MAC_OFFSET, -2); ++ ath79_wmac_disable_2ghz(); ++ ath79_register_wmac(art + CAP324_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_init_mac(mac, art + CAP324_MAC_OFFSET, -1); ++ ap91_pci_init(art + CAP324_PCIE_CALDATA_OFFSET, mac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + CAP324_MAC_OFFSET, 0); ++ ++ /* GMAC0 is connected to an external PHY */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CAP324, "CAP324", "PowerCloud Systems CAP324", ++ cap324_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cap4200ag.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cap4200ag.c +new file mode 100644 +index 0000000000..18944c40fa +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cap4200ag.c +@@ -0,0 +1,131 @@ ++/* ++ * Senao CAP4200AG board support ++ * ++ * Copyright (C) 2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define CAP4200AG_GPIO_LED_PWR_GREEN 12 ++#define CAP4200AG_GPIO_LED_PWR_AMBER 13 ++#define CAP4200AG_GPIO_LED_LAN_GREEN 14 ++#define CAP4200AG_GPIO_LED_LAN_AMBER 15 ++#define CAP4200AG_GPIO_LED_WLAN_GREEN 18 ++#define CAP4200AG_GPIO_LED_WLAN_AMBER 19 ++ ++#define CAP4200AG_GPIO_BTN_RESET 17 ++ ++#define CAP4200AG_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define CAP4200AG_KEYS_DEBOUNCE_INTERVAL (3 * CAP4200AG_KEYS_POLL_INTERVAL) ++ ++#define CAP4200AG_MAC_OFFSET 0 ++#define CAP4200AG_WMAC_CALDATA_OFFSET 0x1000 ++#define CAP4200AG_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led cap4200ag_leds_gpio[] __initdata = { ++ { ++ .name = "senao:green:pwr", ++ .gpio = CAP4200AG_GPIO_LED_PWR_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "senao:amber:pwr", ++ .gpio = CAP4200AG_GPIO_LED_PWR_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "senao:green:lan", ++ .gpio = CAP4200AG_GPIO_LED_LAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "senao:amber:lan", ++ .gpio = CAP4200AG_GPIO_LED_LAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "senao:green:wlan", ++ .gpio = CAP4200AG_GPIO_LED_WLAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "senao:amber:wlan", ++ .gpio = CAP4200AG_GPIO_LED_WLAN_AMBER, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button cap4200ag_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CAP4200AG_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CAP4200AG_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init cap4200ag_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ ath79_gpio_output_select(CAP4200AG_GPIO_LED_LAN_GREEN, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(CAP4200AG_GPIO_LED_LAN_AMBER, ++ AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cap4200ag_leds_gpio), ++ cap4200ag_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, CAP4200AG_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cap4200ag_gpio_keys), ++ cap4200ag_gpio_keys); ++ ++ ath79_init_mac(mac, art + CAP4200AG_MAC_OFFSET, -1); ++ ath79_wmac_disable_2ghz(); ++ ath79_register_wmac(art + CAP4200AG_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_init_mac(mac, art + CAP4200AG_MAC_OFFSET, -2); ++ ap91_pci_init(art + CAP4200AG_PCIE_CALDATA_OFFSET, mac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + CAP4200AG_MAC_OFFSET, -2); ++ ++ /* GMAC0 is connected to an external PHY */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CAP4200AG, "CAP4200AG", "Senao CAP4200AG", ++ cap4200ag_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-carambola2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-carambola2.c +new file mode 100644 +index 0000000000..babe101141 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-carambola2.c +@@ -0,0 +1,105 @@ ++/* ++ * 8devices Carambola2 board support ++ * ++ * Copyright (C) 2013 Darius Augulis ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define CARAMBOLA2_GPIO_LED_WLAN 0 ++#define CARAMBOLA2_GPIO_LED_ETH0 14 ++#define CARAMBOLA2_GPIO_LED_ETH1 13 ++ ++#define CARAMBOLA2_GPIO_BTN_JUMPSTART 11 ++ ++#define CARAMBOLA2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define CARAMBOLA2_KEYS_DEBOUNCE_INTERVAL (3 * CARAMBOLA2_KEYS_POLL_INTERVAL) ++ ++#define CARAMBOLA2_MAC0_OFFSET 0x0000 ++#define CARAMBOLA2_MAC1_OFFSET 0x0006 ++#define CARAMBOLA2_CALDATA_OFFSET 0x1000 ++#define CARAMBOLA2_WMAC_MAC_OFFSET 0x1002 ++ ++static struct gpio_led carambola2_leds_gpio[] __initdata = { ++ { ++ .name = "carambola2:green:wlan", ++ .gpio = CARAMBOLA2_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "carambola2:orange:eth0", ++ .gpio = CARAMBOLA2_GPIO_LED_ETH0, ++ .active_low = 0, ++ }, { ++ .name = "carambola2:orange:eth1", ++ .gpio = CARAMBOLA2_GPIO_LED_ETH1, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button carambola2_gpio_keys[] __initdata = { ++ { ++ .desc = "jumpstart button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = CARAMBOLA2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CARAMBOLA2_GPIO_BTN_JUMPSTART, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init carambola2_common_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_wmac(art + CARAMBOLA2_CALDATA_OFFSET, ++ art + CARAMBOLA2_WMAC_MAC_OFFSET); ++ ++ ath79_setup_ar933x_phy4_switch(true, true); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + CARAMBOLA2_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + CARAMBOLA2_MAC1_OFFSET, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++} ++ ++static void __init carambola2_setup(void) ++{ ++ carambola2_common_setup(); ++ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(carambola2_leds_gpio), ++ carambola2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, CARAMBOLA2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(carambola2_gpio_keys), ++ carambola2_gpio_keys); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CARAMBOLA2, "CARAMBOLA2", "8devices Carambola2 board", ++ carambola2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cf-e316n-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cf-e316n-v2.c +new file mode 100644 +index 0000000000..82174ba935 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cf-e316n-v2.c +@@ -0,0 +1,765 @@ ++/* ++ * Support for COMFAST boards: ++ * - CF-E316N v2 (AR9341) ++ * - CF-E320N v2 (QCA9531) ++ * - CF-E355AC v1 (QCA9531 + QCA9882) ++ * - CF-E355AC v2 (QCA9531 + QCA9886) ++ * - CF-E375AC (QCA9563 + QCA9886 + QCA8337) ++ * - CF-E380AC v1/v2 (QCA9558) ++ * - CF-E385AC (QCA9558 + QCA9984 + QCA8337) ++ * - CF-E520N/CF-E530N (QCA9531) ++ * ++ * Copyright (C) 2016 Piotr Dymacz ++ * Copyright (C) 2016 Gareth Parker ++ * Copyright (C) 2015 Paul Fertser ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define CF_EXXXN_KEYS_POLL_INTERVAL 20 ++#define CF_EXXXN_KEYS_DEBOUNCE_INTERVAL (3 * CF_EXXXN_KEYS_POLL_INTERVAL) ++ ++/* CF-E316N v2 */ ++#define CF_E316N_V2_GPIO_LED_DIAG_B 0 ++#define CF_E316N_V2_GPIO_LED_DIAG_R 2 ++#define CF_E316N_V2_GPIO_LED_DIAG_G 3 ++#define CF_E316N_V2_GPIO_LED_WLAN 12 ++#define CF_E316N_V2_GPIO_LED_WAN 17 ++#define CF_E316N_V2_GPIO_LED_LAN 19 ++ ++#define CF_E316N_V2_GPIO_EXT_WDT 16 ++ ++#define CF_E316N_V2_GPIO_EXTERNAL_PA0 13 ++#define CF_E316N_V2_GPIO_EXTERNAL_PA1 14 ++ ++#define CF_E316N_V2_GPIO_BTN_RESET 20 ++ ++static struct gpio_led cf_e316n_v2_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e316n-v2:blue:diag", ++ .gpio = CF_E316N_V2_GPIO_LED_DIAG_B, ++ .active_low = 0, ++ }, { ++ .name = "cf-e316n-v2:red:diag", ++ .gpio = CF_E316N_V2_GPIO_LED_DIAG_R, ++ .active_low = 0, ++ }, { ++ .name = "cf-e316n-v2:green:diag", ++ .gpio = CF_E316N_V2_GPIO_LED_DIAG_G, ++ .active_low = 0, ++ }, { ++ .name = "cf-e316n-v2:blue:wlan", ++ .gpio = CF_E316N_V2_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "cf-e316n-v2:blue:wan", ++ .gpio = CF_E316N_V2_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "cf-e316n-v2:blue:lan", ++ .gpio = CF_E316N_V2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button cf_e316n_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CF_EXXXN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CF_E316N_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++/* CF-E320N v2 */ ++#define CF_E320N_V2_GPIO_LED_WLAN 0 ++#define CF_E320N_V2_GPIO_LED_WAN 2 ++#define CF_E320N_V2_GPIO_LED_LAN 3 ++ ++#define CF_E320N_V2_GPIO_HEADER_J9_1 14 ++#define CF_E320N_V2_GPIO_HEADER_J9_2 12 ++#define CF_E320N_V2_GPIO_HEADER_J9_3 11 ++#define CF_E320N_V2_GPIO_HEADER_J9_4 16 ++ ++#define CF_E320N_V2_GPIO_EXT_WDT 13 ++ ++#define CF_E320N_V2_GPIO_BTN_RESET 17 ++ ++static struct gpio_led cf_e320n_v2_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e320n-v2:green:lan", ++ .gpio = CF_E320N_V2_GPIO_LED_LAN, ++ .active_low = 0, ++ }, { ++ .name = "cf-e320n-v2:red:wan", ++ .gpio = CF_E320N_V2_GPIO_LED_WAN, ++ .active_low = 0, ++ }, { ++ .name = "cf-e320n-v2:blue:wlan", ++ .gpio = CF_E320N_V2_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button cf_e320n_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CF_EXXXN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CF_E320N_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++/* CF-E355AC v1/v2 */ ++#define CF_E355AC_GPIO_LED_LAN 3 ++#define CF_E355AC_GPIO_LED_WLAN2G 0 ++#define CF_E355AC_GPIO_LED_WLAN5G 2 ++ ++#define CF_E355AC_GPIO_EXT_WDT 13 ++ ++#define CF_E355AC_GPIO_BTN_RESET 17 ++ ++static struct gpio_led cf_e355ac_v1_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e355ac-v1:green:lan", ++ .gpio = CF_E355AC_GPIO_LED_LAN, ++ .active_low = 0, ++ }, { ++ .name = "cf-e355ac-v1:blue:wlan2g", ++ .gpio = CF_E355AC_GPIO_LED_WLAN2G, ++ .active_low = 0, ++ }, { ++ .name = "cf-e355ac-v1:red:wlan5g", ++ .gpio = CF_E355AC_GPIO_LED_WLAN5G, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_led cf_e355ac_v2_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e355ac-v2:green:lan", ++ .gpio = CF_E355AC_GPIO_LED_LAN, ++ .active_low = 0, ++ }, { ++ .name = "cf-e355ac-v2:blue:wlan2g", ++ .gpio = CF_E355AC_GPIO_LED_WLAN2G, ++ .active_low = 0, ++ }, { ++ .name = "cf-e355ac-v2:red:wlan5g", ++ .gpio = CF_E355AC_GPIO_LED_WLAN5G, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button cf_e355ac_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CF_EXXXN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CF_E355AC_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++/* CF-E375AC */ ++#define CF_E375AC_GPIO_LED_LAN 17 ++#define CF_E375AC_GPIO_LED_WLAN2G 16 ++#define CF_E375AC_GPIO_LED_WLAN5G 15 ++ ++#define CF_E375AC_GPIO_EXT_WDT 6 ++ ++#define CF_E375AC_GPIO_BTN_RESET 2 ++ ++static struct gpio_led cf_e375ac_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e375ac:green:lan", ++ .gpio = CF_E375AC_GPIO_LED_LAN, ++ .active_low = 0, ++ }, { ++ .name = "cf-e375ac:red:wlan5g", ++ .gpio = CF_E375AC_GPIO_LED_WLAN5G, ++ .active_low = 0, ++ }, { ++ .name = "cf-e375ac:blue:wlan2g", ++ .gpio = CF_E375AC_GPIO_LED_WLAN2G, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button cf_e375ac_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CF_EXXXN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CF_E375AC_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg cf_e375ac_ar8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data cf_e375ac_ar8337_data = { ++ .pad0_cfg = &cf_e375ac_ar8337_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info cf_e375ac_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &cf_e375ac_ar8337_data, ++ }, ++}; ++ ++/* CF-E380AC v1/v2, CF-E385AC */ ++#define CF_E38XAC_GPIO_LED_LAN 0 ++#define CF_E38XAC_GPIO_LED_WLAN2G 2 ++#define CF_E38XAC_GPIO_LED_WLAN5G 3 ++ ++#define CF_E38XAC_GPIO_EXT_WDT 17 ++ ++#define CF_E38XAC_GPIO_BTN_RESET 19 ++ ++static struct gpio_led cf_e380ac_v1_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e380ac-v1:green:lan", ++ .gpio = CF_E38XAC_GPIO_LED_LAN, ++ .active_low = 0, ++ }, { ++ .name = "cf-e380ac-v1:blue:wlan2g", ++ .gpio = CF_E38XAC_GPIO_LED_WLAN2G, ++ .active_low = 0, ++ }, { ++ .name = "cf-e380ac-v1:red:wlan5g", ++ .gpio = CF_E38XAC_GPIO_LED_WLAN5G, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_led cf_e380ac_v2_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e380ac-v2:green:lan", ++ .gpio = CF_E38XAC_GPIO_LED_LAN, ++ .active_low = 0, ++ }, { ++ .name = "cf-e380ac-v2:blue:wlan2g", ++ .gpio = CF_E38XAC_GPIO_LED_WLAN2G, ++ .active_low = 0, ++ }, { ++ .name = "cf-e380ac-v2:red:wlan5g", ++ .gpio = CF_E38XAC_GPIO_LED_WLAN5G, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_led cf_e385ac_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e385ac:green:lan", ++ .gpio = CF_E38XAC_GPIO_LED_LAN, ++ .active_low = 0, ++ }, { ++ .name = "cf-e385ac:blue:wlan2g", ++ .gpio = CF_E38XAC_GPIO_LED_WLAN2G, ++ .active_low = 0, ++ }, { ++ .name = "cf-e385ac:red:wlan5g", ++ .gpio = CF_E38XAC_GPIO_LED_WLAN5G, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button cf_e38xac_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CF_EXXXN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CF_E38XAC_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct at803x_platform_data cf_e380ac_v1v2_at803x_data = { ++ .disable_smarteee = 1, ++}; ++ ++static struct mdio_board_info cf_e380ac_v1v2_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &cf_e380ac_v1v2_at803x_data, ++ }, ++}; ++ ++/* CF-E520N/CF-E530N */ ++#define CF_E5X0N_GPIO_LED_WAN 11 ++#define CF_E5X0N_GPIO_BTN_RESET 17 ++ ++static struct gpio_led cf_e520n_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e520n:blue:wan", ++ .gpio = CF_E5X0N_GPIO_LED_WAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led cf_e530n_leds_gpio[] __initdata = { ++ { ++ .name = "cf-e530n:blue:wan", ++ .gpio = CF_E5X0N_GPIO_LED_WAN, ++ .active_low = 1, ++ } ++}; ++ ++/* ++ * Some COMFAST devices include external hardware watchdog chip, ++ * Pericon Technology PT7A7514, connected to a selected GPIO ++ * and WiSoC RESET_L input. Watchdog time-out is ~1.6 s. ++ */ ++#define CF_EXXXN_EXT_WDT_TIMEOUT_MS 500 ++ ++static struct timer_list gpio_wdt_timer; ++ ++static void gpio_wdt_toggle(unsigned long gpio) ++{ ++ static int state; ++ ++ state = !state; ++ gpio_set_value(gpio, state); ++ ++ mod_timer(&gpio_wdt_timer, ++ jiffies + msecs_to_jiffies(CF_EXXXN_EXT_WDT_TIMEOUT_MS)); ++} ++ ++static void __init cf_exxxn_common_setup(unsigned long art_ofs, int gpio_wdt) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f001000 + art_ofs); ++ ++ if (gpio_wdt > -1) { ++ gpio_request_one(gpio_wdt, GPIOF_OUT_INIT_HIGH, ++ "PT7A7514 watchdog"); ++ ++ setup_timer(&gpio_wdt_timer, gpio_wdt_toggle, gpio_wdt); ++ gpio_wdt_toggle(gpio_wdt); ++ } ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_wmac(art, NULL); ++ ++ ath79_register_usb(); ++} ++ ++static void __init cf_e316n_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f010000); ++ ++ cf_exxxn_common_setup(0x10000, CF_E316N_V2_GPIO_EXT_WDT); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 2); ++ ath79_register_eth(1); ++ ++ /* Enable 2x Skyworks SE2576L WLAN power amplifiers */ ++ gpio_request_one(CF_E316N_V2_GPIO_EXTERNAL_PA0, GPIOF_OUT_INIT_HIGH, ++ "WLAN PA0"); ++ gpio_request_one(CF_E316N_V2_GPIO_EXTERNAL_PA1, GPIOF_OUT_INIT_HIGH, ++ "WLAN PA1"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e316n_v2_leds_gpio), ++ cf_e316n_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, CF_EXXXN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cf_e316n_v2_gpio_keys), ++ cf_e316n_v2_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E316N_V2, "CF-E316N-V2", "COMFAST CF-E316N v2", ++ cf_e316n_v2_setup); ++ ++static void __init cf_exxxn_qca953x_eth_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f010000); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 2); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++} ++ ++static void __init cf_e320n_v2_setup(void) ++{ ++ cf_exxxn_common_setup(0x10000, CF_E320N_V2_GPIO_EXT_WDT); ++ ++ cf_exxxn_qca953x_eth_setup(); ++ ++ /* Disable JTAG (enables GPIO0-3) */ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_gpio_direction_select(CF_E320N_V2_GPIO_LED_LAN, true); ++ ath79_gpio_direction_select(CF_E320N_V2_GPIO_LED_WAN, true); ++ ath79_gpio_direction_select(CF_E320N_V2_GPIO_LED_WLAN, true); ++ ++ ath79_gpio_output_select(CF_E320N_V2_GPIO_LED_LAN, 0); ++ ath79_gpio_output_select(CF_E320N_V2_GPIO_LED_WAN, 0); ++ ath79_gpio_output_select(CF_E320N_V2_GPIO_LED_WLAN, 0); ++ ++ /* Enable GPIO function for GPIOs in J9 header */ ++ ath79_gpio_output_select(CF_E320N_V2_GPIO_HEADER_J9_1, 0); ++ ath79_gpio_output_select(CF_E320N_V2_GPIO_HEADER_J9_2, 0); ++ ath79_gpio_output_select(CF_E320N_V2_GPIO_HEADER_J9_3, 0); ++ ath79_gpio_output_select(CF_E320N_V2_GPIO_HEADER_J9_4, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e320n_v2_leds_gpio), ++ cf_e320n_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, CF_EXXXN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cf_e320n_v2_gpio_keys), ++ cf_e320n_v2_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E320N_V2, "CF-E320N-V2", "COMFAST CF-E320N v2", ++ cf_e320n_v2_setup); ++ ++static void __init cf_e355ac_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f010000); ++ ++ /* Disable JTAG, enabling GPIOs 0-3 */ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, 0); ++ ++ cf_exxxn_common_setup(0x10000, CF_E355AC_GPIO_EXT_WDT); ++ ++ cf_exxxn_qca953x_eth_setup(); ++ ++ ath79_gpio_output_select(CF_E355AC_GPIO_LED_LAN, 0); ++ ath79_gpio_output_select(CF_E355AC_GPIO_LED_WLAN2G, 0); ++ ath79_gpio_output_select(CF_E355AC_GPIO_LED_WLAN5G, 0); ++ ++ ap91_pci_init(art + 0x5000, NULL); ++ ++ ath79_register_gpio_keys_polled(1, CF_EXXXN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cf_e355ac_gpio_keys), ++ cf_e355ac_gpio_keys); ++} ++ ++static void __init cf_e355ac_v1_setup(void) ++{ ++ cf_e355ac_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e355ac_v1_leds_gpio), ++ cf_e355ac_v1_leds_gpio); ++} ++ ++static void __init cf_e355ac_v2_setup(void) ++{ ++ cf_e355ac_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e355ac_v2_leds_gpio), ++ cf_e355ac_v2_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E355AC, "CF-E355AC-V1", "COMFAST CF-E355AC v1", ++ cf_e355ac_v1_setup); ++ ++MIPS_MACHINE(ATH79_MACH_CF_E355AC_V2, "CF-E355AC-V2", "COMFAST CF-E355AC v2", ++ cf_e355ac_v2_setup); ++ ++static void __init cf_e375ac_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f040000); ++ ++ /* Disable JTAG, enabling GPIOs 0-3 */ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, 0); ++ ++ cf_exxxn_common_setup(0x40000, CF_E375AC_GPIO_EXT_WDT); ++ ++ ath79_gpio_output_select(CF_E375AC_GPIO_LED_LAN, 0); ++ ath79_gpio_output_select(CF_E375AC_GPIO_LED_WLAN2G, 0); ++ ath79_gpio_output_select(CF_E375AC_GPIO_LED_WLAN5G, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e375ac_leds_gpio), ++ cf_e375ac_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, CF_EXXXN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cf_e375ac_gpio_keys), ++ cf_e375ac_gpio_keys); ++ ++ platform_device_register(&ath79_mdio0_device); ++ ++ mdiobus_register_board_info(cf_e375ac_mdio0_info, ++ ARRAY_SIZE(cf_e375ac_mdio0_info)); ++ ++ /* GMAC0 is connected to an AR8337 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E375AC, "CF-E375AC", "COMFAST CF-E375AC", ++ cf_e375ac_setup); ++ ++static void __init cf_e38xac_common_setup(unsigned long art_ofs) ++{ ++ cf_exxxn_common_setup(art_ofs, CF_E38XAC_GPIO_EXT_WDT); ++ ++ ath79_register_pci(); ++ ++ /* Disable JTAG (enables GPIO0-3) */ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_gpio_direction_select(CF_E38XAC_GPIO_LED_LAN, true); ++ ath79_gpio_direction_select(CF_E38XAC_GPIO_LED_WLAN2G, true); ++ ath79_gpio_direction_select(CF_E38XAC_GPIO_LED_WLAN5G, true); ++ ++ ath79_gpio_output_select(CF_E38XAC_GPIO_LED_LAN, 0); ++ ath79_gpio_output_select(CF_E38XAC_GPIO_LED_WLAN2G, 0); ++ ath79_gpio_output_select(CF_E38XAC_GPIO_LED_WLAN5G, 0); ++ ++ /* For J7-4 */ ++ ath79_gpio_function_disable(AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ ath79_register_gpio_keys_polled(-1, CF_EXXXN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cf_e38xac_gpio_keys), ++ cf_e38xac_gpio_keys); ++} ++ ++static void __init cf_e380ac_v1v2_common_setup(unsigned long art_ofs) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f000000 + art_ofs); ++ ++ cf_e38xac_common_setup(art_ofs); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(cf_e380ac_v1v2_mdio0_info, ++ ARRAY_SIZE(cf_e380ac_v1v2_mdio0_info)); ++ ++ /* LAN */ ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_pll_data.pll_1000 = 0xbe000000; ++ ath79_eth0_pll_data.pll_100 = 0xb0000101; ++ ath79_eth0_pll_data.pll_10 = 0xb0001313; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++} ++ ++static void __init cf_e380ac_v1_setup(void) ++{ ++ cf_e380ac_v1v2_common_setup(0x20000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e380ac_v1_leds_gpio), ++ cf_e380ac_v1_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E380AC_V1, "CF-E380AC-V1", "COMFAST CF-E380AC v1", ++ cf_e380ac_v1_setup); ++ ++static void __init cf_e380ac_v2_setup(void) ++{ ++ cf_e380ac_v1v2_common_setup(0x40000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e380ac_v2_leds_gpio), ++ cf_e380ac_v2_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E380AC_V2, "CF-E380AC-V2", "COMFAST CF-E380AC v2", ++ cf_e380ac_v2_setup); ++ ++/* QCA8337 GMAC0 is connected with QCA9558 over RGMII */ ++static struct ar8327_pad_cfg cf_e385ac_qca8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++}; ++ ++/* QCA8337 GMAC6 is connected with QCA9558 over SGMII */ ++static struct ar8327_pad_cfg cf_e385ac_qca8337_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++}; ++ ++static struct ar8327_platform_data cf_e385ac_qca8337_data = { ++ .pad0_cfg = &cf_e385ac_qca8337_pad0_cfg, ++ .pad6_cfg = &cf_e385ac_qca8337_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info cf_e385ac_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &cf_e385ac_qca8337_data, ++ }, ++}; ++ ++static void __init cf_e385ac_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f040000); ++ ++ cf_e38xac_common_setup(0x40000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e385ac_leds_gpio), ++ cf_e385ac_leds_gpio); ++ ++ mdiobus_register_board_info(cf_e385ac_mdio0_info, ++ ARRAY_SIZE(cf_e385ac_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* QCA9558 GMAC0 is connected to RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x96000000; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ /* QCA9558 GMAC1 is connected to SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E385AC, "CF-E385AC", "COMFAST CF-E385AC", ++ cf_e385ac_setup); ++ ++static void __init cf_e5x0n_gpio_setup(void) ++{ ++ ath79_gpio_direction_select(CF_E5X0N_GPIO_LED_WAN, true); ++ ++ ath79_gpio_output_select(CF_E5X0N_GPIO_LED_WAN, 0); ++ ++ ath79_register_gpio_keys_polled(-1, CF_EXXXN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cf_e320n_v2_gpio_keys), ++ cf_e320n_v2_gpio_keys); ++} ++ ++static void __init cf_e520n_setup(void) ++{ ++ cf_exxxn_common_setup(0x10000, -1); ++ ++ cf_exxxn_qca953x_eth_setup(); ++ ++ cf_e5x0n_gpio_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e520n_leds_gpio), ++ cf_e520n_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E520N, "CF-E520N", "COMFAST CF-E520N", ++ cf_e520n_setup); ++ ++static void __init cf_e530n_setup(void) ++{ ++ cf_exxxn_common_setup(0x10000, -1); ++ ++ cf_exxxn_qca953x_eth_setup(); ++ ++ cf_e5x0n_gpio_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cf_e530n_leds_gpio), ++ cf_e530n_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CF_E530N, "CF-E530N", "COMFAST CF-E530N", ++ cf_e530n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c +new file mode 100644 +index 0000000000..49d9cf9bb5 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c +@@ -0,0 +1,281 @@ ++/* ++ * TP-LINK CPE210/210 v2/220/510/520 board support ++ * ++ * Copyright (C) 2014 Matthias Schiffer ++ * Copyright (C) 2017 Robert Marko ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++#define CPE510_GPIO_LED_LAN0 11 ++#define CPE510_GPIO_LED_LAN1 12 ++#define CPE510_GPIO_LED_L1 13 ++#define CPE510_GPIO_LED_L2 14 ++#define CPE510_GPIO_LED_L3 15 ++#define CPE510_GPIO_LED_L4 16 ++ ++/* All LEDs/button except for link4 are the same for CPE and WBS series */ ++#define WBS510_GPIO_LED_L4 2 ++ ++#define CPE510_GPIO_EXTERNAL_LNA0 18 ++#define CPE510_GPIO_EXTERNAL_LNA1 19 ++ ++#define CPE510_GPIO_BTN_RESET 4 ++ ++#define CPE510_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define CPE510_KEYS_DEBOUNCE_INTERVAL (3 * CPE510_KEYS_POLL_INTERVAL) ++ ++/* CPE210 v2 reset GPIO */ ++#define CPE210_V2_GPIO_BTN_RESET 17 ++ ++static struct gpio_led cpe510_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan0", ++ .gpio = CPE510_GPIO_LED_LAN0, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan1", ++ .gpio = CPE510_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link1", ++ .gpio = CPE510_GPIO_LED_L1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link2", ++ .gpio = CPE510_GPIO_LED_L2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link3", ++ .gpio = CPE510_GPIO_LED_L3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link4", ++ .gpio = CPE510_GPIO_LED_L4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led wbs510_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan0", ++ .gpio = CPE510_GPIO_LED_LAN0, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan1", ++ .gpio = CPE510_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link1", ++ .gpio = CPE510_GPIO_LED_L1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link2", ++ .gpio = CPE510_GPIO_LED_L2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link3", ++ .gpio = CPE510_GPIO_LED_L3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link4", ++ .gpio = WBS510_GPIO_LED_L4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led cpe210_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan0", ++ .gpio = CPE510_GPIO_LED_LAN0, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link1", ++ .gpio = CPE510_GPIO_LED_L1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link2", ++ .gpio = CPE510_GPIO_LED_L2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link3", ++ .gpio = CPE510_GPIO_LED_L3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link4", ++ .gpio = CPE510_GPIO_LED_L4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button cpe510_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CPE510_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CPE510_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button cpe210_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CPE510_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CPE210_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init cpe_setup(u8 *mac) ++{ ++ /* Disable JTAG, enabling GPIOs 0-3 */ ++ /* Configure OBS4 line, for GPIO 4*/ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, ++ AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ ath79_register_gpio_keys_polled(1, CPE510_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cpe510_gpio_keys), ++ cpe510_gpio_keys); ++ ++ ath79_wmac_set_ext_lna_gpio(0, CPE510_GPIO_EXTERNAL_LNA0); ++ ath79_wmac_set_ext_lna_gpio(1, CPE510_GPIO_EXTERNAL_LNA1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++} ++ ++ ++static void __init cpe210_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f830008); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe510_leds_gpio), ++ cpe510_leds_gpio); ++ ++ cpe_setup(mac); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init cpe510_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f830008); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe510_leds_gpio), ++ cpe510_leds_gpio); ++ ++ cpe_setup(mac); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init wbs_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f830008); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wbs510_leds_gpio), ++ wbs510_leds_gpio); ++ ++ cpe_setup(mac); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init cpe210_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f830008); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe210_v2_leds_gpio), ++ cpe210_v2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, CPE510_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cpe210_v2_gpio_keys), ++ cpe210_v2_gpio_keys); ++ ath79_register_m25p80(NULL); ++ ath79_register_mdio(0, 0x0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init cpe510_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f830008); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe210_v2_leds_gpio), ++ cpe210_v2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, CPE510_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cpe510_gpio_keys), ++ cpe510_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_mdio(1, 0x0); ++ ++ /* LAN port */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CPE210, "CPE210", "TP-LINK CPE210/220", ++ cpe210_setup); ++ ++MIPS_MACHINE(ATH79_MACH_CPE210_V2, "CPE210V2", "TP-LINK CPE210 v2", ++ cpe210_v2_setup); ++ ++MIPS_MACHINE(ATH79_MACH_CPE210_V3, "CPE210V3", "TP-LINK CPE210 v3", ++ cpe210_v2_setup); ++ ++MIPS_MACHINE(ATH79_MACH_CPE510, "CPE510", "TP-LINK CPE510/520", ++ cpe510_setup); ++ ++MIPS_MACHINE(ATH79_MACH_CPE510_V2, "CPE510V2", "TP-LINK CPE510 v2", ++ cpe510_v2_setup); ++ ++MIPS_MACHINE(ATH79_MACH_WBS210, "WBS210", "TP-LINK WBS210", ++ wbs_setup); ++ ++MIPS_MACHINE(ATH79_MACH_WBS510, "WBS510", "TP-LINK WBS510", ++ wbs_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe870.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe870.c +new file mode 100644 +index 0000000000..284cdc71c2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe870.c +@@ -0,0 +1,152 @@ ++/* ++ * YunCore CPE870 board support ++ * ++ * Copyright (C) 2016 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define CPE870_GPIO_LED_LINK1 0 ++#define CPE870_GPIO_LED_LINK2 1 ++#define CPE870_GPIO_LED_LINK3 2 ++#define CPE870_GPIO_LED_LINK4 3 ++#define CPE870_GPIO_LED_WLAN 13 ++#define CPE870_GPIO_LED_WAN 19 ++#define CPE870_GPIO_LED_LAN 20 ++ ++#define CPE870_GPIO_BTN_RESET 16 ++ ++#define CPE870_KEYS_POLL_INTERVAL 20 ++#define CPE870_KEYS_DEBOUNCE_INTERVAL (3 * CPE870_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led cpe870_leds_gpio[] __initdata = { ++ { ++ .name = "cpe870:green:lan", ++ .gpio = CPE870_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe870:green:wan", ++ .gpio = CPE870_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe870:green:wlan", ++ .gpio = CPE870_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe870:green:link1", ++ .gpio = CPE870_GPIO_LED_LINK1, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe870:green:link2", ++ .gpio = CPE870_GPIO_LED_LINK2, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe870:green:link3", ++ .gpio = CPE870_GPIO_LED_LINK3, ++ .active_low = 1, ++ }, ++ { ++ .name = "cpe870:green:link4", ++ .gpio = CPE870_GPIO_LED_LINK4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button cpe870_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CPE870_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CPE870_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init cpe870_gpio_setup(void) ++{ ++ /* Disable JTAG (enables GPIO0-3) */ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_gpio_direction_select(CPE870_GPIO_LED_LINK1, true); ++ ath79_gpio_direction_select(CPE870_GPIO_LED_LINK2, true); ++ ath79_gpio_direction_select(CPE870_GPIO_LED_LINK3, true); ++ ath79_gpio_direction_select(CPE870_GPIO_LED_LINK4, true); ++ ++ /* Mute LEDs on boot */ ++ gpio_set_value(CPE870_GPIO_LED_LAN, 1); ++ gpio_set_value(CPE870_GPIO_LED_WAN, 1); ++ gpio_set_value(CPE870_GPIO_LED_LINK1, 1); ++ gpio_set_value(CPE870_GPIO_LED_LINK2, 1); ++ gpio_set_value(CPE870_GPIO_LED_LINK3, 1); ++ gpio_set_value(CPE870_GPIO_LED_LINK4, 1); ++ ++ ath79_gpio_output_select(CPE870_GPIO_LED_LINK1, 0); ++ ath79_gpio_output_select(CPE870_GPIO_LED_LINK2, 0); ++ ath79_gpio_output_select(CPE870_GPIO_LED_LINK3, 0); ++ ath79_gpio_output_select(CPE870_GPIO_LED_LINK4, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe870_leds_gpio), ++ cpe870_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, CPE870_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cpe870_gpio_keys), ++ cpe870_gpio_keys); ++} ++ ++static void __init cpe870_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ cpe870_gpio_setup(); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CPE870, "CPE870", "YunCore CPE870", cpe870_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cr3000.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cr3000.c +new file mode 100644 +index 0000000000..235b0ec769 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cr3000.c +@@ -0,0 +1,168 @@ ++/* ++ * PowerCloud Systems CR3000 support ++ * ++ * Copyright (c) 2011 Qualcomm Atheros ++ * Copyright (c) 2011-2012 Gabor Juhos ++ * Copyright (c) 2012-2013 PowerCloud Systems ++ * Copyright (c) 2015 Daniel Dickinson ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define CR3000_GPIO_LED_WLAN_2G 13 ++#define CR3000_GPIO_LED_POWER_AMBER 15 ++#define CR3000_GPIO_LED_WAN 18 ++#define CR3000_GPIO_LED_LAN1 19 ++#define CR3000_GPIO_LED_LAN2 20 ++#define CR3000_GPIO_LED_LAN3 21 ++#define CR3000_GPIO_LED_LAN4 22 ++ ++#define CR3000_GPIO_BTN_WPS 16 ++#define CR3000_GPIO_BTN_RESET 17 ++ ++#define CR3000_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define CR3000_KEYS_DEBOUNCE_INTERVAL (3 * CR3000_KEYS_POLL_INTERVAL) ++ ++#define CR3000_MAC0_OFFSET 0 ++#define CR3000_MAC1_OFFSET 6 ++#define CR3000_WMAC_CALDATA_OFFSET 0x1000 ++#define CR3000_WMAC_MAC_OFFSET 0x1002 ++ ++static struct gpio_led cr3000_leds_gpio[] __initdata = { ++ { ++ .name = "pcs:amber:power", ++ .gpio = CR3000_GPIO_LED_POWER_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:blue:wlan", ++ .gpio = CR3000_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:blue:wan", ++ .gpio = CR3000_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:blue:lan1", ++ .gpio = CR3000_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:blue:lan2", ++ .gpio = CR3000_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:blue:lan3", ++ .gpio = CR3000_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:blue:lan4", ++ .gpio = CR3000_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button cr3000_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = CR3000_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CR3000_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = CR3000_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CR3000_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init cr3000_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cr3000_leds_gpio), ++ cr3000_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, CR3000_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cr3000_gpio_keys), ++ cr3000_gpio_keys); ++ ++ /* WLAN 2GHz onboard */ ++ ath79_register_wmac(art + CR3000_WMAC_CALDATA_OFFSET, art + CR3000_WMAC_MAC_OFFSET); ++ ++ /* FE Lan on first 4-ports of internal switch and attached to GMAC1 ++ * WAN Fast Ethernet interface attached to GMAC0 ++ * Could be configured as a 5-port switch, but we use ++ * the SoC capabilities to attach port 5 to a separate PHY/MAC ++ * theoretically this leaves future possibility of using SoC ++ * acceleration/offloading. ++ */ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ /* GMAC0 attached to PHY4 (port 5 of the internal switch) */ ++ ath79_switch_data.phy4_mii_en = 1; ++ /* For switch carrier ignore port 5 (wan) */ ++ ath79_switch_data.phy_poll_mask = 0x1; ++ ++ /* Register MII bus */ ++ ath79_register_mdio(1, 0x0); ++ ++ /* GMAC0 attached to PHY4 (port 5 of the internal switch) */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = 0x1; ++ ++ /* LAN */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + CR3000_MAC0_OFFSET, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ /* Wan */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + CR3000_MAC0_OFFSET, 1); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CR3000, "CR3000", "PowerCloud Systems CR3000", ++ cr3000_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cr5000.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cr5000.c +new file mode 100644 +index 0000000000..7c41e7fbc0 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cr5000.c +@@ -0,0 +1,179 @@ ++/* ++ * PowerCloud Systems CR5000 support ++ * ++ * Copyright (c) 2011 Qualcomm Atheros ++ * Copyright (c) 2011-2012 Gabor Juhos ++ * Copyright (c) 2012-2013 PowerCloud Systems ++ * Copyright (c) 2015 Daniel Dickinson ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define CR5000_GPIO_LED_WLAN_2G 14 ++#define CR5000_GPIO_LED_WPS 12 ++#define CR5000_GPIO_LED_POWER_AMBER 4 ++/* GPIO2 has to have JTAG disabled as it is also to ++ * power led ++ */ ++#define CR5000_GPIO_LED_POWER_ENABLE 2 ++#define CR5000_GPIO_BTN_WPS 16 ++#define CR5000_GPIO_BTN_RESET 17 ++ ++#define CR5000_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define CR5000_KEYS_DEBOUNCE_INTERVAL (3 * CR5000_KEYS_POLL_INTERVAL) ++ ++#define CR5000_MAC0_OFFSET 0 ++#define CR5000_WMAC_CALDATA_OFFSET 0x1000 ++#define CR5000_WMAC_MAC_OFFSET 0x1002 ++#define CR5000_PCIE_CALDATA_OFFSET 0x5000 ++#define CR5000_PCIE_WMAC_OFFSET 0x5002 ++ ++static struct gpio_led cr5000_leds_gpio[] __initdata = { ++ { ++ .name = "pcs:amber:power", ++ .gpio = CR5000_GPIO_LED_POWER_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:white:wps", ++ .gpio = CR5000_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "pcs:blue:wlan", ++ .gpio = CR5000_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button cr5000_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = CR5000_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CR5000_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CR5000_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CR5000_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg cr5000_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg cr5000_ar8327_led_cfg = { ++ .led_ctrl0 = 0xcc35cc35, ++ .led_ctrl1 = 0xca35ca35, ++ .led_ctrl2 = 0xc935c935, ++ .led_ctrl3 = 0x03ffff00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data cr5000_ar8327_data = { ++ .pad0_cfg = &cr5000_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &cr5000_ar8327_led_cfg, ++}; ++ ++static struct mdio_board_info cr5000_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &cr5000_ar8327_data, ++ }, ++}; ++ ++static void __init cr5000_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ struct ath9k_platform_data *pdata; ++ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ gpio_request_one(CR5000_GPIO_LED_POWER_ENABLE, ++ GPIOF_OUT_INIT_LOW, "Power LED enable"); ++ ath79_gpio_output_select(CR5000_GPIO_LED_POWER_AMBER, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(CR5000_GPIO_LED_WLAN_2G, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(CR5000_GPIO_LED_WPS, AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cr5000_leds_gpio), ++ cr5000_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, CR5000_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cr5000_gpio_keys), ++ cr5000_gpio_keys); ++ ath79_register_usb(); ++ ath79_register_wmac(art + CR5000_WMAC_CALDATA_OFFSET, art + CR5000_WMAC_MAC_OFFSET); ++ ap91_pci_init(NULL, art + CR5000_PCIE_WMAC_OFFSET); ++ pdata = ap9x_pci_get_wmac_data(0); ++ if (pdata) ++ pdata->use_eeprom = true; ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + CR5000_MAC0_OFFSET, 0); ++ ++ mdiobus_register_board_info(cr5000_mdio0_info, ++ ARRAY_SIZE(cr5000_mdio0_info)); ++ ++ /* GMAC0 is connected to an AR8327 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CR5000, "CR5000", "PowerCloud Systems CR5000", ++ cr5000_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dap-1330-a1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dap-1330-a1.c +new file mode 100644 +index 0000000000..9c50bc7e9b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dap-1330-a1.c +@@ -0,0 +1,146 @@ ++/* ++ * D-Link DAP-1330 ++ * ++ * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2017 Nicolò Veronese ++ * Copyright (c) 2017 Federico Cappon ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define DAP_1330_GPIO_LED_GREEN_POWER 13 ++#define DAP_1330_GPIO_LED_RED_POWER 3 ++#define DAP_1330_GPIO_LED_GREEN_WIFI 14 ++#define DAP_1330_GPIO_LED_RED_WIFI 11 ++#define DAP_1330_GPIO_LED_SIGNAL1 15 ++#define DAP_1330_GPIO_LED_SIGNAL2 16 ++ ++#define DAP_1330_GPIO_BTN_WPS 2 ++#define DAP_1330_GPIO_BTN_RESET 17 ++ ++#define DAP_1330_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DAP_1330_KEYS_DEBOUNCE_INTERVAL (3 * DAP_1330_KEYS_POLL_INTERVAL) ++ ++#define DAP1330_MAC_ADDR 0x1f020001 ++ ++#define DAP1330_WMAC_CALDATA_ADDR 0x1f010000 ++#define DAP_1330_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led dap_1330_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:green:power", ++ .gpio = DAP_1330_GPIO_LED_GREEN_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:red:power", ++ .gpio = DAP_1330_GPIO_LED_RED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:wifi", ++ .gpio = DAP_1330_GPIO_LED_GREEN_WIFI, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:red:wifi", ++ .gpio = DAP_1330_GPIO_LED_RED_WIFI, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:signal1", ++ .gpio = DAP_1330_GPIO_LED_SIGNAL1, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:signal2", ++ .gpio = DAP_1330_GPIO_LED_SIGNAL2, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button dap_1330_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DAP_1330_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DAP_1330_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DAP_1330_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DAP_1330_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init dap_1330_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(DAP1330_WMAC_CALDATA_ADDR); ++ u8 *mac_ptr = (u8 *) KSEG1ADDR(DAP1330_MAC_ADDR); ++ u8 mac[ETH_ALEN]; ++ ++ ath79_parse_ascii_mac((char *) mac_ptr, mac); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dap_1330_leds_gpio), ++ dap_1330_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DAP_1330_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dap_1330_gpio_keys), ++ dap_1330_gpio_keys); ++ ++ ath79_register_wmac(art + DAP_1330_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DAP_1330_A1, "DAP-1330-A1", ++ "D-Link DAP-1330 Rev. A1", dap_1330_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dap-2695-a1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dap-2695-a1.c +new file mode 100644 +index 0000000000..2577dbffae +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dap-2695-a1.c +@@ -0,0 +1,191 @@ ++/* ++ * D-Link DAP-2695 rev. A1 support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * Copyright (c) 2016 Stijn Tintel ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define DAP2695_GPIO_LED_GREEN_POWER 23 ++#define DAP2695_GPIO_LED_RED_POWER 14 ++#define DAP2695_GPIO_LED_WLAN_2G 13 ++ ++#define DAP2695_GPIO_BTN_RESET 17 ++ ++#define DAP2695_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DAP2695_KEYS_DEBOUNCE_INTERVAL (3 * DAP2695_KEYS_POLL_INTERVAL) ++ ++#define DAP2695_NVRAM_ADDR 0x1f040000 ++#define DAP2695_NVRAM_SIZE 0x10000 ++ ++#define DAP2695_MAC0_OFFSET 1 ++#define DAP2695_MAC1_OFFSET 2 ++#define DAP2695_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led dap2695_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:green:power", ++ .gpio = DAP2695_GPIO_LED_GREEN_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:red:power", ++ .gpio = DAP2695_GPIO_LED_RED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:wlan2g", ++ .gpio = DAP2695_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button dap2695_gpio_keys[] __initdata = { ++ { ++ .desc = "Soft reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DAP2695_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DAP2695_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg dap2695_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++ .mac06_exchange_dis = true, ++}; ++ ++static struct ar8327_pad_cfg dap2695_ar8327_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data dap2695_ar8327_data = { ++ .pad0_cfg = &dap2695_ar8327_pad0_cfg, ++ .pad6_cfg = &dap2695_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info dap2695_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dap2695_ar8327_data, ++ }, ++}; ++ ++static struct flash_platform_data dap2695_flash_data = { ++ .type = "mx25l12805d", ++}; ++ ++static void dap2695_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(DAP2695_NVRAM_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, DAP2695_NVRAM_SIZE, ++ name, mac); ++ if (err) ++ pr_err("no MAC address found for %s\n", name); ++} ++ ++static void __init dap2695_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 mac0[ETH_ALEN], mac1[ETH_ALEN], wmac0[ETH_ALEN]; ++ ++ dap2695_get_mac("lanmac=", mac0); ++ dap2695_get_mac("wanmac=", mac1); ++ dap2695_get_mac("wlanmac=", wmac0); ++ ++ ath79_register_m25p80(&dap2695_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dap2695_leds_gpio), ++ dap2695_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DAP2695_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dap2695_gpio_keys), ++ dap2695_gpio_keys); ++ ++ ath79_register_wmac(art + DAP2695_WMAC_CALDATA_OFFSET, wmac0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(dap2695_mdio0_info, ++ ARRAY_SIZE(dap2695_mdio0_info)); ++ ++ /* GMAC0 is connected to the RGMII interface */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac0, DAP2695_MAC0_OFFSET); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac1, DAP2695_MAC1_OFFSET); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DAP_2695_A1, "DAP-2695-A1", ++ "D-Link DAP-2695 rev. A1", ++ dap2695_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dgl-5500-a1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dgl-5500-a1.c +new file mode 100644 +index 0000000000..f9f3f9e60d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dgl-5500-a1.c +@@ -0,0 +1,150 @@ ++/* ++ * D-Link DGL-5500 board support ++ * ++ * Copyright (C) 2014 Gabor Juhos ++ * Copyright (C) 2014 Imre Kaloz ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DGL_5500_A1_GPIO_LED_POWER_ORANGE 14 ++#define DGL_5500_A1_GPIO_LED_POWER_GREEN 19 ++#define DGL_5500_A1_GPIO_LED_PLANET_GREEN 22 ++#define DGL_5500_A1_GPIO_LED_PLANET_ORANGE 23 ++ ++#define DGL_5500_A1_GPIO_BTN_WPS 16 ++#define DGL_5500_A1_GPIO_BTN_RESET 17 ++ ++#define DGL_5500_A1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DGL_5500_A1_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * DGL_5500_A1_KEYS_POLL_INTERVAL) ++ ++#define DGL_5500_A1_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define DGL_5500_A1_LAN_MAC_OFFSET 0x04 ++#define DGL_5500_A1_WAN_MAC_OFFSET 0x16 ++ ++static struct gpio_led dgl_5500_a1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:green:power", ++ .gpio = DGL_5500_A1_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:orange:power", ++ .gpio = DGL_5500_A1_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:planet", ++ .gpio = DGL_5500_A1_GPIO_LED_PLANET_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:orange:planet", ++ .gpio = DGL_5500_A1_GPIO_LED_PLANET_ORANGE, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button dgl_5500_a1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DGL_5500_A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DGL_5500_A1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DGL_5500_A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DGL_5500_A1_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg dgl_5500_a1_ar8327_pad0_cfg = { ++ /* Use the SGMII interface for the GMAC0 of the AR8327 switch */ ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data dgl_5500_a1_ar8327_data = { ++ .pad0_cfg = &dgl_5500_a1_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info dgl_5500_a1_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dgl_5500_a1_ar8327_data, ++ }, ++}; ++ ++static void __init dgl_5500_a1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1ffe0000); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 lan_mac[ETH_ALEN]; ++ ++ ath79_parse_ascii_mac(mac + DGL_5500_A1_LAN_MAC_OFFSET, lan_mac); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dgl_5500_a1_leds_gpio), ++ dgl_5500_a1_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DGL_5500_A1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dgl_5500_a1_gpio_keys), ++ dgl_5500_a1_gpio_keys); ++ ++ ath79_register_wmac(art + DGL_5500_A1_WMAC_CALDATA_OFFSET, lan_mac); ++ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(dgl_5500_a1_mdio0_info, ++ ARRAY_SIZE(dgl_5500_a1_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, lan_mac, 0); ++ ++ /* GMAC1 is connected to an AR8327N switch via the SMGII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.phy_mask = BIT(0); ++ ath79_eth1_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DGL_5500_A1, "DGL-5500-A1", "D-Link DGL-5500 rev. A1", ++ dgl_5500_a1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dhp-1565-a1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dhp-1565-a1.c +new file mode 100644 +index 0000000000..275d2a29a0 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dhp-1565-a1.c +@@ -0,0 +1,170 @@ ++/* ++ * D-Link DHP-1565 rev. A1 board support ++ * ++ * Copyright (C) 2014 Jacek Kikiewicz ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DHP1565A1_GPIO_LED_BLUE_USB 11 ++#define DHP1565A1_GPIO_LED_AMBER_POWER 14 ++#define DHP1565A1_GPIO_LED_BLUE_POWER 22 ++#define DHP1565A1_GPIO_LED_BLUE_WPS 15 ++#define DHP1565A1_GPIO_LED_AMBER_PLANET 19 ++#define DHP1565A1_GPIO_LED_BLUE_PLANET 18 ++#define DHP1565A1_GPIO_LED_WLAN_2G 13 ++ ++#define DHP1565A1_GPIO_WAN_LED_ENABLE 20 ++ ++#define DHP1565A1_GPIO_BTN_RESET 17 ++#define DHP1565A1_GPIO_BTN_WPS 16 ++ ++#define DHP1565A1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DHP1565A1_KEYS_DEBOUNCE_INTERVAL (3 * DHP1565A1_KEYS_POLL_INTERVAL) ++ ++#define DHP1565A1_MAC0_OFFSET 0xFFA0 ++#define DHP1565A1_MAC1_OFFSET 0xFFB4 ++#define DHP1565A1_WMAC0_OFFSET 0x5 ++#define DHP1565A1_WMAC_CALDATA_OFFSET 0x1000 ++#define DHP1565A1_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led dhp1565a1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:amber:power", ++ .gpio = DHP1565A1_GPIO_LED_AMBER_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:power", ++ .gpio = DHP1565A1_GPIO_LED_BLUE_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:amber:planet", ++ .gpio = DHP1565A1_GPIO_LED_AMBER_PLANET, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:planet", ++ .gpio = DHP1565A1_GPIO_LED_BLUE_PLANET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button dhp1565a1_gpio_keys[] __initdata = { ++ { ++ .desc = "Soft reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DHP1565A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DHP1565A1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DHP1565A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DHP1565A1_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg dhp1565a1_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data dhp1565a1_ar8327_data = { ++ .pad0_cfg = &dhp1565a1_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info dhp1565a1_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dhp1565a1_ar8327_data, ++ }, ++}; ++ ++static void __init dhp1565a1_generic_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1ffe0000); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 mac0[ETH_ALEN], mac1[ETH_ALEN]; ++ u8 wmac0[ETH_ALEN]; ++ ++ ath79_parse_ascii_mac(mac + DHP1565A1_MAC0_OFFSET, mac0); ++ ath79_parse_ascii_mac(mac + DHP1565A1_MAC1_OFFSET, mac1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_gpio_keys_polled(-1, DHP1565A1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dhp1565a1_gpio_keys), ++ dhp1565a1_gpio_keys); ++ ++ ath79_init_mac(wmac0, mac0, 0); ++ ath79_register_wmac(art + DHP1565A1_WMAC_CALDATA_OFFSET, wmac0); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ++ mdiobus_register_board_info(dhp1565a1_mdio0_info, ++ ARRAY_SIZE(dhp1565a1_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac0, 1); ++ ++ /* GMAC0 is connected to an AR8327N switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++ ++ ath79_register_usb(); ++} ++ ++static void __init dhp1565a1_setup(void) ++{ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dhp1565a1_leds_gpio), ++ dhp1565a1_leds_gpio); ++ ++ dhp1565a1_generic_setup(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DHP_1565_A1, "DHP-1565-A1", ++ "D-Link DHP-1565 rev. A1", ++ dhp1565a1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-505-a1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-505-a1.c +new file mode 100644 +index 0000000000..1367b64a8f +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-505-a1.c +@@ -0,0 +1,116 @@ ++/* ++ * DLink DIR-505 A1 board support ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define DIR_505A1_GPIO_BTN_WPS 11 /* verify */ ++#define DIR_505A1_GPIO_BTN_RESET 12 /* verify */ ++ ++#define DIR_505A1_GPIO_LED_RED 26 /* unused, fyi */ ++#define DIR_505A1_GPIO_LED_GREEN 27 ++ ++#define DIR_505A1_GPIO_WAN_LED_ENABLE 1 ++ ++#define DIR_505A1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DIR_505A1_KEYS_DEBOUNCE_INTERVAL (3 * DIR_505A1_KEYS_POLL_INTERVAL) ++ ++#define DIR_505A1_ART_ADDRESS 0x1f010000 ++#define DIR_505A1_CALDATA_OFFSET 0x1000 ++ ++#define DIR_505A1_MAC_PART_ADDRESS 0x1f020000 ++#define DIR_505A1_LAN_MAC_OFFSET 0x04 ++#define DIR_505A1_WAN_MAC_OFFSET 0x16 ++ ++static struct gpio_led dir_505_a1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:green:power", ++ .gpio = DIR_505A1_GPIO_LED_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "d-link:red:status", ++ .gpio = DIR_505A1_GPIO_LED_RED, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button dir_505_a1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DIR_505A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR_505A1_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DIR_505A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR_505A1_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init dir_505_a1_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(DIR_505A1_ART_ADDRESS); ++ u8 *mac = (u8 *) KSEG1ADDR(DIR_505A1_MAC_PART_ADDRESS); ++ u8 lan_mac[ETH_ALEN]; ++ u8 wan_mac[ETH_ALEN]; ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ gpio_request_one(DIR_505A1_GPIO_WAN_LED_ENABLE, ++ GPIOF_OUT_INIT_LOW, "WAN LED enable"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dir_505_a1_leds_gpio), ++ dir_505_a1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, DIR_505A1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dir_505_a1_gpio_keys), ++ dir_505_a1_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_usb(); ++ ++ ath79_parse_ascii_mac(mac + DIR_505A1_LAN_MAC_OFFSET, lan_mac); ++ ath79_parse_ascii_mac(mac + DIR_505A1_WAN_MAC_OFFSET, wan_mac); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, wan_mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, lan_mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art + DIR_505A1_CALDATA_OFFSET, lan_mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_505_A1, "DIR-505-A1", ++ "D-Link DIR-505 rev. A1", dir_505_a1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-600-a1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-600-a1.c +new file mode 100644 +index 0000000000..5e6134de7a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-600-a1.c +@@ -0,0 +1,162 @@ ++/* ++ * D-Link DIR-600 rev. A1 board support ++ * ++ * Copyright (C) 2010-2012 Gabor Juhos ++ * Copyright (C) 2012 Vadim Girlin ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define DIR_600_A1_GPIO_LED_WPS 0 ++#define DIR_600_A1_GPIO_LED_POWER_AMBER 1 ++#define DIR_600_A1_GPIO_LED_POWER_GREEN 6 ++#define DIR_600_A1_GPIO_LED_LAN1 13 ++#define DIR_600_A1_GPIO_LED_LAN2 14 ++#define DIR_600_A1_GPIO_LED_LAN3 15 ++#define DIR_600_A1_GPIO_LED_LAN4 16 ++#define DIR_600_A1_GPIO_LED_WAN_AMBER 7 ++#define DIR_600_A1_GPIO_LED_WAN_GREEN 17 ++ ++#define DIR_600_A1_GPIO_BTN_RESET 8 ++#define DIR_600_A1_GPIO_BTN_WPS 12 ++ ++#define DIR_600_A1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DIR_600_A1_KEYS_DEBOUNCE_INTERVAL (3 * DIR_600_A1_KEYS_POLL_INTERVAL) ++ ++#define DIR_600_A1_NVRAM_ADDR 0x1f030000 ++#define DIR_600_A1_NVRAM_SIZE 0x10000 ++ ++static struct gpio_led dir_600_a1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:green:power", ++ .gpio = DIR_600_A1_GPIO_LED_POWER_GREEN, ++ }, { ++ .name = "d-link:amber:power", ++ .gpio = DIR_600_A1_GPIO_LED_POWER_AMBER, ++ }, { ++ .name = "d-link:amber:wan", ++ .gpio = DIR_600_A1_GPIO_LED_WAN_AMBER, ++ }, { ++ .name = "d-link:green:wan", ++ .gpio = DIR_600_A1_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:lan1", ++ .gpio = DIR_600_A1_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:lan2", ++ .gpio = DIR_600_A1_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:lan3", ++ .gpio = DIR_600_A1_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:lan4", ++ .gpio = DIR_600_A1_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "d-link:blue:wps", ++ .gpio = DIR_600_A1_GPIO_LED_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button dir_600_a1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DIR_600_A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR_600_A1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DIR_600_A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR_600_A1_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init dir_600_a1_setup(void) ++{ ++ const char *nvram = (char *) KSEG1ADDR(DIR_600_A1_NVRAM_ADDR); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac_buff[6]; ++ u8 *mac = NULL; ++ ++ if (ath79_nvram_parse_mac_addr(nvram, DIR_600_A1_NVRAM_SIZE, ++ "lan_mac=", mac_buff) == 0) { ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac_buff, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac_buff, 1); ++ mac = mac_buff; ++ } ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dir_600_a1_leds_gpio), ++ dir_600_a1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DIR_600_A1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dir_600_a1_gpio_keys), ++ dir_600_a1_gpio_keys); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ ap91_pci_init(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_600_A1, "DIR-600-A1", "D-Link DIR-600 rev. A1", ++ dir_600_a1_setup); ++ ++MIPS_MACHINE(ATH79_MACH_EBR_2310_C1, "EBR-2310-C1", "D-Link EBR-2310 rev. C1", ++ dir_600_a1_setup); ++ ++static void __init dir_615_e1_setup(void) ++{ ++ dir_600_a1_setup(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_615_E1, "DIR-615-E1", "D-Link DIR-615 rev. E1", ++ dir_615_e1_setup); ++ ++static void __init dir_615_e4_setup(void) ++{ ++ dir_600_a1_setup(); ++ ap9x_pci_setup_wmac_led_pin(0, 1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_615_E4, "DIR-615-E4", "D-Link DIR-615 rev. E4", ++ dir_615_e4_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-c1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-c1.c +new file mode 100644 +index 0000000000..e55a43f9c7 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-c1.c +@@ -0,0 +1,135 @@ ++/* ++ * D-Link DIR-615 rev C1 board support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define DIR_615C1_GPIO_LED_ORANGE_STATUS 1 /* ORANGE:STATUS:TRICOLOR */ ++#define DIR_615C1_GPIO_LED_BLUE_WPS 3 /* BLUE:WPS */ ++#define DIR_615C1_GPIO_LED_GREEN_WAN 4 /* GREEN:WAN:TRICOLOR */ ++#define DIR_615C1_GPIO_LED_GREEN_WANCPU 5 /* GREEN:WAN:CPU:TRICOLOR */ ++#define DIR_615C1_GPIO_LED_GREEN_WLAN 6 /* GREEN:WLAN */ ++#define DIR_615C1_GPIO_LED_GREEN_STATUS 14 /* GREEN:STATUS:TRICOLOR */ ++#define DIR_615C1_GPIO_LED_ORANGE_WAN 15 /* ORANGE:WAN:TRICOLOR */ ++ ++/* buttons may need refinement */ ++ ++#define DIR_615C1_GPIO_BTN_WPS 12 ++#define DIR_615C1_GPIO_BTN_RESET 21 ++ ++#define DIR_615C1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DIR_615C1_KEYS_DEBOUNCE_INTERVAL (3 * DIR_615C1_KEYS_POLL_INTERVAL) ++ ++#define DIR_615C1_CONFIG_ADDR 0x1f020000 ++#define DIR_615C1_CONFIG_SIZE 0x10000 ++ ++#define DIR_615C1_WLAN_MAC_ADDR 0x1f3fffb4 ++ ++static struct gpio_led dir_615c1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:orange:status", ++ .gpio = DIR_615C1_GPIO_LED_ORANGE_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "d-link:blue:wps", ++ .gpio = DIR_615C1_GPIO_LED_BLUE_WPS, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:wan", ++ .gpio = DIR_615C1_GPIO_LED_GREEN_WAN, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:wancpu", ++ .gpio = DIR_615C1_GPIO_LED_GREEN_WANCPU, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:wlan", ++ .gpio = DIR_615C1_GPIO_LED_GREEN_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:status", ++ .gpio = DIR_615C1_GPIO_LED_GREEN_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "d-link:orange:wan", ++ .gpio = DIR_615C1_GPIO_LED_ORANGE_WAN, ++ .active_low = 1, ++ } ++ ++}; ++ ++static struct gpio_keys_button dir_615c1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DIR_615C1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR_615C1_GPIO_BTN_RESET, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DIR_615C1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR_615C1_GPIO_BTN_WPS, ++ } ++}; ++ ++#define DIR_615C1_LAN_PHYMASK BIT(0) ++#define DIR_615C1_WAN_PHYMASK BIT(4) ++#define DIR_615C1_MDIO_MASK (~(DIR_615C1_LAN_PHYMASK | \ ++ DIR_615C1_WAN_PHYMASK)) ++ ++static void __init dir_615c1_setup(void) ++{ ++ const char *config = (char *) KSEG1ADDR(DIR_615C1_CONFIG_ADDR); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[ETH_ALEN], wlan_mac[ETH_ALEN]; ++ ++ if (ath79_nvram_parse_mac_addr(config, DIR_615C1_CONFIG_SIZE, ++ "lan_mac=", mac) == 0) { ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ } ++ ++ ath79_parse_ascii_mac((char *) KSEG1ADDR(DIR_615C1_WLAN_MAC_ADDR), wlan_mac); ++ ++ ath79_register_mdio(0, DIR_615C1_MDIO_MASK); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.phy_mask = DIR_615C1_LAN_PHYMASK; ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = DIR_615C1_WAN_PHYMASK; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dir_615c1_leds_gpio), ++ dir_615c1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DIR_615C1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dir_615c1_gpio_keys), ++ dir_615c1_gpio_keys); ++ ++ ath79_register_wmac(eeprom, wlan_mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_615_C1, "DIR-615-C1", "D-Link DIR-615 rev. C1", ++ dir_615c1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-i1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-i1.c +new file mode 100644 +index 0000000000..64fe438dcb +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-i1.c +@@ -0,0 +1,133 @@ ++/* ++ * D-Link DIR-615 rev. I1 board support ++ * Copyright (C) 2013-2015 Jaehoon You ++ * ++ * based on the DIR-600 rev. A1 board support code ++ * Copyright (C) 2010-2012 Gabor Juhos ++ * Copyright (C) 2012 Vadim Girlin ++ * ++ * based on the TP-LINK TL-WR841N/ND v8/TL-MR3420 v2 board support code ++ * Copyright (C) 2012 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. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DIR_615_I1_GPIO_LED_WPS 15 ++#define DIR_615_I1_GPIO_LED_POWER_AMBER 14 ++#define DIR_615_I1_GPIO_LED_POWER_GREEN 4 ++#define DIR_615_I1_GPIO_LED_WAN_AMBER 22 ++#define DIR_615_I1_GPIO_LED_WAN_GREEN 12 ++#define DIR_615_I1_GPIO_LED_WLAN_GREEN 13 ++ ++#define DIR_615_I1_GPIO_BTN_WPS 16 ++#define DIR_615_I1_GPIO_BTN_RESET 17 ++ ++#define DIR_615_I1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DIR_615_I1_KEYS_DEBOUNCE_INTERVAL (3 * DIR_615_I1_KEYS_POLL_INTERVAL) ++ ++#define DIR_615_I1_LAN_PHYMASK BIT(0) ++#define DIR_615_I1_WAN_PHYMASK BIT(4) ++#define DIR_615_I1_WLAN_MAC_ADDR 0x1fffffb4 ++ ++static struct gpio_led dir_615_i1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:green:power", ++ .gpio = DIR_615_I1_GPIO_LED_POWER_GREEN, ++ }, { ++ .name = "d-link:amber:power", ++ .gpio = DIR_615_I1_GPIO_LED_POWER_AMBER, ++ }, { ++ .name = "d-link:amber:wan", ++ .gpio = DIR_615_I1_GPIO_LED_WAN_AMBER, ++ }, { ++ .name = "d-link:green:wan", ++ .gpio = DIR_615_I1_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "d-link:green:wlan", ++ .gpio = DIR_615_I1_GPIO_LED_WLAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "d-link:blue:wps", ++ .gpio = DIR_615_I1_GPIO_LED_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button dir_615_i1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DIR_615_I1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR_615_I1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DIR_615_I1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR_615_I1_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init dir_615_i1_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[ETH_ALEN]; ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, ~(DIR_615_I1_WAN_PHYMASK)); ++ ++ ath79_parse_ascii_mac((char *) KSEG1ADDR(DIR_615_I1_WLAN_MAC_ADDR), mac); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = DIR_615_I1_WAN_PHYMASK; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_mask = DIR_615_I1_LAN_PHYMASK; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ /* Disable JTAG, enabling GPIOs 0-3 */ ++ /* Configure OBS4 line, for GPIO 4*/ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, ++ AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dir_615_i1_leds_gpio), ++ dir_615_i1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DIR_615_I1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dir_615_i1_gpio_keys), ++ dir_615_i1_gpio_keys); ++ ++ ath79_register_wmac(eeprom, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_615_I1, "DIR-615-I1", "D-Link DIR-615 rev. I1", ++ dir_615_i1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-b1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-b1.c +new file mode 100644 +index 0000000000..9b82990b13 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-b1.c +@@ -0,0 +1,191 @@ ++/* ++ * D-Link DIR-825 rev. B1 board support ++ * ++ * Copyright (C) 2009-2011 Lukas Kuna, Evkanet, s.r.o. ++ * ++ * based on mach-wndr3700.c ++ * ++ * 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 "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define DIR825B1_GPIO_LED_BLUE_USB 0 ++#define DIR825B1_GPIO_LED_ORANGE_POWER 1 ++#define DIR825B1_GPIO_LED_BLUE_POWER 2 ++#define DIR825B1_GPIO_LED_BLUE_WPS 4 ++#define DIR825B1_GPIO_LED_ORANGE_PLANET 6 ++#define DIR825B1_GPIO_LED_BLUE_PLANET 11 ++ ++#define DIR825B1_GPIO_BTN_RESET 3 ++#define DIR825B1_GPIO_BTN_WPS 8 ++ ++#define DIR825B1_GPIO_RTL8366_SDA 5 ++#define DIR825B1_GPIO_RTL8366_SCK 7 ++ ++#define DIR825B1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DIR825B1_KEYS_DEBOUNCE_INTERVAL (3 * DIR825B1_KEYS_POLL_INTERVAL) ++ ++#define DIR825B1_CAL0_OFFSET 0x1000 ++#define DIR825B1_CAL1_OFFSET 0x5000 ++#define DIR825B1_MAC0_OFFSET 0xffa0 ++#define DIR825B1_MAC1_OFFSET 0xffb4 ++ ++#define DIR825B1_CAL_LOCATION_0 0x1f660000 ++#define DIR825B1_CAL_LOCATION_1 0x1f7f0000 ++ ++static struct gpio_led dir825b1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:blue:usb", ++ .gpio = DIR825B1_GPIO_LED_BLUE_USB, ++ .active_low = 1, ++ }, { ++ .name = "d-link:orange:power", ++ .gpio = DIR825B1_GPIO_LED_ORANGE_POWER, ++ .active_low = 1, ++ }, { ++ .name = "d-link:blue:power", ++ .gpio = DIR825B1_GPIO_LED_BLUE_POWER, ++ .active_low = 1, ++ }, { ++ .name = "d-link:blue:wps", ++ .gpio = DIR825B1_GPIO_LED_BLUE_WPS, ++ .active_low = 1, ++ }, { ++ .name = "d-link:orange:planet", ++ .gpio = DIR825B1_GPIO_LED_ORANGE_PLANET, ++ .active_low = 1, ++ }, { ++ .name = "d-link:blue:planet", ++ .gpio = DIR825B1_GPIO_LED_BLUE_PLANET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button dir825b1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DIR825B1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR825B1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DIR825B1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR825B1_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct rtl8366_initval dir825b1_rtl8366s_initvals[] = { ++ { .reg = 0x06, .val = 0x0108 }, ++}; ++ ++static struct rtl8366_platform_data dir825b1_rtl8366s_data = { ++ .gpio_sda = DIR825B1_GPIO_RTL8366_SDA, ++ .gpio_sck = DIR825B1_GPIO_RTL8366_SCK, ++ .num_initvals = ARRAY_SIZE(dir825b1_rtl8366s_initvals), ++ .initvals = dir825b1_rtl8366s_initvals, ++}; ++ ++static struct platform_device dir825b1_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &dir825b1_rtl8366s_data, ++ } ++}; ++ ++static bool __init dir825b1_is_caldata_valid(u8 *p) ++{ ++ u16 *magic0, *magic1; ++ ++ magic0 = (u16 *)(p + DIR825B1_CAL0_OFFSET); ++ magic1 = (u16 *)(p + DIR825B1_CAL1_OFFSET); ++ ++ return (*magic0 == 0xa55a && *magic1 == 0xa55a); ++} ++ ++static void __init dir825b1_wlan_init(void) ++{ ++ u8 *caldata; ++ u8 mac0[ETH_ALEN], mac1[ETH_ALEN]; ++ u8 wmac0[ETH_ALEN], wmac1[ETH_ALEN]; ++ ++ caldata = (u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_0); ++ if (!dir825b1_is_caldata_valid(caldata)) { ++ caldata = (u8 *)KSEG1ADDR(DIR825B1_CAL_LOCATION_1); ++ if (!dir825b1_is_caldata_valid(caldata)) { ++ pr_err("no calibration data found\n"); ++ return; ++ } ++ } ++ ++ ath79_parse_ascii_mac(caldata + DIR825B1_MAC0_OFFSET, mac0); ++ ath79_parse_ascii_mac(caldata + DIR825B1_MAC1_OFFSET, mac1); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac0, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 0); ++ ath79_init_mac(wmac0, mac0, 0); ++ ath79_init_mac(wmac1, mac1, 1); ++ ++ ap9x_pci_setup_wmac_led_pin(0, 5); ++ ap9x_pci_setup_wmac_led_pin(1, 5); ++ ++ ap94_pci_init(caldata + DIR825B1_CAL0_OFFSET, wmac0, ++ caldata + DIR825B1_CAL1_OFFSET, wmac1); ++} ++ ++static void __init dir825b1_setup(void) ++{ ++ dir825b1_wlan_init(); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_eth0_data.mii_bus_dev = &dir825b1_rtl8366s_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_pll_data.pll_1000 = 0x11110000; ++ ++ ath79_eth1_data.mii_bus_dev = &dir825b1_rtl8366s_device.dev; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ath79_eth1_pll_data.pll_1000 = 0x11110000; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dir825b1_leds_gpio), ++ dir825b1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DIR825B1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dir825b1_gpio_keys), ++ dir825b1_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ platform_device_register(&dir825b1_rtl8366s_device); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_825_B1, "DIR-825-B1", "D-Link DIR-825 rev. B1", ++ dir825b1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-c1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-c1.c +new file mode 100644 +index 0000000000..0d586c27e4 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-825-c1.c +@@ -0,0 +1,241 @@ ++/* ++ * D-Link DIR-825 rev. C1 board support ++ * ++ * Copyright (C) 2013 Alexander Stadler ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DIR825C1_GPIO_LED_BLUE_USB 11 ++#define DIR825C1_GPIO_LED_AMBER_POWER 14 ++#define DIR825C1_GPIO_LED_BLUE_POWER 22 ++#define DIR825C1_GPIO_LED_BLUE_WPS 15 ++#define DIR825C1_GPIO_LED_AMBER_PLANET 19 ++#define DIR825C1_GPIO_LED_BLUE_PLANET 18 ++#define DIR825C1_GPIO_LED_WLAN_2G 13 ++ ++#define DIR825C1_GPIO_WAN_LED_ENABLE 20 ++ ++#define DIR825C1_GPIO_BTN_RESET 17 ++#define DIR825C1_GPIO_BTN_WPS 16 ++ ++#define DIR825C1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DIR825C1_KEYS_DEBOUNCE_INTERVAL (3 * DIR825C1_KEYS_POLL_INTERVAL) ++ ++#define DIR825C1_MAC0_OFFSET 0x4 ++#define DIR825C1_MAC1_OFFSET 0x18 ++#define DIR825C1_WMAC_CALDATA_OFFSET 0x1000 ++#define DIR825C1_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led dir825c1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:blue:usb", ++ .gpio = DIR825C1_GPIO_LED_BLUE_USB, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:amber:power", ++ .gpio = DIR825C1_GPIO_LED_AMBER_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:blue:power", ++ .gpio = DIR825C1_GPIO_LED_BLUE_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:blue:wps", ++ .gpio = DIR825C1_GPIO_LED_BLUE_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:amber:planet", ++ .gpio = DIR825C1_GPIO_LED_AMBER_PLANET, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:blue:wlan2g", ++ .gpio = DIR825C1_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led dir835a1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:amber:power", ++ .gpio = DIR825C1_GPIO_LED_AMBER_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:power", ++ .gpio = DIR825C1_GPIO_LED_BLUE_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:blue:wps", ++ .gpio = DIR825C1_GPIO_LED_BLUE_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:amber:planet", ++ .gpio = DIR825C1_GPIO_LED_AMBER_PLANET, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:green:planet", ++ .gpio = DIR825C1_GPIO_LED_BLUE_PLANET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button dir825c1_gpio_keys[] __initdata = { ++ { ++ .desc = "Soft reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DIR825C1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR825C1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DIR825C1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR825C1_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg dir825c1_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg dir825c1_ar8327_led_cfg = { ++ .led_ctrl0 = 0x00000000, ++ .led_ctrl1 = 0xc737c737, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x00c30c00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data dir825c1_ar8327_data = { ++ .pad0_cfg = &dir825c1_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &dir825c1_ar8327_led_cfg, ++}; ++ ++static struct mdio_board_info dir825c1_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dir825c1_ar8327_data, ++ }, ++}; ++ ++static void __init dir825c1_generic_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1ffe0000); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 mac0[ETH_ALEN], mac1[ETH_ALEN]; ++ u8 wmac0[ETH_ALEN], wmac1[ETH_ALEN]; ++ ++ ath79_parse_ascii_mac(mac + DIR825C1_MAC0_OFFSET, mac0); ++ ath79_parse_ascii_mac(mac + DIR825C1_MAC1_OFFSET, mac1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_gpio_keys_polled(-1, DIR825C1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dir825c1_gpio_keys), ++ dir825c1_gpio_keys); ++ ++ ath79_init_mac(wmac0, mac0, 0); ++ ath79_register_wmac(art + DIR825C1_WMAC_CALDATA_OFFSET, wmac0); ++ ++ ath79_init_mac(wmac1, mac1, 1); ++ ap91_pci_init(art + DIR825C1_PCIE_CALDATA_OFFSET, wmac1); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ++ mdiobus_register_board_info(dir825c1_mdio0_info, ++ ARRAY_SIZE(dir825c1_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac0, 0); ++ ++ /* GMAC0 is connected to an AR8327N switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++ ++ ath79_register_usb(); ++} ++ ++static void __init dir825c1_setup(void) ++{ ++ ath79_gpio_output_select(DIR825C1_GPIO_LED_BLUE_USB, ++ AR934X_GPIO_OUT_GPIO); ++ ++ gpio_request_one(DIR825C1_GPIO_WAN_LED_ENABLE, ++ GPIOF_OUT_INIT_LOW, "WAN LED enable"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dir825c1_leds_gpio), ++ dir825c1_leds_gpio); ++ ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++ ++ dir825c1_generic_setup(); ++} ++ ++static void __init dir835a1_setup(void) ++{ ++ dir825c1_ar8327_data.led_cfg = NULL; ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dir835a1_leds_gpio), ++ dir835a1_leds_gpio); ++ ++ dir825c1_generic_setup(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_825_C1, "DIR-825-C1", ++ "D-Link DIR-825 rev. C1", ++ dir825c1_setup); ++ ++MIPS_MACHINE(ATH79_MACH_DIR_835_A1, "DIR-835-A1", ++ "D-Link DIR-835 rev. A1", ++ dir835a1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-869-a1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-869-a1.c +new file mode 100644 +index 0000000000..3841c3d5d5 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-869-a1.c +@@ -0,0 +1,175 @@ ++/* ++ * D-Link DIR-869 A1 support ++ * ++ * Copyright (C) 2015-2016 P. Wassi ++ * Copyright (C) 2016 Matthias Schiffer ++ * ++ * Derived from: mach-ubnt-unifiac.c ++ * ++ * 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 ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++ ++#define DIR869A1_GPIO_BTN_RESET 1 ++#define DIR869A1_GPIO_BTN_WPS 2 ++#define DIR869A1_GPIO_SWITCH_MODE 8 ++ ++#define DIR869A1_GPIO_ENABLE_SWITCH 11 ++ ++#define DIR869A1_GPIO_LED_ORANGE 15 ++#define DIR869A1_GPIO_LED_WHITE 16 ++ ++#define DIR869A1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DIR869A1_KEYS_DEBOUNCE_INTERVAL (3 * DIR869A1_KEYS_POLL_INTERVAL) ++ ++ ++#define DIR869A1_DEVDATA_ADDR 0x1f050000 ++#define DIR869A1_DEVDATA_SIZE 0x10000 ++ ++#define DIR869A1_EEPROM_ADDR 0x1fff0000 ++#define DIR869A1_WMAC_CALDATA_OFFSET 0x1000 ++#define DIR869A1_PCI_CALDATA_OFFSET 0x5000 ++ ++ ++static struct gpio_led dir869a1_leds_gpio[] __initdata = { ++ { ++ .name = "d-link:white:status", ++ .gpio = DIR869A1_GPIO_LED_WHITE, ++ .active_low = 1, ++ }, ++ { ++ .name = "d-link:orange:status", ++ .gpio = DIR869A1_GPIO_LED_ORANGE, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button dir869a1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DIR869A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR869A1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DIR869A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR869A1_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "mode", ++ .type = EV_SW, ++ .code = BTN_0, ++ .debounce_interval = DIR869A1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DIR869A1_GPIO_SWITCH_MODE, ++ .active_low = 0, ++ }, ++}; ++ ++ ++static struct ar8327_pad_cfg dir869a1_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data dir869a1_ar8327_data = { ++ .pad0_cfg = &dir869a1_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++ ++static struct mdio_board_info dir869a1_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dir869a1_ar8327_data, ++ }, ++}; ++ ++ ++static void dir869a1_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(DIR869A1_DEVDATA_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, DIR869A1_DEVDATA_SIZE, ++ name, mac); ++ if (err) ++ pr_err("no MAC address found for %s\n", name); ++} ++ ++static void __init dir869a1_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(DIR869A1_EEPROM_ADDR); ++ u8 wlan24mac[ETH_ALEN] = {}, wlan5mac[ETH_ALEN] = {}; ++ ++ ath79_register_m25p80(NULL); ++ ++ gpio_request_one(DIR869A1_GPIO_ENABLE_SWITCH, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "Switch power"); ++ ++ dir869a1_get_mac("lanmac=", ath79_eth0_data.mac_addr); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ mdiobus_register_board_info(dir869a1_mdio0_info, ++ ARRAY_SIZE(dir869a1_mdio0_info)); ++ ++ ath79_register_mdio(0, 0); ++ ath79_register_eth(0); ++ ++ dir869a1_get_mac("wlan24mac=", wlan24mac); ++ ath79_register_wmac(eeprom + DIR869A1_WMAC_CALDATA_OFFSET, wlan24mac); ++ ++ dir869a1_get_mac("wlan5mac=", wlan5mac); ++ ap91_pci_init(eeprom + DIR869A1_PCI_CALDATA_OFFSET, wlan5mac); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dir869a1_leds_gpio), ++ dir869a1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DIR869A1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dir869a1_gpio_keys), ++ dir869a1_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DIR_869_A1, "DIR-869-A1", "D-Link DIR-869 rev. A1", ++ dir869a1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-hotspot.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-hotspot.c +new file mode 100644 +index 0000000000..3ae46514fc +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-hotspot.c +@@ -0,0 +1,117 @@ ++/* ++ * devolo dLAN Hotspot board support ++ * ++ * Copyright (C) 2015 Torsten Schnuis ++ * Copyright (C) 2015 devolo AG ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DLAN_HOTSPOT_GPIO_LED_WIFI 0 ++ ++#define DLAN_HOTSPOT_GPIO_BTN_RESET 11 ++#define DLAN_HOTSPOT_GPIO_BTN_PLC_PAIRING 12 ++#define DLAN_HOTSPOT_GPIO_BTN_WIFI 21 ++ ++#define DLAN_HOTSPOT_GPIO_PLC_POWER 22 ++#define DLAN_HOTSPOT_GPIO_PLC_RESET 20 ++#define DLAN_HOTSPOT_GPIO_PLC_DISABLE_LEDS 18 ++ ++#define DLAN_HOTSPOT_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DLAN_HOTSPOT_KEYS_DEBOUNCE_INTERVAL (3 * DLAN_HOTSPOT_KEYS_POLL_INTERVAL) ++ ++#define DLAN_HOTSPOT_ART_ADDRESS 0x1fff0000 ++#define DLAN_HOTSPOT_CALDATA_OFFSET 0x00001000 ++#define DLAN_HOTSPOT_MAC_ADDRESS_OFFSET 0x00001002 ++ ++static struct gpio_led dlan_hotspot_leds_gpio[] __initdata = { ++ { ++ .name = "devolo:green:wifi", ++ .gpio = DLAN_HOTSPOT_GPIO_LED_WIFI, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button dlan_hotspot_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DLAN_HOTSPOT_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_HOTSPOT_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++ { ++ .desc = "Pairing button", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = DLAN_HOTSPOT_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_HOTSPOT_GPIO_BTN_PLC_PAIRING, ++ .active_low = 0, ++ }, ++ { ++ .desc = "WLAN button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DLAN_HOTSPOT_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_HOTSPOT_GPIO_BTN_WIFI, ++ .active_low = 0, ++ } ++}; ++ ++static void __init dlan_hotspot_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(DLAN_HOTSPOT_ART_ADDRESS); ++ u8 *cal = art + DLAN_HOTSPOT_CALDATA_OFFSET; ++ u8 *wifi_mac = art + DLAN_HOTSPOT_MAC_ADDRESS_OFFSET; ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dlan_hotspot_leds_gpio), ++ dlan_hotspot_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DLAN_HOTSPOT_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dlan_hotspot_gpio_keys), ++ dlan_hotspot_gpio_keys); ++ ++ gpio_request_one(DLAN_HOTSPOT_GPIO_PLC_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "PLC power"); ++ gpio_request_one(DLAN_HOTSPOT_GPIO_PLC_RESET, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "PLC reset"); ++ gpio_request_one(DLAN_HOTSPOT_GPIO_PLC_DISABLE_LEDS, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "PLC LEDs"); ++ ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, wifi_mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, wifi_mac, 2); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(cal, wifi_mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DLAN_HOTSPOT, "dLAN-Hotspot", ++ "dLAN Hotspot", dlan_hotspot_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-pro-1200-ac.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-pro-1200-ac.c +new file mode 100644 +index 0000000000..2100a9608d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-pro-1200-ac.c +@@ -0,0 +1,190 @@ ++/* ++ * devolo dLAN pro 500 Wireless+ support ++ * ++ * Copyright (c) 2013-2015 devolo AG ++ * Copyright (c) 2011-2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DLAN_PRO_1200_AC_GPIO_DLAN_POWER_ENABLE 13 ++#define DLAN_PRO_1200_AC_GPIO_WLAN_POWER_ENABLE 21 ++#define DLAN_PRO_1200_AC_GPIO_LED_WLAN 12 ++#define DLAN_PRO_1200_AC_GPIO_LED_DLAN 14 ++#define DLAN_PRO_1200_AC_GPIO_LED_DLAN_ERR 15 ++ ++#define DLAN_PRO_1200_AC_GPIO_BTN_WLAN 20 ++#define DLAN_PRO_1200_AC_GPIO_BTN_DLAN 22 ++#define DLAN_PRO_1200_AC_GPIO_BTN_RESET 4 ++#define DLAN_PRO_1200_AC_GPIO_DLAN_IND 17 ++#define DLAN_PRO_1200_AC_GPIO_DLAN_ERR_IND 16 ++ ++#define DLAN_PRO_1200_AC_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DLAN_PRO_1200_AC_KEYS_DEBOUNCE_INTERVAL (3 * DLAN_PRO_1200_AC_KEYS_POLL_INTERVAL) ++ ++#define DLAN_PRO_1200_AC_ART_ADDRESS 0x1fff0000 ++#define DLAN_PRO_1200_AC_CALDATA_OFFSET 0x1000 ++#define DLAN_PRO_1200_AC_WIFIMAC_OFFSET 0x1002 ++#define DLAN_PRO_1200_AC_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led dlan_pro_1200_ac_leds_gpio[] __initdata = { ++ { ++ .name = "devolo:status:wlan", ++ .gpio = DLAN_PRO_1200_AC_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "devolo:status:dlan", ++ .gpio = DLAN_PRO_1200_AC_GPIO_LED_DLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "devolo:error:dlan", ++ .gpio = DLAN_PRO_1200_AC_GPIO_LED_DLAN_ERR, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button dlan_pro_1200_ac_gpio_keys[] __initdata = { ++ { ++ .desc = "dLAN button", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = DLAN_PRO_1200_AC_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_PRO_1200_AC_GPIO_BTN_DLAN, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WLAN button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DLAN_PRO_1200_AC_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_PRO_1200_AC_GPIO_BTN_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DLAN_PRO_1200_AC_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_PRO_1200_AC_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct ar8327_pad_cfg dlan_pro_1200_ac_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = false, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++ .mac06_exchange_dis = true, ++}; ++ ++static struct ar8327_pad_cfg dlan_pro_1200_ac_ar8327_pad5_cfg = { ++ .mode = 0, ++ .txclk_delay_en = 0, ++ .rxclk_delay_en = 0, ++ .txclk_delay_sel = 0, ++ .rxclk_delay_sel = 0, ++}; ++ ++static struct ar8327_platform_data dlan_pro_1200_ac_ar8327_data = { ++ .pad0_cfg = &dlan_pro_1200_ac_ar8327_pad0_cfg, ++ .pad5_cfg = &dlan_pro_1200_ac_ar8327_pad5_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info dlan_pro_1200_ac_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dlan_pro_1200_ac_ar8327_data, ++ }, ++}; ++ ++static void __init dlan_pro_1200_ac_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(DLAN_PRO_1200_AC_ART_ADDRESS); ++ u8 *cal = art + DLAN_PRO_1200_AC_CALDATA_OFFSET; ++ u8 *wifi_mac = art + DLAN_PRO_1200_AC_WIFIMAC_OFFSET; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dlan_pro_1200_ac_leds_gpio), ++ dlan_pro_1200_ac_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DLAN_PRO_1200_AC_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dlan_pro_1200_ac_gpio_keys), ++ dlan_pro_1200_ac_gpio_keys); ++ ++ /* dLAN power must be enabled from user-space as soon as the boot-from-host daemon is running */ ++ gpio_request_one(DLAN_PRO_1200_AC_GPIO_DLAN_POWER_ENABLE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "dLAN power"); ++ ++ /* WLAN power is turned on initially to allow the PCI bus scan to succeed */ ++ gpio_request_one(DLAN_PRO_1200_AC_GPIO_WLAN_POWER_ENABLE, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "WLAN power"); ++ ++ ath79_register_wmac(cal, wifi_mac); ++ ap91_pci_init(art + DLAN_PRO_1200_AC_PCIE_CALDATA_OFFSET, NULL); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, wifi_mac, 2); ++ ++ mdiobus_register_board_info(dlan_pro_1200_ac_mdio0_info, ++ ARRAY_SIZE(dlan_pro_1200_ac_mdio0_info)); ++ ++ /* GMAC0 is connected to an AR8337 */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x02000000; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DLAN_PRO_1200_AC, "dLAN-pro-1200-ac", "devolo dLAN pro 1200+ WiFi ac", ++ dlan_pro_1200_ac_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-pro-500-wp.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-pro-500-wp.c +new file mode 100644 +index 0000000000..931eafffcb +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dlan-pro-500-wp.c +@@ -0,0 +1,203 @@ ++/* ++ * devolo dLAN pro 500 Wireless+ support ++ * ++ * Copyright (c) 2013-2015 devolo AG ++ * Copyright (c) 2011-2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DLAN_PRO_500_WP_GPIO_DLAN_POWER_ENABLE 13 ++#define DLAN_PRO_500_WP_GPIO_DLAN_LED_ENABLE 17 ++#define DLAN_PRO_500_WP_GPIO_LED_WLAN_5G 11 ++#define DLAN_PRO_500_WP_GPIO_LED_WLAN_2G 12 ++#define DLAN_PRO_500_WP_GPIO_LED_STATUS 16 ++#define DLAN_PRO_500_WP_GPIO_LED_ETH 14 ++ ++#define DLAN_PRO_500_WP_GPIO_BTN_WPS 20 ++#define DLAN_PRO_500_WP_GPIO_BTN_WLAN 22 ++#define DLAN_PRO_500_WP_GPIO_BTN_DLAN 21 ++#define DLAN_PRO_500_WP_GPIO_BTN_RESET 4 ++ ++#define DLAN_PRO_500_WP_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DLAN_PRO_500_WP_KEYS_DEBOUNCE_INTERVAL (3 * DLAN_PRO_500_WP_KEYS_POLL_INTERVAL) ++ ++#define DLAN_PRO_500_WP_ART_ADDRESS 0x1fff0000 ++#define DLAN_PRO_500_WP_CALDATA_OFFSET 0x1000 ++#define DLAN_PRO_500_WP_MAC_ADDRESS_OFFSET 0x1002 ++#define DLAN_PRO_500_WP_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led dlan_pro_500_wp_leds_gpio[] __initdata = { ++ { ++ .name = "devolo:green:status", ++ .gpio = DLAN_PRO_500_WP_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "devolo:green:eth", ++ .gpio = DLAN_PRO_500_WP_GPIO_LED_ETH, ++ .active_low = 1, ++ }, ++ { ++ .name = "devolo:blue:wlan-5g", ++ .gpio = DLAN_PRO_500_WP_GPIO_LED_WLAN_5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "devolo:green:wlan-2g", ++ .gpio = DLAN_PRO_500_WP_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button dlan_pro_500_wp_gpio_keys[] __initdata = { ++ { ++ .desc = "dLAN button", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = DLAN_PRO_500_WP_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_PRO_500_WP_GPIO_BTN_DLAN, ++ .active_low = 0, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DLAN_PRO_500_WP_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_PRO_500_WP_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, ++ { ++ .desc = "WLAN button", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = DLAN_PRO_500_WP_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_PRO_500_WP_GPIO_BTN_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DLAN_PRO_500_WP_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DLAN_PRO_500_WP_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct ar8327_pad_cfg dlan_pro_500_wp_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_PHY_RGMII, ++ .txclk_delay_en = false, ++ .rxclk_delay_en = false, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++}; ++ ++static struct ar8327_led_cfg dlan_pro_500_wp_ar8327_led_cfg = { ++ .led_ctrl0 = 0x00000000, ++ .led_ctrl1 = 0xc737c737, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x00c30c00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data dlan_pro_500_wp_ar8327_data = { ++ .pad0_cfg = &dlan_pro_500_wp_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 0, ++ .rxpause = 0, ++ }, ++ .led_cfg = &dlan_pro_500_wp_ar8327_led_cfg, ++}; ++ ++static struct mdio_board_info dlan_pro_500_wp_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dlan_pro_500_wp_ar8327_data, ++ }, ++}; ++ ++static void __init dlan_pro_500_wp_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(DLAN_PRO_500_WP_ART_ADDRESS); ++ u8 *cal = art + DLAN_PRO_500_WP_CALDATA_OFFSET; ++ u8 *wifi_mac = art + DLAN_PRO_500_WP_MAC_ADDRESS_OFFSET; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dlan_pro_500_wp_leds_gpio), ++ dlan_pro_500_wp_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DLAN_PRO_500_WP_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dlan_pro_500_wp_gpio_keys), ++ dlan_pro_500_wp_gpio_keys); ++ ++ gpio_request_one(DLAN_PRO_500_WP_GPIO_DLAN_POWER_ENABLE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "PLC power"); ++ gpio_request_one(DLAN_PRO_500_WP_GPIO_DLAN_LED_ENABLE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "PLC LEDs"); ++ ++ ath79_register_wmac(cal, wifi_mac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ++ ath79_register_mdio(1, 0x0); ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(dlan_pro_500_wp_mdio0_info, ++ ARRAY_SIZE(dlan_pro_500_wp_mdio0_info)); ++ ++ /* GMAC0 is connected to a AR7400 PLC in PHY mode */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, wifi_mac, 2); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_pll_data.pll_1000 = 0x0e000000; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, wifi_mac, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DLAN_PRO_500_WP, "dLAN-pro-500-wp", "devolo dLAN pro 500 Wireless+", ++ dlan_pro_500_wp_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-domywifi-dw33d.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-domywifi-dw33d.c +new file mode 100644 +index 0000000000..ac4aa8eadf +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-domywifi-dw33d.c +@@ -0,0 +1,192 @@ ++/* ++ * DomyWifi DW33D support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * ++ * 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 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++ ++#include ++ ++#include "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DW33D_GPIO_LED_MMC 4 ++#define DW33D_GPIO_LED_WLAN_2G 13 ++#define DW33D_GPIO_LED_STATUS 14 ++#define DW33D_GPIO_LED_USB 15 ++#define DW33D_GPIO_LED_INTERNET 22 ++ ++#define DW33D_GPIO_BTN_RESET 17 ++ ++#define DW33D_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DW33D_KEYS_DEBOUNCE_INTERVAL (3 * DW33D_KEYS_POLL_INTERVAL) ++ ++#define DW33D_MAC0_OFFSET 0 ++#define DW33D_MAC1_OFFSET 6 ++#define DW33D_WMAC_OFFSET 12 ++#define DW33D_WMAC_CALDATA_OFFSET 0x1000 ++#define DW33D_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led dw33d_leds_gpio[] __initdata = { ++ { ++ .name = "dw33d:blue:status", ++ .gpio = DW33D_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "dw33d:blue:mmc", ++ .gpio = DW33D_GPIO_LED_MMC, ++ .active_low = 1, ++ }, ++ { ++ .name = "dw33d:blue:usb", ++ .gpio = DW33D_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++ { ++ .name = "dw33d:blue:wlan-2g", ++ .gpio = DW33D_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "dw33d:blue:internet", ++ .gpio = DW33D_GPIO_LED_INTERNET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button dw33d_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DW33D_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DW33D_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++/* GMAC6 of the QCA8337 switch is connected to the QCA9558 SoC via SGMII */ ++static struct ar8327_pad_cfg dw33d_qca8337_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++/* GMAC0 of the QCA8337 switch is connected to the QCA9558 SoC via RGMII */ ++static struct ar8327_pad_cfg dw33d_qca8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data dw33d_qca8337_data = { ++ .pad0_cfg = &dw33d_qca8337_pad0_cfg, ++ .pad6_cfg = &dw33d_qca8337_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info dw33d_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dw33d_qca8337_data, ++ }, ++}; ++ ++static void __init dw33d_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dw33d_leds_gpio), ++ dw33d_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DW33D_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dw33d_gpio_keys), ++ dw33d_gpio_keys); ++ ++ ath79_register_usb(); ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_HW); ++ ath79_register_nfc(); ++ ath79_register_pci(); ++ ++ ath79_register_wmac(art + DW33D_WMAC_CALDATA_OFFSET, art + DW33D_WMAC_OFFSET); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + DW33D_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + DW33D_MAC1_OFFSET, 0); ++ ++ mdiobus_register_board_info(dw33d_mdio0_info, ++ ARRAY_SIZE(dw33d_mdio0_info)); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected tot eh SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DOMYWIFI_DW33D, "DW33D", ++ "DomyWifi DW33D", ++ dw33d_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dr344.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dr344.c +new file mode 100644 +index 0000000000..888c9c949f +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dr344.c +@@ -0,0 +1,224 @@ ++/* ++ * Wallys DR342/DR344 boards support ++ * ++ * Copyright (c) 2011 Qualcomm Atheros ++ * Copyright (c) 2011-2012 Gabor Juhos ++ * Copyright (c) 2015 Philippe Duchein ++ * Copyright (c) 2017 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-usb.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DR34X_GPIO_LED_SIG1 12 ++#define DR34X_GPIO_LED_SIG2 13 ++#define DR34X_GPIO_LED_SIG3 14 ++#define DR34X_GPIO_LED_SIG4 15 ++#define DR34X_GPIO_LED_STATUS 11 ++#define DR344_GPIO_LED_LAN 17 ++#define DR344_GPIO_EXTERNAL_LNA0 18 ++#define DR344_GPIO_EXTERNAL_LNA1 19 ++ ++#define DR34X_GPIO_BTN_RESET 16 ++ ++#define DR344_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DR344_KEYS_DEBOUNCE_INTERVAL (3 * DR344_KEYS_POLL_INTERVAL) ++ ++#define DR34X_MAC0_OFFSET 0 ++#define DR34X_MAC1_OFFSET 8 ++#define DR34X_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led dr342_leds_gpio[] __initdata = { ++ { ++ .name = "dr342:green:status", ++ .gpio = DR34X_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr342:green:sig1", ++ .gpio = DR34X_GPIO_LED_SIG1, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr342:green:sig2", ++ .gpio = DR34X_GPIO_LED_SIG2, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr342:green:sig3", ++ .gpio = DR34X_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr342:green:sig4", ++ .gpio = DR34X_GPIO_LED_SIG4, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led dr344_leds_gpio[] __initdata = { ++ { ++ .name = "dr344:green:lan", ++ .gpio = DR344_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr344:green:status", ++ .gpio = DR34X_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr344:green:sig1", ++ .gpio = DR34X_GPIO_LED_SIG1, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr344:green:sig2", ++ .gpio = DR34X_GPIO_LED_SIG2, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr344:green:sig3", ++ .gpio = DR34X_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr344:green:sig4", ++ .gpio = DR34X_GPIO_LED_SIG4, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button dr34x_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DR344_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DR34X_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct at803x_platform_data dr34x_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info dr34x_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &dr34x_at803x_data, ++ }, ++}; ++ ++static void __init dr34x_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f03f810); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_gpio_direction_select(DR34X_GPIO_LED_STATUS, true); ++ gpio_set_value(DR34X_GPIO_LED_STATUS, 1); ++ ath79_gpio_output_select(DR34X_GPIO_LED_STATUS, 0); ++ ++ ath79_register_gpio_keys_polled(-1, DR344_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dr34x_gpio_keys), ++ dr34x_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + DR34X_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ++ mdiobus_register_board_info(dr34x_mdio0_info, ++ ARRAY_SIZE(dr34x_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ /* GMAC0 is connected to an AR8035 Gbps PHY */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x02000000; ++ ath79_eth0_pll_data.pll_100 = 0x0101; ++ ath79_eth0_pll_data.pll_10 = 0x1313; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac + DR34X_MAC0_OFFSET, 0); ++ ath79_register_eth(0); ++} ++ ++static void __init dr342_setup(void) ++{ ++ dr34x_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dr342_leds_gpio), ++ dr342_leds_gpio); ++} ++ ++static void __init dr344_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f03f810); ++ ++ dr34x_setup(); ++ ++ ath79_gpio_direction_select(DR344_GPIO_LED_LAN, true); ++ gpio_set_value(DR344_GPIO_LED_LAN, 1); ++ ath79_gpio_output_select(DR344_GPIO_LED_LAN, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dr344_leds_gpio), ++ dr344_leds_gpio); ++ ++ ath79_wmac_set_ext_lna_gpio(0, DR344_GPIO_EXTERNAL_LNA0); ++ ath79_wmac_set_ext_lna_gpio(1, DR344_GPIO_EXTERNAL_LNA1); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac + DR34X_MAC1_OFFSET, 0); ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DR342, "DR342", "Wallys DR342", dr342_setup); ++MIPS_MACHINE(ATH79_MACH_DR344, "DR344", "Wallys DR344", dr344_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dr531.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dr531.c +new file mode 100644 +index 0000000000..b638a9001c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dr531.c +@@ -0,0 +1,155 @@ ++/* ++ * Wallys DR531 board support ++ * ++ * Copyright (C) 2016 Piotr Dymacz ++ * ++ * Based on mach-wpj531.c ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define DR531_GPIO_BUZZER 4 ++#define DR531_GPIO_LED_WAN 11 ++#define DR531_GPIO_LED_LAN 14 ++#define DR531_GPIO_LED_SIG1 12 ++#define DR531_GPIO_LED_SIG2 16 ++#define DR531_GPIO_LED_SIG3 15 ++#define DR531_GPIO_LED_SIG4 13 ++ ++#define DR531_GPIO_BTN_RESET 17 ++ ++#define DR531_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DR531_KEYS_DEBOUNCE_INTERVAL (3 * DR531_KEYS_POLL_INTERVAL) ++ ++#define DR531_MAC0_OFFSET 0x0 ++#define DR531_MAC1_OFFSET 0x8 ++#define DR531_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led dr531_leds_gpio[] __initdata = { ++ { ++ .name = "dr531:green:wan", ++ .gpio = DR531_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr531:green:lan", ++ .gpio = DR531_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr531:green:sig1", ++ .gpio = DR531_GPIO_LED_SIG1, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr531:green:sig2", ++ .gpio = DR531_GPIO_LED_SIG2, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr531:green:sig3", ++ .gpio = DR531_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr531:green:sig4", ++ .gpio = DR531_GPIO_LED_SIG4, ++ .active_low = 1, ++ }, ++ { ++ .name = "dr531:buzzer", ++ .gpio = DR531_GPIO_BUZZER, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button dr531_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DR531_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DR531_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init dr531_gpio_setup(void) ++{ ++ ath79_gpio_direction_select(DR531_GPIO_BUZZER, true); ++ ath79_gpio_direction_select(DR531_GPIO_LED_WAN, true); ++ ath79_gpio_direction_select(DR531_GPIO_LED_LAN, true); ++ ath79_gpio_direction_select(DR531_GPIO_LED_SIG1, true); ++ ath79_gpio_direction_select(DR531_GPIO_LED_SIG2, true); ++ ath79_gpio_direction_select(DR531_GPIO_LED_SIG3, true); ++ ath79_gpio_direction_select(DR531_GPIO_LED_SIG4, true); ++ ++ ath79_gpio_output_select(DR531_GPIO_BUZZER, 0); ++ ath79_gpio_output_select(DR531_GPIO_LED_WAN, 0); ++ ath79_gpio_output_select(DR531_GPIO_LED_LAN, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dr531_leds_gpio), ++ dr531_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, DR531_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dr531_gpio_keys), ++ dr531_gpio_keys); ++} ++ ++static void __init dr531_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f03f810); ++ ++ ath79_register_m25p80(NULL); ++ ++ dr531_gpio_setup(); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac + DR531_MAC1_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ /* WAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac + DR531_MAC0_OFFSET, 0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + DR531_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DR531, "DR531", "Wallys DR531", dr531_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dragino2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dragino2.c +new file mode 100644 +index 0000000000..95bd6f41a3 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dragino2.c +@@ -0,0 +1,136 @@ ++/* ++ * DRAGINO V2 board support, based on Atheros AP121 board support ++ * ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2012 Elektra Wagenrad ++ * Copyright (C) 2014 Vittorio Gambaletta ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DRAGINO2_GPIO_LED_WLAN 0 ++#define DRAGINO2_GPIO_LED_LAN 13 ++#define DRAGINO2_GPIO_LED_WAN 17 ++ ++/* ++ * The following GPIO is named "SYS" on newer revisions of the the board. ++ * It was previously used to indicate USB activity, even though it was ++ * named "Router". ++ */ ++ ++#define DRAGINO2_GPIO_LED_SYS 28 ++#define DRAGINO2_GPIO_BTN_JUMPSTART 11 ++#define DRAGINO2_GPIO_BTN_RESET 12 ++ ++#define DRAGINO2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DRAGINO2_KEYS_DEBOUNCE_INTERVAL (3 * DRAGINO2_KEYS_POLL_INTERVAL) ++ ++#define DRAGINO2_MAC0_OFFSET 0x0000 ++#define DRAGINO2_MAC1_OFFSET 0x0006 ++#define DRAGINO2_CALDATA_OFFSET 0x1000 ++#define DRAGINO2_WMAC_MAC_OFFSET 0x1002 ++ ++static struct gpio_led dragino2_leds_gpio[] __initdata = { ++ { ++ .name = "dragino2:red:wlan", ++ .gpio = DRAGINO2_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "dragino2:red:wan", ++ .gpio = DRAGINO2_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "dragino2:red:lan", ++ .gpio = DRAGINO2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "dragino2:red:system", ++ .gpio = DRAGINO2_GPIO_LED_SYS, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button dragino2_gpio_keys[] __initdata = { ++ { ++ .desc = "jumpstart button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DRAGINO2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DRAGINO2_GPIO_BTN_JUMPSTART, ++ .active_low = 1, ++ }, ++ { ++ .desc = "reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DRAGINO2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DRAGINO2_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init dragino2_common_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_wmac(art + DRAGINO2_CALDATA_OFFSET, ++ art + DRAGINO2_WMAC_MAC_OFFSET); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + DRAGINO2_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + DRAGINO2_MAC1_OFFSET, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* Enable GPIO13, GPIO14, GPIO15, GPIO16 and GPIO17 */ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ /* LAN port */ ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ /* Enable GPIO26 and GPIO27 */ ++ ath79_reset_wr(AR933X_RESET_REG_BOOTSTRAP, ++ ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP) | ++ AR933X_BOOTSTRAP_MDIO_GPIO_EN); ++} ++ ++static void __init dragino2_setup(void) ++{ ++ dragino2_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dragino2_leds_gpio), ++ dragino2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DRAGINO2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dragino2_gpio_keys), ++ dragino2_gpio_keys); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_DRAGINO2, "DRAGINO2", "Dragino Dragino v2", ++ dragino2_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-e1700ac-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-e1700ac-v2.c +new file mode 100644 +index 0000000000..1ba47a4255 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-e1700ac-v2.c +@@ -0,0 +1,145 @@ ++/* ++ * Qxwlan E1700AC v2 board support ++ * ++ * Copyright (C) 2017 Peng Zhang ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define E1700AC_V2_GPIO_LED_SYS 1 ++#define E1700AC_V2_GPIO_LED_USB 7 ++#define E1700AC_V2_GPIO_LED_WLAN2G 19 ++ ++#define E1700AC_V2_GPIO_BTN_SW1 2 ++#define E1700AC_V2_GPIO_BTN_RESET 11 ++ ++#define E1700AC_V2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define E1700AC_V2_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * E1700AC_V2_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led e1700ac_v2_leds_gpio[] __initdata = { ++ { ++ .name = "e1700ac-v2:green:system", ++ .gpio = E1700AC_V2_GPIO_LED_SYS, ++ .active_low = 1, ++ }, { ++ .name = "e1700ac-v2:green:usb", ++ .gpio = E1700AC_V2_GPIO_LED_USB, ++ .active_low = 1, ++ }, { ++ .name = "e1700ac-v2:green:wlan2g", ++ .gpio = E1700AC_V2_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button e1700ac_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = E1700AC_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E1700AC_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "sw1", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = E1700AC_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E1700AC_V2_GPIO_BTN_SW1, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info e1700ac_v2_leds_qca8334[] = { ++ AR8327_LED_INFO(PHY1_0, HW, "e1700ac-v2:green:lan"), ++ AR8327_LED_INFO(PHY2_0, HW, "e1700ac-v2:green:wan"), ++}; ++ ++/* Blink rate: 1 Gbps -> 8 hz, 100 Mbs -> 4 Hz, 10 Mbps -> 2 Hz */ ++static struct ar8327_led_cfg e1700ac_v2_qca8334_led_cfg = { ++ .led_ctrl0 = 0xcf37cf37, ++ .led_ctrl1 = 0xcf37cf37, ++ .led_ctrl2 = 0xcf37cf37, ++ .led_ctrl3 = 0x0, ++ .open_drain = true, ++}; ++ ++static struct ar8327_pad_cfg e1700ac_v2_qca8334_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data e1700ac_v2_qca8334_data = { ++ .pad0_cfg = &e1700ac_v2_qca8334_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &e1700ac_v2_qca8334_led_cfg, ++ .leds = e1700ac_v2_leds_qca8334, ++ .num_leds = ARRAY_SIZE(e1700ac_v2_leds_qca8334), ++}; ++ ++static struct mdio_board_info e1700ac_v2_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &e1700ac_v2_qca8334_data, ++ }, ++}; ++ ++static void __init e1700ac_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f050400); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f061000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(e1700ac_v2_leds_gpio), ++ e1700ac_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, E1700AC_V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(e1700ac_v2_gpio_keys), ++ e1700ac_v2_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(e1700ac_v2_mdio0_info, ++ ARRAY_SIZE(e1700ac_v2_mdio0_info)); ++ ++ /* GMAC0 is connected to QCA8334 switch */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_pll_data.pll_1000 = 0x03000101; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++ ath79_register_wmac(art, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_E1700AC_V2, "E1700AC-V2", "Qxwlan E1700AC v2", ++ e1700ac_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-e2100l.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-e2100l.c +new file mode 100644 +index 0000000000..c09083460e +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-e2100l.c +@@ -0,0 +1,126 @@ ++/* ++ * Linksys E2100L board support ++ * ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "nvram.h" ++#include "machtypes.h" ++ ++#define E2100L_GPIO_LED_POWER 14 ++#define E2100L_GPIO_LED_WPS_AMBER 9 ++#define E2100L_GPIO_LED_WPS_BLUE 8 ++#define E2100L_GPIO_LED_WLAN 6 ++ ++#define E2100L_GPIO_BTN_WPS 7 ++#define E2100L_GPIO_BTN_RESET 21 ++ ++#define E2100L_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define E2100L_KEYS_DEBOUNCE_INTERVAL (3 * E2100L_KEYS_POLL_INTERVAL) ++ ++#define E2100L_NVRAM_ADDR 0x1f7e0000 ++#define E2100L_NVRAM_SIZE 0x10000 ++ ++static const char *e2100l_part_probes[] = { ++ "cybertan", ++ NULL, ++}; ++ ++static struct flash_platform_data e2100l_flash_data = { ++ .part_probes = e2100l_part_probes, ++}; ++ ++static struct gpio_led e2100l_leds_gpio[] __initdata = { ++ { ++ .name = "e2100l:blue:power", ++ .gpio = E2100L_GPIO_LED_POWER, ++ .active_low = 1, ++ .default_trigger = "default-on", ++ }, { ++ .name = "e2100l:amber:wps", ++ .gpio = E2100L_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "e2100l:blue:wps", ++ .gpio = E2100L_GPIO_LED_WPS_BLUE, ++ .active_low = 1, ++ }, { ++ .name = "e2100l:blue:wlan", ++ .gpio = E2100L_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button e2100l_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = E2100L_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E2100L_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = E2100L_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E2100L_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init e2100l_setup(void) ++{ ++ const char *nvram = (char *) KSEG1ADDR(E2100L_NVRAM_ADDR); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[6]; ++ ++ if (ath79_nvram_parse_mac_addr(nvram, E2100L_NVRAM_SIZE, ++ "lan_hwaddr=", mac) == 0) { ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ } ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.phy_mask = 0x01; ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(&e2100l_flash_data); ++ ++ ath79_register_usb(); ++ ++ if (ath79_nvram_parse_mac_addr(nvram, E2100L_NVRAM_SIZE, ++ "wl0_hwaddr=", mac) == 0) ++ ath79_register_wmac(eeprom, mac); ++ else ++ ath79_register_wmac(eeprom, NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(e2100l_leds_gpio), ++ e2100l_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, E2100L_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(e2100l_gpio_keys), ++ e2100l_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_E2100L, "E2100L", "Linksys E2100L", ++ e2100l_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-e558-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-e558-v2.c +new file mode 100644 +index 0000000000..cc08147209 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-e558-v2.c +@@ -0,0 +1,170 @@ ++/* ++ * Qxwlan E558 v2 board support ++ * ++ * Copyright (C) 2017 Peng Zhang ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define E558_V2_GPIO_LED_WLAN 13 ++#define E558_V2_GPIO_LED_SYSTEM 14 ++#define E558_V2_GPIO_LED_QSS 15 ++ ++#define E558_V2_GPIO_BTN_RESET 16 ++ ++#define E558_V2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define E558_V2_KEYS_DEBOUNCE_INTERVAL (3 * E558_V2_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led e558_v2_leds_gpio[] __initdata = { ++ { ++ .name = "e558-v2:green:qss", ++ .gpio = E558_V2_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "e558-v2:green:system", ++ .gpio = E558_V2_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "e558-v2:green:wlan", ++ .gpio = E558_V2_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button e558_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = E558_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E558_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++/* GMAC0 of the AR8327 switch is connected to the QCA9558 SoC via SGMII */ ++static struct ar8327_pad_cfg e558_v2_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++/* GMAC6 of the AR8327 switch is connected to the QCA9558 SoC via RGMII */ ++static struct ar8327_pad_cfg e558_v2_ar8327_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static const struct ar8327_led_info e558_v2_leds_qca8334[] = { ++ AR8327_LED_INFO(PHY2_0, HW, "e558-v2:green:wan"), ++ AR8327_LED_INFO(PHY3_0, HW, "e558-v2:green:lan1"), ++ AR8327_LED_INFO(PHY4_0, HW, "e558-v2:green:lan2"), ++}; ++ ++static struct ar8327_led_cfg e558_v2_ar8327_led_cfg = { ++ .led_ctrl0 = 0xc737c737, ++ .led_ctrl1 = 0x00000000, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x0030c300, ++ .open_drain = false, ++}; ++ ++static struct ar8327_platform_data e558_v2_ar8327_data = { ++ .pad0_cfg = &e558_v2_ar8327_pad0_cfg, ++ .pad6_cfg = &e558_v2_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &e558_v2_ar8327_led_cfg, ++ .leds = e558_v2_leds_qca8334, ++ .num_leds = ARRAY_SIZE(e558_v2_leds_qca8334), ++}; ++ ++static struct mdio_board_info e558_v2_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &e558_v2_ar8327_data, ++ }, ++}; ++ ++static void __init e558_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f050400); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f061000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(e558_v2_leds_gpio), ++ e558_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, E558_V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(e558_v2_gpio_keys), ++ e558_v2_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(e558_v2_mdio0_info, ++ ARRAY_SIZE(e558_v2_mdio0_info)); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++ ath79_register_wmac(art, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_E558_V2, "E558-V2", "Qxwlan E558 v2", ++ e558_v2_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-e600g-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-e600g-v2.c +new file mode 100644 +index 0000000000..29411dea86 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-e600g-v2.c +@@ -0,0 +1,184 @@ ++/* ++ * Qxwlan E600G/E600GAC v2 board support ++ * ++ * Copyright (C) 2017 Peng Zhang ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define E600G_V2_GPIO_LED_LAN 16 ++#define E600G_V2_GPIO_LED_SYS 13 ++#define E600G_V2_GPIO_LED_WAN_B 4 ++#define E600G_V2_GPIO_LED_WAN_G 15 ++ ++#define E600GAC_V2_GPIO_LED_CTRL_B 14 ++#define E600GAC_V2_GPIO_LED_CTRL_G 11 ++#define E600GAC_V2_GPIO_LED_CTRL_R 12 ++#define E600GAC_V2_GPIO_LED_LAN 16 ++#define E600GAC_V2_GPIO_LED_SYS 13 ++#define E600GAC_V2_GPIO_LED_WAN_G 15 ++#define E600GAC_V2_GPIO_LED_WAN_O 4 ++ ++#define E600G_V2_GPIO_BTN_RESET 17 ++#define E600GAC_V2_GPIO_BTN_WPS 1 ++ ++#define E600G_V2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define E600G_V2_KEYS_DEBOUNCE_INTERVAL (3 * E600G_V2_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led e600g_v2_leds_gpio[] __initdata = { ++ { ++ .name = "e600g-v2:blue:system", ++ .gpio = E600G_V2_GPIO_LED_SYS, ++ .active_low = 1, ++ }, { ++ .name = "e600g-v2:blue:wan", ++ .gpio = E600G_V2_GPIO_LED_WAN_B, ++ .active_low = 1, ++ }, { ++ .name = "e600g-v2:green:lan", ++ .gpio = E600G_V2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "e600g-v2:green:wan", ++ .gpio = E600G_V2_GPIO_LED_WAN_G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led e600gac_v2_leds_gpio[] __initdata = { ++ { ++ .name = "e600gac-v2:blue:control", ++ .gpio = E600GAC_V2_GPIO_LED_CTRL_B, ++ .active_low = 1, ++ }, { ++ .name = "e600gac-v2:green:control", ++ .gpio = E600GAC_V2_GPIO_LED_CTRL_G, ++ .active_low = 1, ++ }, { ++ .name = "e600gac-v2:red:control", ++ .gpio = E600GAC_V2_GPIO_LED_CTRL_R, ++ .active_low = 1, ++ }, { ++ .name = "e600gac-v2:green:system", ++ .gpio = E600GAC_V2_GPIO_LED_SYS, ++ .active_low = 1, ++ }, { ++ .name = "e600gac-v2:orange:wan", ++ .gpio = E600GAC_V2_GPIO_LED_WAN_O, ++ .active_low = 1, ++ }, { ++ .name = "e600gac-v2:green:lan", ++ .gpio = E600GAC_V2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "e600gac-v2:green:wan", ++ .gpio = E600GAC_V2_GPIO_LED_WAN_G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button e600g_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = E600G_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E600G_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button e600gac_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = E600G_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E600G_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = E600G_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E600GAC_V2_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init e600g_v2_common_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f050400); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f061000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = 0xfe; ++ ++ /* LAN */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ /* WAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.phy_mask = BIT(0); ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++ ath79_register_wmac(art, NULL); ++} ++ ++static void __init e600g_v2_setup(void) ++{ ++ e600g_v2_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(e600g_v2_leds_gpio), ++ e600g_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, E600G_V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(e600g_v2_gpio_keys), ++ e600g_v2_gpio_keys); ++} ++ ++static void __init e600gac_v2_setup(void) ++{ ++ e600g_v2_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(e600gac_v2_leds_gpio), ++ e600gac_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, E600G_V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(e600gac_v2_gpio_keys), ++ e600gac_v2_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_E600G_V2, "E600G-V2", "Qxwlan E600G v2", ++ e600g_v2_setup); ++ ++MIPS_MACHINE(ATH79_MACH_E600GAC_V2, "E600GAC-V2", "Qxwlan E600GAC v2", ++ e600gac_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-e750a-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-e750a-v4.c +new file mode 100644 +index 0000000000..7cf3292c68 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-e750a-v4.c +@@ -0,0 +1,122 @@ ++/* ++ * Qxwlan E750A v4 board support ++ * ++ * Copyright (C) 2017 Peng Zhang ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define E750A_V4_GPIO_LED_SYS 14 ++#define E750A_V4_GPIO_LED_LAN 19 ++#define E750A_V4_GPIO_LED_WAN 18 ++#define E750A_V4_GPIO_LED_DS10 15 ++#define E750A_V4_GPIO_LED_DS20 20 ++#define E750A_V4_GPIO_LED_WLAN 21 ++ ++#define E750A_V4_GPIO_BTN_RESET 12 ++ ++#define E750A_V4_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define E750A_V4_KEYS_DEBOUNCE_INTERVAL (3 * E750A_V4_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led e750a_v4_leds_gpio[] __initdata = { ++ { ++ .name = "e750a-v4:green:system", ++ .gpio = E750A_V4_GPIO_LED_SYS, ++ .active_low = 1, ++ }, ++ { ++ .name = "e750a-v4:green:lan", ++ .gpio = E750A_V4_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "e750a-v4:green:wan", ++ .gpio = E750A_V4_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "e750a-v4:green:wlan", ++ .gpio = E750A_V4_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "e750a-v4:green:ds10", ++ .gpio = E750A_V4_GPIO_LED_DS10, ++ .active_low = 1, ++ }, ++ { ++ .name = "e750a-v4:green:ds20", ++ .gpio = E750A_V4_GPIO_LED_DS20, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button e750a_v4_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = E750A_V4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E750A_V4_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++ ++static void __init e750a_v4_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f050400); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f061000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(e750a_v4_leds_gpio), ++ e750a_v4_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, E750A_V4_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(e750a_v4_gpio_keys), ++ e750a_v4_gpio_keys); ++ ++ ath79_register_mdio(1, 0x0); ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ /* GMAC0 is connected to the PHY4 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++ ath79_register_wmac(art, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_E750A_V4, "E750A-V4", "Qxlan E750A v4", ++ e750a_v4_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-e750g-v8.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-e750g-v8.c +new file mode 100644 +index 0000000000..9252d1d5ad +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-e750g-v8.c +@@ -0,0 +1,151 @@ ++/* ++ * Qxwlan E750G v8 board support ++ * ++ * Copyright (C) 2017 Peng Zhang ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-usb.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define E750G_V8_GPIO_LED_SYS 14 ++#define E750G_V8_GPIO_LED_DS20 15 ++#define E750G_V8_GPIO_LED_DS10 20 ++#define E750G_V8_GPIO_LED_WLAN 21 ++ ++#define E750G_V8_GPIO_BTN_RESET 12 ++ ++#define E750G_V8_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define E750G_V8_KEYS_DEBOUNCE_INTERVAL (3 * E750G_V8_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led e750g_v8_leds_gpio[] __initdata = { ++ { ++ .name = "e750g-v8:green:system", ++ .gpio = E750G_V8_GPIO_LED_SYS, ++ .active_low = 1, ++ }, ++ { ++ .name = "e750g-v8:green:ds10", ++ .gpio = E750G_V8_GPIO_LED_DS10, ++ .active_low = 1, ++ }, ++ { ++ .name = "e750g-v8:green:ds20", ++ .gpio = E750G_V8_GPIO_LED_DS20, ++ .active_low = 1, ++ }, ++ { ++ .name = "e750g-v8:green:wlan", ++ .gpio = E750G_V8_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button e750g_v8_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = E750G_V8_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = E750G_V8_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info e750g_v8_leds_qca8334[] = { ++ AR8327_LED_INFO(PHY1_0, HW, "e750g-v8:green:lan"), ++ AR8327_LED_INFO(PHY2_0, HW, "e750g-v8:green:wan"), ++}; ++ ++static struct ar8327_pad_cfg e750g_v8_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++ .mac06_exchange_dis = true, ++}; ++ ++static struct ar8327_led_cfg e750g_v8_ar8327_led_cfg = { ++ .led_ctrl0 = 0x00000000, ++ .led_ctrl1 = 0xc737c737, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x00c30c00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data e750g_v8_ar8327_data = { ++ .pad0_cfg = &e750g_v8_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &e750g_v8_ar8327_led_cfg, ++ .leds = e750g_v8_leds_qca8334, ++ .num_leds = ARRAY_SIZE(e750g_v8_leds_qca8334), ++}; ++ ++static struct mdio_board_info e750g_v8_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &e750g_v8_ar8327_data, ++ }, ++}; ++ ++static void __init e750g_v8_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f050400); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f061000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(e750g_v8_leds_gpio), ++ e750g_v8_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, E750G_V8_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(e750g_v8_gpio_keys), ++ e750g_v8_gpio_keys); ++ ++ mdiobus_register_board_info(e750g_v8_mdio0_info, ++ ARRAY_SIZE(e750g_v8_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ /* GMAC0 is connected to an AR8327 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++ ath79_register_wmac(art, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_E750G_V8, "E750G-V8", "Qxwlan E750G v8", ++ e750g_v8_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-eap120.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-eap120.c +new file mode 100644 +index 0000000000..130c7706a6 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-eap120.c +@@ -0,0 +1,126 @@ ++/* ++ * TP-LINK EAP120 board support ++ * ++ * Copyright (C) 2016 Henryk Heisig ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++#define EAP120_GPIO_LED_RED 12 ++#define EAP120_GPIO_LED_YEL 13 ++#define EAP120_GPIO_LED_GRN 15 ++#define EAP120_GPIO_BTN_RESET 4 ++ ++#define EAP120_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define EAP120_KEYS_DEBOUNCE_INTERVAL (3 * EAP120_KEYS_POLL_INTERVAL) ++ ++#define EAP120_GPIO_SMI_MDIO 16 ++#define EAP120_GPIO_SMI_MDC 17 ++ ++#define EAP120_LAN_PHYADDR 4 ++ ++static struct gpio_led eap120_leds_gpio[] __initdata = { ++ { ++ .name = "eap120:red:system", ++ .gpio = EAP120_GPIO_LED_RED, ++ .active_low = 1, ++ }, { ++ .name = "eap120:yellow:system", ++ .gpio = EAP120_GPIO_LED_YEL, ++ .active_low = 1, ++ }, { ++ .name = "eap120:green:system", ++ .gpio = EAP120_GPIO_LED_GRN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button eap120_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = EAP120_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EAP120_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct mdio_gpio_platform_data eap120_mdio = { ++ .mdc = EAP120_GPIO_SMI_MDC, ++ .mdio = EAP120_GPIO_SMI_MDIO, ++ .phy_mask = ~BIT(EAP120_LAN_PHYADDR), ++}; ++ ++static struct at803x_platform_data eap120_ar8035_data = { ++ .disable_smarteee = 0, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 0, ++ .fixup_rgmii_tx_delay = 1, ++}; ++ ++static struct platform_device eap120_phy_device = { ++ .name = "mdio-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &eap120_mdio, &eap120_ar8035_data ++ }, ++}; ++ ++static void __init eap_setup(u8 *mac) ++{ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(eap120_leds_gpio), ++ eap120_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, EAP120_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(eap120_gpio_keys), ++ eap120_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ++ /* MDIO Interface */ ++ platform_device_register(&eap120_phy_device); ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ++ /* GMAC0 is connected to the RGMII interface to an Atheros AR8035-A */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.mii_bus_dev = &eap120_phy_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(EAP120_LAN_PHYADDR); ++ ath79_eth0_pll_data.pll_1000 = 0x0e000000; ++ ath79_eth0_pll_data.pll_100 = 0x00000101; ++ ath79_eth0_pll_data.pll_10 = 0x00001313; ++ ath79_register_eth(0); ++} ++ ++static void __init eap120_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f030008); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ eap_setup(mac); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_EAP120, "EAP120", "TP-LINK EAP120", ++ eap120_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-eap300v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-eap300v2.c +new file mode 100644 +index 0000000000..ba577e2517 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-eap300v2.c +@@ -0,0 +1,101 @@ ++/* ++ * EnGenius EAP300 v2 board support ++ * ++ * Copyright (C) 2014 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. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define EAP300V2_GPIO_LED_POWER 0 ++#define EAP300V2_GPIO_LED_LAN 16 ++#define EAP300V2_GPIO_LED_WLAN 17 ++ ++#define EAP300V2_GPIO_BTN_RESET 1 ++ ++#define EAP300V2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define EAP300V2_KEYS_DEBOUNCE_INTERVAL (3 * EAP300V2_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led eap300v2_leds_gpio[] __initdata = { ++ { ++ .name = "engenius:blue:power", ++ .gpio = EAP300V2_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "engenius:blue:lan", ++ .gpio = EAP300V2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "engenius:blue:wlan", ++ .gpio = EAP300V2_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button eap300v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = EAP300V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EAP300V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++#define EAP300V2_ART_MAC_OFFSET 2 ++ ++#define EAP300V2_LAN_PHYMASK BIT(0) ++ ++static void __init eap300v2_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff1000); ++ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_gpio_output_select(EAP300V2_GPIO_LED_POWER, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(EAP300V2_GPIO_LED_LAN, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(EAP300V2_GPIO_LED_WLAN, AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(eap300v2_leds_gpio), ++ eap300v2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, EAP300V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(eap300v2_gpio_keys), ++ eap300v2_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_wmac(art, NULL); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + EAP300V2_ART_MAC_OFFSET, 0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = EAP300V2_LAN_PHYMASK; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = EAP300V2_LAN_PHYMASK; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_EAP300V2, "EAP300V2", "EnGenius EAP300 v2", ++ eap300v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-eap7660d.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-eap7660d.c +new file mode 100644 +index 0000000000..787e6275d6 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-eap7660d.c +@@ -0,0 +1,181 @@ ++/* ++ * Senao EAP7660D board support ++ * ++ * Copyright (C) 2010 Daniel Golle ++ * Copyright (C) 2008 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define EAP7660D_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define EAP7660D_KEYS_DEBOUNCE_INTERVAL (3 * EAP7660D_KEYS_POLL_INTERVAL) ++ ++#define EAP7660D_GPIO_DS4 7 ++#define EAP7660D_GPIO_DS5 2 ++#define EAP7660D_GPIO_DS7 0 ++#define EAP7660D_GPIO_DS8 4 ++#define EAP7660D_GPIO_SW1 3 ++#define EAP7660D_GPIO_SW3 8 ++#define EAP7660D_PHYMASK BIT(20) ++#define EAP7660D_BOARDCONFIG 0x1F7F0000 ++#define EAP7660D_GBIC_MAC_OFFSET 0x1000 ++#define EAP7660D_WMAC0_MAC_OFFSET 0x1010 ++#define EAP7660D_WMAC1_MAC_OFFSET 0x1016 ++#define EAP7660D_WMAC0_CALDATA_OFFSET 0x2000 ++#define EAP7660D_WMAC1_CALDATA_OFFSET 0x3000 ++ ++#ifdef CONFIG_PCI ++static struct ath5k_platform_data eap7660d_wmac0_data; ++static struct ath5k_platform_data eap7660d_wmac1_data; ++static char eap7660d_wmac0_mac[6]; ++static char eap7660d_wmac1_mac[6]; ++static u16 eap7660d_wmac0_eeprom[ATH5K_PLAT_EEP_MAX_WORDS]; ++static u16 eap7660d_wmac1_eeprom[ATH5K_PLAT_EEP_MAX_WORDS]; ++ ++static int eap7660d_pci_plat_dev_init(struct pci_dev *dev) ++{ ++ switch (PCI_SLOT(dev->devfn)) { ++ case 17: ++ dev->dev.platform_data = &eap7660d_wmac0_data; ++ break; ++ ++ case 18: ++ dev->dev.platform_data = &eap7660d_wmac1_data; ++ break; ++ } ++ ++ return 0; ++} ++ ++void __init eap7660d_pci_init(u8 *cal_data0, u8 *mac_addr0, ++ u8 *cal_data1, u8 *mac_addr1) ++{ ++ if (cal_data0 && *cal_data0 == 0xa55a) { ++ memcpy(eap7660d_wmac0_eeprom, cal_data0, ++ ATH5K_PLAT_EEP_MAX_WORDS); ++ eap7660d_wmac0_data.eeprom_data = eap7660d_wmac0_eeprom; ++ } ++ ++ if (cal_data1 && *cal_data1 == 0xa55a) { ++ memcpy(eap7660d_wmac1_eeprom, cal_data1, ++ ATH5K_PLAT_EEP_MAX_WORDS); ++ eap7660d_wmac1_data.eeprom_data = eap7660d_wmac1_eeprom; ++ } ++ ++ if (mac_addr0) { ++ memcpy(eap7660d_wmac0_mac, mac_addr0, ++ sizeof(eap7660d_wmac0_mac)); ++ eap7660d_wmac0_data.macaddr = eap7660d_wmac0_mac; ++ } ++ ++ if (mac_addr1) { ++ memcpy(eap7660d_wmac1_mac, mac_addr1, ++ sizeof(eap7660d_wmac1_mac)); ++ eap7660d_wmac1_data.macaddr = eap7660d_wmac1_mac; ++ } ++ ++ ath79_pci_set_plat_dev_init(eap7660d_pci_plat_dev_init); ++ ath79_register_pci(); ++} ++#else ++static inline void eap7660d_pci_init(u8 *cal_data0, u8 *mac_addr0, ++ u8 *cal_data1, u8 *mac_addr1) ++{ ++} ++#endif /* CONFIG_PCI */ ++ ++static struct gpio_led eap7660d_leds_gpio[] __initdata = { ++ { ++ .name = "eap7660d:green:ds8", ++ .gpio = EAP7660D_GPIO_DS8, ++ .active_low = 0, ++ }, ++ { ++ .name = "eap7660d:green:ds5", ++ .gpio = EAP7660D_GPIO_DS5, ++ .active_low = 0, ++ }, ++ { ++ .name = "eap7660d:green:ds7", ++ .gpio = EAP7660D_GPIO_DS7, ++ .active_low = 0, ++ }, ++ { ++ .name = "eap7660d:green:ds4", ++ .gpio = EAP7660D_GPIO_DS4, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button eap7660d_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = EAP7660D_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EAP7660D_GPIO_SW1, ++ .active_low = 1, ++ }, ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = EAP7660D_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EAP7660D_GPIO_SW3, ++ .active_low = 1, ++ } ++}; ++ ++static const char *eap7660d_part_probes[] = { ++ "RedBoot", ++ NULL, ++}; ++ ++static struct flash_platform_data eap7660d_flash_data = { ++ .part_probes = eap7660d_part_probes, ++}; ++ ++static void __init eap7660d_setup(void) ++{ ++ u8 *boardconfig = (u8 *) KSEG1ADDR(EAP7660D_BOARDCONFIG); ++ ++ ath79_register_mdio(0, ~EAP7660D_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ boardconfig + EAP7660D_GBIC_MAC_OFFSET, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = EAP7660D_PHYMASK; ++ ath79_register_eth(0); ++ ath79_register_m25p80(&eap7660d_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(eap7660d_leds_gpio), ++ eap7660d_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, EAP7660D_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(eap7660d_gpio_keys), ++ eap7660d_gpio_keys); ++ eap7660d_pci_init(boardconfig + EAP7660D_WMAC0_CALDATA_OFFSET, ++ boardconfig + EAP7660D_WMAC0_MAC_OFFSET, ++ boardconfig + EAP7660D_WMAC1_CALDATA_OFFSET, ++ boardconfig + EAP7660D_WMAC1_MAC_OFFSET); ++}; ++ ++MIPS_MACHINE(ATH79_MACH_EAP7660D, "EAP7660D", "Senao EAP7660D", ++ eap7660d_setup); ++ ++MIPS_MACHINE(ATH79_MACH_ALL0305, "ALL0305", "Allnet ALL0305", ++ eap7660d_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-el-m150.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-el-m150.c +new file mode 100644 +index 0000000000..b95d6c2f68 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-el-m150.c +@@ -0,0 +1,112 @@ ++/* ++ * Easy-Link EL-M150 board support ++ * ++ * Copyright (C) 2012 huangfc ++ * Copyright (C) 2012 HYS <550663898@qq.com> ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "dev-usb.h" ++ ++#define EL_M150_GPIO_BTN6 6 ++#define EL_M150_GPIO_BTN7 7 ++#define EL_M150_GPIO_BTN_RESET 11 ++ ++#define EL_M150_GPIO_LED_SYSTEM 27 ++#define EL_M150_GPIO_USB_POWER 8 ++ ++#define EL_M150_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define EL_M150_KEYS_DEBOUNCE_INTERVAL (3 * EL_M150_KEYS_POLL_INTERVAL) ++ ++static const char *EL_M150_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data EL_M150_flash_data = { ++ .part_probes = EL_M150_part_probes, ++}; ++ ++static struct gpio_led EL_M150_leds_gpio[] __initdata = { ++ { ++ .name = "easylink:green:system", ++ .gpio = EL_M150_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button EL_M150_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = EL_M150_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EL_M150_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++ { ++ .desc = "BTN_6", ++ .type = EV_KEY, ++ .code = BTN_6, ++ .debounce_interval = EL_M150_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EL_M150_GPIO_BTN6, ++ .active_low = 1, ++ }, ++ { ++ .desc = "BTN_7", ++ .type = EV_KEY, ++ .code = BTN_7, ++ .debounce_interval = EL_M150_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EL_M150_GPIO_BTN7, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init el_m150_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(EL_M150_leds_gpio), ++ EL_M150_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, EL_M150_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(EL_M150_gpio_keys), ++ EL_M150_gpio_keys); ++ ++ gpio_request_one(EL_M150_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(&EL_M150_flash_data); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_EL_M150, "EL-M150", ++ "EasyLink EL-M150", el_m150_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-el-mini.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-el-mini.c +new file mode 100644 +index 0000000000..9879b18f7c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-el-mini.c +@@ -0,0 +1,86 @@ ++/* ++ * Easy-Link EL-MINI board support ++ * ++ * Copyright (C) 2012 huangfc ++ * Copyright (C) 2011 hys <550663898@qq.com> ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define MINI_GPIO_LED_SYSTEM 27 ++#define MINI_GPIO_BTN_RESET 11 ++ ++#define MINI_GPIO_USB_POWER 8 ++ ++#define MINI_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MINI_KEYS_DEBOUNCE_INTERVAL (3 * MINI_KEYS_POLL_INTERVAL) ++ ++static const char *mini_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data mini_flash_data = { ++ .part_probes = mini_part_probes, ++}; ++ ++static struct gpio_led mini_leds_gpio[] __initdata = { ++ { ++ .name = "easylink:green:system", ++ .gpio = MINI_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button mini_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MINI_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MINI_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static void __init el_mini_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&mini_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mini_leds_gpio), ++ mini_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, MINI_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mini_gpio_keys), ++ mini_gpio_keys); ++ ++ gpio_request_one(MINI_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_EL_MINI, "EL-MINI", "EasyLink EL-MINI", ++ el_mini_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ens202ext.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ens202ext.c +new file mode 100644 +index 0000000000..07dbc2e69d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ens202ext.c +@@ -0,0 +1,124 @@ ++/* ++ * EnGenius ENS202EXT board support ++ * ++ * Copyright (C) 2017 Marty Plummer ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define ENS202_GPIO_LED_WLAN4 0 ++#define ENS202_GPIO_LED_POWER 14 ++#define ENS202_GPIO_LED_WLAN2 16 ++#define ENS202_GPIO_LED_WLAN3 17 ++#define ENS202_GPIO_LED_WLAN1 18 ++ ++#define ENS202_GPIO_BTN_RESET 1 ++ ++#define ENS202_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ENS202_KEYS_DEBOUNCE_INTERVAL (3 * ENS202_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led ens202_leds_gpio[] __initdata = { ++ { ++ .name = "engenius:amber:wlan1", ++ .gpio = ENS202_GPIO_LED_WLAN1, ++ .active_low = 1, ++ }, { ++ .name = "engenius:red:wlan2", ++ .gpio = ENS202_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, { ++ .name = "engenius:amber:wlan3", ++ .gpio = ENS202_GPIO_LED_WLAN3, ++ .active_low = 1, ++ }, { ++ .name = "engenius:green:wlan4", ++ .gpio = ENS202_GPIO_LED_WLAN4, ++ .active_low = 1, ++ }, { ++ .name = "engenius:amber:power", ++ .gpio = ENS202_GPIO_LED_POWER, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button ens202_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ENS202_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ENS202_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init ens202_setup(void) ++{ ++ const char *nvram = (char *) KSEG1ADDR(0x1f040000); ++ u8 mac_buff[6]; ++ u8 *mac = NULL; ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ if (ath79_nvram_parse_mac_addr(nvram, 0x10000, ++ "ethaddr=", mac_buff) == 0) { ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac_buff, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac_buff, 1); ++ mac = mac_buff; ++ } ++ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_gpio_output_select(ENS202_GPIO_LED_POWER, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(ENS202_GPIO_LED_WLAN1, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(ENS202_GPIO_LED_WLAN2, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(ENS202_GPIO_LED_WLAN3, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(ENS202_GPIO_LED_WLAN4, AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ens202_leds_gpio), ++ ens202_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, ENS202_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ens202_gpio_keys), ++ ens202_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_wmac(art + 0x1000, NULL); ++ ++ ath79_register_mdio(1, 0); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ENS202EXT, "ENS202EXT", "EnGenius ENS202EXT", ++ ens202_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-epg5000.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-epg5000.c +new file mode 100644 +index 0000000000..89d6ec6fe3 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-epg5000.c +@@ -0,0 +1,177 @@ ++/* ++ * EnGenius EPG5000 board support ++ * ++ * Copyright (c) 2014 Jon Suphammer ++ * Copyright (c) 2015 Christian Beier ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define EPG5000_GPIO_LED_WLAN_5G 23 ++#define EPG5000_GPIO_LED_WLAN_2G 13 ++#define EPG5000_GPIO_LED_POWER_AMBER 2 ++#define EPG5000_GPIO_LED_WPS_AMBER 22 ++#define EPG5000_GPIO_LED_WPS_BLUE 19 ++ ++#define EPG5000_GPIO_BTN_WPS 16 ++#define EPG5000_GPIO_BTN_RESET 17 ++ ++#define EPG5000_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define EPG5000_KEYS_DEBOUNCE_INTERVAL (3 * EPG5000_KEYS_POLL_INTERVAL) ++ ++#define EPG5000_CALDATA_ADDR 0x1fff0000 ++#define EPG5000_WMAC_CALDATA_OFFSET 0x1000 ++#define EPG5000_PCIE_CALDATA_OFFSET 0x5000 ++ ++#define EPG5000_NVRAM_ADDR 0x1f030000 ++#define EPG5000_NVRAM_SIZE 0x10000 ++ ++static struct gpio_led epg5000_leds_gpio[] __initdata = { ++ { ++ .name = "epg5000:amber:power", ++ .gpio = EPG5000_GPIO_LED_POWER_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "epg5000:blue:wps", ++ .gpio = EPG5000_GPIO_LED_WPS_BLUE, ++ .active_low = 1, ++ }, ++ { ++ .name = "epg5000:amber:wps", ++ .gpio = EPG5000_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "epg5000:blue:wlan-2g", ++ .gpio = EPG5000_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "epg5000:blue:wlan-5g", ++ .gpio = EPG5000_GPIO_LED_WLAN_5G, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button epg5000_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = EPG5000_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EPG5000_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = EPG5000_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = EPG5000_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg epg5000_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data epg5000_ar8327_data = { ++ .pad0_cfg = &epg5000_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info epg5000_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &epg5000_ar8327_data, ++ }, ++}; ++ ++static int epg5000_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(EPG5000_NVRAM_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, EPG5000_NVRAM_SIZE, ++ name, mac); ++ if (err) { ++ pr_err("no MAC address found for %s\n", name); ++ return false; ++ } ++ ++ return true; ++} ++ ++static void __init epg5000_setup(void) ++{ ++ u8 *caldata = (u8 *) KSEG1ADDR(EPG5000_CALDATA_ADDR); ++ u8 mac1[ETH_ALEN]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(epg5000_leds_gpio), ++ epg5000_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, EPG5000_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(epg5000_gpio_keys), ++ epg5000_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(epg5000_mdio0_info, ++ ARRAY_SIZE(epg5000_mdio0_info)); ++ ++ /* GMAC0 is connected to an QCA8327N switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ if (epg5000_get_mac("ethaddr=", mac1)) ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(caldata + EPG5000_WMAC_CALDATA_OFFSET, mac1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_EPG5000, "EPG5000", ++ "EnGenius EPG5000", ++ epg5000_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-esr1750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-esr1750.c +new file mode 100644 +index 0000000000..c275ef6f1b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-esr1750.c +@@ -0,0 +1,176 @@ ++/* ++ * EnGenius ESR1750 board support ++ * ++ * Copyright (c) 2014 Jon Suphammer ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define ESR1750_GPIO_LED_WLAN_5G 23 ++#define ESR1750_GPIO_LED_WLAN_2G 13 ++#define ESR1750_GPIO_LED_POWER_AMBER 2 ++#define ESR1750_GPIO_LED_WPS_AMBER 22 ++#define ESR1750_GPIO_LED_WPS_BLUE 19 ++ ++#define ESR1750_GPIO_BTN_WPS 16 ++#define ESR1750_GPIO_BTN_RESET 17 ++ ++#define ESR1750_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ESR1750_KEYS_DEBOUNCE_INTERVAL (3 * ESR1750_KEYS_POLL_INTERVAL) ++ ++#define ESR1750_CALDATA_ADDR 0x1fff0000 ++#define ESR1750_WMAC_CALDATA_OFFSET 0x1000 ++#define ESR1750_PCIE_CALDATA_OFFSET 0x5000 ++ ++#define ESR1750_NVRAM_ADDR 0x1f030000 ++#define ESR1750_NVRAM_SIZE 0x10000 ++ ++static struct gpio_led esr1750_leds_gpio[] __initdata = { ++ { ++ .name = "esr1750:amber:power", ++ .gpio = ESR1750_GPIO_LED_POWER_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "esr1750:blue:wps", ++ .gpio = ESR1750_GPIO_LED_WPS_BLUE, ++ .active_low = 1, ++ }, ++ { ++ .name = "esr1750:amber:wps", ++ .gpio = ESR1750_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "esr1750:blue:wlan-2g", ++ .gpio = ESR1750_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "esr1750:blue:wlan-5g", ++ .gpio = ESR1750_GPIO_LED_WLAN_5G, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button esr1750_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ESR1750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ESR1750_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ESR1750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ESR1750_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg esr1750_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data esr1750_ar8327_data = { ++ .pad0_cfg = &esr1750_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info esr1750_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &esr1750_ar8327_data, ++ }, ++}; ++ ++static int esr1750_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(ESR1750_NVRAM_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, ESR1750_NVRAM_SIZE, ++ name, mac); ++ if (err) { ++ pr_err("no MAC address found for %s\n", name); ++ return false; ++ } ++ ++ return true; ++} ++ ++static void __init esr1750_setup(void) ++{ ++ u8 *caldata = (u8 *) KSEG1ADDR(ESR1750_CALDATA_ADDR); ++ u8 mac1[ETH_ALEN]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(esr1750_leds_gpio), ++ esr1750_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, ESR1750_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(esr1750_gpio_keys), ++ esr1750_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(esr1750_mdio0_info, ++ ARRAY_SIZE(esr1750_mdio0_info)); ++ ++ /* GMAC0 is connected to an QCA8327N switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ if (esr1750_get_mac("ethaddr=", mac1)) ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(caldata + ESR1750_WMAC_CALDATA_OFFSET, mac1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ESR1750, "ESR1750", ++ "EnGenius ESR1750", ++ esr1750_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-esr900.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-esr900.c +new file mode 100644 +index 0000000000..cf2ee9295a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-esr900.c +@@ -0,0 +1,200 @@ ++/* ++ * EnGenius ESR900 board support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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. ++ */ ++ ++#define pr_fmt(fmt) "esr900: " fmt ++ ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define ESR900_GPIO_LED_POWER 2 ++#define ESR900_GPIO_LED_WLAN_2G 13 ++#define ESR900_GPIO_LED_WPS_BLUE 19 ++#define ESR900_GPIO_LED_WPS_AMBER 22 ++#define ESR900_GPIO_LED_WLAN_5G 23 ++ ++#define ESR900_GPIO_BTN_WPS 16 ++#define ESR900_GPIO_BTN_RESET 17 ++ ++#define ESR900_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ESR900_KEYS_DEBOUNCE_INTERVAL (3 * ESR900_KEYS_POLL_INTERVAL) ++ ++#define ESR900_CALDATA_ADDR 0x1fff0000 ++#define ESR900_WMAC_CALDATA_OFFSET 0x1000 ++#define ESR900_PCIE_CALDATA_OFFSET 0x5000 ++ ++#define ESR900_CONFIG_ADDR 0x1f030000 ++#define ESR900_CONFIG_SIZE 0x10000 ++ ++#define ESR900_LAN_PHYMASK BIT(0) ++#define ESR900_WAN_PHYMASK BIT(5) ++#define ESR900_MDIO_MASK (~(ESR900_LAN_PHYMASK | ESR900_WAN_PHYMASK)) ++ ++static struct gpio_led esr900_leds_gpio[] __initdata = { ++ { ++ .name = "engenius:amber:power", ++ .gpio = ESR900_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "engenius:blue:wlan-2g", ++ .gpio = ESR900_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "engenius:blue:wps", ++ .gpio = ESR900_GPIO_LED_WPS_BLUE, ++ .active_low = 1, ++ }, ++ { ++ .name = "engenius:amber:wps", ++ .gpio = ESR900_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "engenius:blue:wlan-5g", ++ .gpio = ESR900_GPIO_LED_WLAN_5G, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button esr900_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ESR900_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ESR900_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ESR900_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ESR900_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg esr900_ar8327_pad0_cfg = { ++ /* GMAC0 of the AR8337 switch is connected to GMAC0 via RGMII */ ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_pad_cfg esr900_ar8327_pad6_cfg = { ++ /* GMAC6 of the AR8337 switch is connected to GMAC1 via SGMII */ ++ .mode = AR8327_PAD_MAC_SGMII, ++ .rxclk_delay_en = true, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++}; ++ ++static struct ar8327_platform_data esr900_ar8327_data = { ++ .pad0_cfg = &esr900_ar8327_pad0_cfg, ++ .pad6_cfg = &esr900_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info esr900_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &esr900_ar8327_data, ++ }, ++}; ++ ++static void __init esr900_setup(void) ++{ ++ const char *config = (char *) KSEG1ADDR(ESR900_CONFIG_ADDR); ++ u8 *art = (u8 *) KSEG1ADDR(ESR900_CALDATA_ADDR); ++ u8 lan_mac[ETH_ALEN]; ++ u8 wlan0_mac[ETH_ALEN]; ++ u8 wlan1_mac[ETH_ALEN]; ++ ++ if (ath79_nvram_parse_mac_addr(config, ESR900_CONFIG_SIZE, ++ "ethaddr=", lan_mac) == 0) { ++ ath79_init_local_mac(ath79_eth0_data.mac_addr, lan_mac); ++ ath79_init_mac(wlan0_mac, lan_mac, 0); ++ ath79_init_mac(wlan1_mac, lan_mac, 1); ++ } else { ++ pr_err("could not find ethaddr in u-boot environment\n"); ++ } ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(esr900_leds_gpio), ++ esr900_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, ESR900_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(esr900_gpio_keys), ++ esr900_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + ESR900_WMAC_CALDATA_OFFSET, wlan0_mac); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(esr900_mdio0_info, ++ ARRAY_SIZE(esr900_mdio0_info)); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = ESR900_LAN_PHYMASK; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ath79_register_eth(1); ++ ++ ap91_pci_init(art + ESR900_PCIE_CALDATA_OFFSET, wlan1_mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ESR900, "ESR900", "EnGenius ESR900", esr900_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ew-balin.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ew-balin.c +new file mode 100644 +index 0000000000..2e82ffdaa1 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ew-balin.c +@@ -0,0 +1,110 @@ ++/* ++ * EW Balin board support ++ * (based on Atheros DB120 reference board support) ++ * ++ * Copyright (c) 2011 Qualcomm Atheros ++ * Copyright (c) 2011-2012 Gabor Juhos ++ * Copyright (C) 2017 Embedded Wireless GmbH www.80211.de ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define BALIN_GPIO_LED_STATUS 14 ++ ++#define BALIN_GPIO_BTN_WPS 18 ++ ++#define BALIN_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define BALIN_KEYS_DEBOUNCE_INTERVAL (3 * BALIN_KEYS_POLL_INTERVAL) ++ ++#define BALIN_CALDATA_OFFSET 0x1000 ++#define BALIN_WMAC_MAC_OFFSET (BALIN_CALDATA_OFFSET + 0x02) ++ ++static struct gpio_led balin_leds_gpio[] __initdata = { ++ { ++ .name = "balin:green:status", ++ .gpio = BALIN_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button balin_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = BALIN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = BALIN_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, ++}; ++ ++ ++static void __init balin_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ static u8 mac[6]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(balin_leds_gpio), ++ balin_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, BALIN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(balin_gpio_keys), ++ balin_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + BALIN_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ memcpy(mac, art + BALIN_WMAC_MAC_OFFSET, sizeof(mac)); ++ mac[3] |= 0x40; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_EW_BALIN, "EW-BALIN", "EmbWir-Balin", ++ balin_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ew-dorin.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ew-dorin.c +new file mode 100644 +index 0000000000..5544596f91 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ew-dorin.c +@@ -0,0 +1,138 @@ ++/* ++ * EW Dorin board support ++ * (based on Atheros Ref. Design AP121) ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2012-2017 Embedded Wireless GmbH www.80211.de ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DORIN_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DORIN_KEYS_DEBOUNCE_INTERVAL (3 * DORIN_KEYS_POLL_INTERVAL) ++ ++#define DORIN_CALDATA_OFFSET 0x1000 ++#define DORIN_WMAC_MAC_OFFSET 0x1002 ++ ++#define DORIN_GPIO_LED_STATUS 21 ++ ++#define DORIN_GPIO_BTN_JUMPSTART 11 ++#define DORIN_GPIO_BTN_RESET 6 ++ ++static struct gpio_led dorin_leds_gpio[] __initdata = { ++ { ++ .name = "dorin:green:status", ++ .gpio = DORIN_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button dorin_gpio_keys[] __initdata = { ++ { ++ .desc = "jumpstart button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DORIN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DORIN_GPIO_BTN_JUMPSTART, ++ .active_low = 0, ++ }, ++ { ++ .desc = "reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DORIN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DORIN_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static void __init ew_dorin_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ static u8 mac[6]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_usb(); ++ ++ if (ar93xx_wmac_read_mac_address(mac)) { ++ ath79_register_wmac(NULL, NULL); ++ } else { ++ ath79_register_wmac(art + DORIN_CALDATA_OFFSET, ++ art + DORIN_WMAC_MAC_OFFSET); ++ memcpy(mac, art + DORIN_WMAC_MAC_OFFSET, sizeof(mac)); ++ } ++ ++ mac[3] |= 0x40; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dorin_leds_gpio), ++ dorin_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DORIN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dorin_gpio_keys), ++ dorin_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_EW_DORIN, "EW-DORIN", "EmbWir-Dorin", ++ ew_dorin_setup); ++ ++ ++static void __init ew_dorin_router_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ static u8 mac[6]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_usb(); ++ ++ if (ar93xx_wmac_read_mac_address(mac)) { ++ ath79_register_wmac(NULL, NULL); ++ } else { ++ ath79_register_wmac(art + DORIN_CALDATA_OFFSET, ++ art + DORIN_WMAC_MAC_OFFSET); ++ memcpy(mac, art + DORIN_WMAC_MAC_OFFSET, sizeof(mac)); ++ } ++ ++ mac[3] |= 0x40; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ mac[3] &= 0x3F; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_setup_ar933x_phy4_switch(true, true); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(dorin_leds_gpio), ++ dorin_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DORIN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(dorin_gpio_keys), ++ dorin_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_EW_DORIN_ROUTER, "EW-DORIN-ROUTER", ++ "EmbWir-Dorin-Router", ew_dorin_router_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-f9k1115v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-f9k1115v2.c +new file mode 100644 +index 0000000000..232105e068 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-f9k1115v2.c +@@ -0,0 +1,189 @@ ++/* ++ * Belkin AC1750DB (F9K1115V2) board support ++ * ++ * Copyright (C) 2014 Gabor Juhos ++ * Copyright (C) 2014 Imre Kaloz ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define F9K1115V2_GPIO_LED_USB2 4 ++#define F9K1115V2_GPIO_LED_WPS_AMBER 14 ++#define F9K1115V2_GPIO_LED_STATUS_AMBER 15 ++#define F9K1115V2_GPIO_LED_WPS_BLUE 19 ++#define F9K1115V2_GPIO_LED_STATUS_BLUE 20 ++ ++#define F9K1115V2_GPIO_BTN_WPS 16 ++#define F9K1115V2_GPIO_BTN_RESET 17 ++ ++#define F9K1115V2_GPIO_USB2_POWER 21 ++ ++#define F9K1115V2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define F9K1115V2_KEYS_DEBOUNCE_INTERVAL (3 * F9K1115V2_KEYS_POLL_INTERVAL) ++ ++#define F9K1115V2_WAN_MAC_OFFSET 0 ++#define F9K1115V2_LAN_MAC_OFFSET 6 ++#define F9K1115V2_WMAC_CALDATA_OFFSET 0x1000 ++#define F9K1115V2_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led f9k1115v2_leds_gpio[] __initdata = { ++ { ++ .name = "belkin:amber:status", ++ .gpio = F9K1115V2_GPIO_LED_STATUS_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "belkin:blue:status", ++ .gpio = F9K1115V2_GPIO_LED_STATUS_BLUE, ++ .active_low = 1, ++ }, ++ { ++ .name = "belkin:blue:wps", ++ .gpio = F9K1115V2_GPIO_LED_WPS_BLUE, ++ .active_low = 1, ++ }, ++ { ++ .name = "belkin:amber:wps", ++ .gpio = F9K1115V2_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "belkin:green:usb2", ++ .gpio = F9K1115V2_GPIO_LED_USB2, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button f9k1115v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = F9K1115V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = F9K1115V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = F9K1115V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = F9K1115V2_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg f9k1115v2_ar8327_pad0_cfg = { ++ /* Use the RGMII interface for the GMAC0 of the AR8337 switch */ ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_pad_cfg f9k1115v2_ar8327_pad6_cfg = { ++ /* Use the SGMII interface for the GMAC6 of the AR8337 switch */ ++ .mode = AR8327_PAD_MAC_SGMII, ++ .rxclk_delay_en = true, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++}; ++ ++static struct ar8327_platform_data f9k1115v2_ar8327_data = { ++ .pad0_cfg = &f9k1115v2_ar8327_pad0_cfg, ++ .pad6_cfg = &f9k1115v2_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info f9k1115v2_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &f9k1115v2_ar8327_data, ++ }, ++}; ++ ++static void __init f9k1115v2_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(f9k1115v2_leds_gpio), ++ f9k1115v2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, F9K1115V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(f9k1115v2_gpio_keys), ++ f9k1115v2_gpio_keys); ++ ++ ath79_register_wmac(art + F9K1115V2_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(f9k1115v2_mdio0_info, ++ ARRAY_SIZE(f9k1115v2_mdio0_info)); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + F9K1115V2_WAN_MAC_OFFSET, 0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ++ art + F9K1115V2_LAN_MAC_OFFSET, 0); ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++ ++ ath79_register_usb(); ++ gpio_request_one(F9K1115V2_GPIO_USB2_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB2 power"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_F9K1115V2, "F9K1115V2", "Belkin AC1750DB", ++ f9k1115v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz300e.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz300e.c +new file mode 100644 +index 0000000000..43af71a0a8 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz300e.c +@@ -0,0 +1,132 @@ ++/* ++ * AVM FRITZ!WLAN Repeater 300E board support ++ * ++ * Copyright (C) 2017 Mathias Kresin ++ * ++ * 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 "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define FRITZ300E_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define FRITZ300E_KEYS_DEBOUNCE_INTERVAL (3 * FRITZ300E_KEYS_POLL_INTERVAL) ++ ++static struct mtd_partition fritz300e_flash_partitions[] = { ++ { ++ .name = "urloader", ++ .offset = 0, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0020000, ++ .size = 0x0ee0000, ++ }, { ++ .name = "tffs (1)", ++ .offset = 0x0f00000, ++ .size = 0x0080000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "tffs (2)", ++ .offset = 0x0f80000, ++ .size = 0x0080000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++ ++static struct flash_platform_data fritz300e_flash_data = { ++ .parts = fritz300e_flash_partitions, ++ .nr_parts = ARRAY_SIZE(fritz300e_flash_partitions), ++}; ++ ++static struct gpio_led fritz300e_leds_gpio[] __initdata = { ++ { ++ .name = "fritz300e:green:power", ++ .gpio = 13, ++ .active_low = 1, ++ }, { ++ .name = "fritz300e:green:lan", ++ .gpio = 15, ++ .active_low = 1, ++ }, { ++ .name = "fritz300e:green:wlan", ++ .gpio = 16, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led fritz300e_wmac_leds_gpio[] = { ++ { ++ .name = "fritz300e:green:rssi0", ++ .gpio = 10, ++ .active_low = 1, ++ }, { ++ .name = "fritz300e:green:rssi1", ++ .gpio = 4, ++ .active_low = 1, ++ }, { ++ .name = "fritz300e:green:rssi2", ++ .gpio = 6, ++ .active_low = 1, ++ }, { ++ .name = "fritz300e:green:rssi3", ++ .gpio = 7, ++ .active_low = 1, ++ }, { ++ .name = "fritz300e:green:rssi4", ++ .gpio = 5, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button fritz300e_gpio_keys[] __initdata = { ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = FRITZ300E_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 12, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init fritz300e_setup(void) ++{ ++ /* get the Lantiq PEF7071V phy out of reset */ ++ gpio_request_one(11, GPIOF_OUT_INIT_HIGH, "phy reset"); ++ ++ ath79_register_m25p80(&fritz300e_flash_data); ++ ++ ath79_register_mdio(0, ~(BIT(0))); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(fritz300e_leds_gpio), ++ fritz300e_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, FRITZ300E_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(fritz300e_gpio_keys), ++ fritz300e_gpio_keys); ++ ++ ap9x_pci_setup_wmac_leds(0, fritz300e_wmac_leds_gpio, ++ ARRAY_SIZE(fritz300e_wmac_leds_gpio)); ++ ap91_pci_init_simple(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_FRITZ300E, "FRITZ300E", ++ "AVM FRITZ!WLAN Repeater 300E", fritz300e_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz4020.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz4020.c +new file mode 100644 +index 0000000000..c00cf681b2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz4020.c +@@ -0,0 +1,242 @@ ++/* ++ * AVM FRITZ!Box 4020 board support ++ * ++ * Copyright (C) 2018 David Bauer ++ * ++ * 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 ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++#define FRITZ4020_GPIO_SHIFT_SER 19 /* DS, Data Serial Input */ ++#define FRITZ4020_GPIO_SHIFT_SRCLK 20 /* SHCP, Shift Reg Clock Input */ ++ ++#define FRITZ4020_SSR_BIT_0 0 ++#define FRITZ4020_SSR_BIT_1 1 ++#define FRITZ4020_SSR_BIT_2 2 ++#define FRITZ4020_SSR_BIT_3 3 ++#define FRITZ4020_SSR_BIT_4 4 ++#define FRITZ4020_SSR_BIT_5 5 ++#define FRITZ4020_SSR_BIT_6 6 ++#define FRITZ4020_SSR_BIT_7 7 ++ ++#define FRITZ4020_74HC_GPIO_BASE 32 ++#define FRITZ4020_74HC_GPIO_LED_LAN (FRITZ4020_74HC_GPIO_BASE + 0) ++#define FRITZ4020_74HC_GPIO_LED_INFO_RED (FRITZ4020_74HC_GPIO_BASE + 1) ++#define FRITZ4020_74HC_GPIO_LED_POWER (FRITZ4020_74HC_GPIO_BASE + 2) ++#define FRITZ4020_74HC_GPIO_LED_WLAN (FRITZ4020_74HC_GPIO_BASE + 3) ++#define FRITZ4020_74HC_GPIO_LED_WAN (FRITZ4020_74HC_GPIO_BASE + 4) ++#define FRITZ4020_74HC_GPIO_USB_RST (FRITZ4020_74HC_GPIO_BASE + 5) ++#define FRITZ4020_74HC_GPIO_LED_INFO (FRITZ4020_74HC_GPIO_BASE + 6) ++ ++ ++#define FRITZ4020_GPIO_BTN_WPS 2 ++#define FRITZ4020_GPIO_BTN_WLAN 21 ++#define FRITZ4020_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define FRITZ4020_KEYS_DEBOUNCE_INTERVAL (3 * FRITZ4020_KEYS_POLL_INTERVAL) ++ ++#define FRTIZ4020_OFFSET_URLADER_WIFI_MAC_REVERSE 0x1979 ++ ++ ++static struct spi_gpio_platform_data fritz4020_spi_data = { ++ .sck = FRITZ4020_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = FRITZ4020_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 fritz4020_ssr_initdata[] = { ++ BIT(FRITZ4020_SSR_BIT_7) | ++ BIT(FRITZ4020_SSR_BIT_6) | ++ BIT(FRITZ4020_SSR_BIT_5) | ++ BIT(FRITZ4020_SSR_BIT_4) | ++ BIT(FRITZ4020_SSR_BIT_3) | ++ BIT(FRITZ4020_SSR_BIT_2) | ++ BIT(FRITZ4020_SSR_BIT_1) ++}; ++ ++static struct gen_74x164_chip_platform_data fritz4020_ssr_data = { ++ .base = FRITZ4020_74HC_GPIO_BASE, ++ .num_registers = ARRAY_SIZE(fritz4020_ssr_initdata), ++ .init_data = fritz4020_ssr_initdata, ++}; ++ ++static struct platform_device fritz4020_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &fritz4020_spi_data, ++ }, ++}; ++ ++static struct spi_board_info fritz4020_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &fritz4020_ssr_data, ++ .controller_data = (void *) 0x0, ++ }, ++}; ++ ++static struct mtd_partition fritz4020_flash_partitions[] = { ++ { ++ .name = "urlader", ++ .offset = 0, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0020000, ++ .size = 0x0EE0000, ++ }, { ++ .name = "tffs (1)", ++ .offset = 0x0f00000, ++ .size = 0x0080000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "tffs (2)", ++ .offset = 0x0f80000, ++ .size = 0x0080000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++ ++static struct flash_platform_data fritz4020_flash_data = { ++ .parts = fritz4020_flash_partitions, ++ .nr_parts = ARRAY_SIZE(fritz4020_flash_partitions), ++}; ++ ++static struct gpio_led fritz4020_leds_gpio[] __initdata = { ++ { ++ .name = "fritz4020:green:lan", ++ .gpio = FRITZ4020_74HC_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:green:info", ++ .gpio = FRITZ4020_74HC_GPIO_LED_INFO, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:red:info", ++ .gpio = FRITZ4020_74HC_GPIO_LED_INFO_RED, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:green:power", ++ .gpio = FRITZ4020_74HC_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:green:wlan", ++ .gpio = FRITZ4020_74HC_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:green:wan", ++ .gpio = FRITZ4020_74HC_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button fritz4020_gpio_keys[] __initdata = { ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = FRITZ4020_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = FRITZ4020_GPIO_BTN_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = FRITZ4020_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = FRITZ4020_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init fritz4020_setup(void) { ++ u8 *urlader = (u8 *) KSEG1ADDR(0x1f000000); ++ u8 wifi_mac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&fritz4020_flash_data); ++ ++ /* Initialize ethernet */ ++ ath79_extract_mac_reverse(urlader + FRTIZ4020_OFFSET_URLADER_WIFI_MAC_REVERSE, wifi_mac); ++ ath79_setup_qca956x_eth_cfg(QCA956X_ETH_CFG_SW_PHY_SWAP | ++ QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, wifi_mac, -1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, wifi_mac, -2); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(0); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ /* Initialize 2.4GHz WiFi */ ++ ath79_register_wmac_simple(); ++ ++ /* Activate USB Power */ ++ gpio_request_one(FRITZ4020_74HC_GPIO_USB_RST, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ /* Initialize USB port */ ++ ath79_register_usb(); ++ ++ /* Register LED shift-register */ ++ spi_register_board_info(fritz4020_spi_info, ++ ARRAY_SIZE(fritz4020_spi_info)); ++ platform_device_register(&fritz4020_spi_device); ++ ++ /* Register GPIO buttons */ ++ ath79_register_gpio_keys_polled(-1, FRITZ4020_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(fritz4020_gpio_keys), ++ fritz4020_gpio_keys); ++ ++ /* Register LEDs */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(fritz4020_leds_gpio), ++ fritz4020_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_FRITZ4020, "FRITZ4020", ++ "AVM FRITZ!Box 4020", fritz4020_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz450e.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz450e.c +new file mode 100644 +index 0000000000..5bded81a4d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz450e.c +@@ -0,0 +1,179 @@ ++/* ++ * AVM FRITZ!WLAN Repeater 450E board support ++ * ++ * Copyright (C) 2018 David Bauer ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define FRITZ450E_GPIO_LED_POWER 14 ++#define FRITZ450E_GPIO_LED_LAN 13 ++#define FRITZ450E_GPIO_LED_WLAN 15 ++#define FRITZ450E_GPIO_LED_RSSI2 16 ++#define FRITZ450E_GPIO_LED_RSSI3 17 ++#define FRITZ450E_GPIO_LED_RSSI4 18 ++ ++#define FRITZ450E_GPIO_BTN_WPS 4 ++#define FRITZ450E_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define FRITZ450E_KEYS_DEBOUNCE_INTERVAL (3 * FRITZ450E_KEYS_POLL_INTERVAL) ++ ++#define FRITZ450E_PHY_ADDRESS 0 ++#define FRITZ450E_GPIO_PHY_RESET 11 ++#define FRITZ450E_GPIO_MDIO_CLK 12 ++#define FRITZ450E_GPIO_MDIO_DATA 19 ++ ++#define FRITZ450E_OFFSET_URLADER_WIFI_MAC_REVERSE 0x1979 ++ ++ ++static struct mtd_partition fritz450E_flash_partitions[] = { ++ { ++ .name = "urlader", ++ .offset = 0, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0020000, ++ .size = 0x0EE0000, ++ }, { ++ .name = "tffs (1)", ++ .offset = 0x0f00000, ++ .size = 0x0080000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "tffs (2)", ++ .offset = 0x0f80000, ++ .size = 0x0080000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++ ++static struct flash_platform_data fritz450E_flash_data = { ++ .parts = fritz450E_flash_partitions, ++ .nr_parts = ARRAY_SIZE(fritz450E_flash_partitions), ++}; ++ ++static struct gpio_led fritz450E_leds_gpio[] __initdata = { ++ { ++ .name = "fritz450e:green:lan", ++ .gpio = FRITZ450E_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "fritz450e:green:rssi2", ++ .gpio = FRITZ450E_GPIO_LED_RSSI2, ++ .active_low = 1, ++ }, { ++ .name = "fritz450e:green:rssi3", ++ .gpio = FRITZ450E_GPIO_LED_RSSI3, ++ .active_low = 1, ++ }, { ++ .name = "fritz450e:green:rssi4", ++ .gpio = FRITZ450E_GPIO_LED_RSSI4, ++ .active_low = 1, ++ }, { ++ .name = "fritz450e:green:wlan", ++ .gpio = FRITZ450E_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "fritz450e:green:power", ++ .gpio = FRITZ450E_GPIO_LED_POWER, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button fritz450E_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS Button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = FRITZ450E_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = FRITZ450E_GPIO_BTN_WPS, ++ .active_low = 0, ++ } ++}; ++ ++static struct at803x_platform_data fritz450E_at803x_data = { ++ .disable_smarteee = 1, ++ .has_reset_gpio = 1, ++ .override_sgmii_aneg = 1, ++ .reset_gpio = FRITZ450E_GPIO_PHY_RESET, ++}; ++ ++static struct mdio_board_info fritz450E_mdio_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.1", ++ .mdio_addr = FRITZ450E_PHY_ADDRESS, ++ .platform_data = &fritz450E_at803x_data, ++ }, ++}; ++ ++static void __init fritz450E_setup(void) { ++ u8 *urlader = (u8 *) KSEG1ADDR(0x1f000000); ++ u8 wifi_mac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&fritz450E_flash_data); ++ ++ gpio_request_one(FRITZ450E_GPIO_MDIO_CLK, GPIOF_OUT_INIT_HIGH, "MDC Pull-UP"); ++ gpio_request_one(FRITZ450E_GPIO_MDIO_DATA, GPIOF_OUT_INIT_HIGH, "MDIO Pull-UP"); ++ gpio_request_one(FRITZ450E_GPIO_PHY_RESET, GPIOF_OUT_INIT_HIGH, "PHY reset"); ++ ++ /* Register PHY device */ ++ mdiobus_register_board_info(fritz450E_mdio_info, ++ ARRAY_SIZE(fritz450E_mdio_info)); ++ ++ /* Initialize Ethernet */ ++ ath79_extract_mac_reverse(urlader + FRITZ450E_OFFSET_URLADER_WIFI_MAC_REVERSE, wifi_mac); ++ ath79_init_mac(ath79_eth0_data.mac_addr, wifi_mac, -2); ++ ++ ath79_register_mdio(1, ~BIT(FRITZ450E_PHY_ADDRESS)); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.phy_mask = BIT(FRITZ450E_PHY_ADDRESS); ++ ath79_eth0_data.enable_sgmii_fixup = 1; ++ ath79_eth0_pll_data.pll_1000 = 0x03000000; ++ ath79_eth0_pll_data.pll_100 = 0x00000101; ++ ath79_eth0_pll_data.pll_10 = 0x00001313; ++ ath79_register_eth(0); ++ ++ /* Initialize 2.4GHz WiFi */ ++ ath79_register_wmac_simple(); ++ ++ /* Register GPIO buttons */ ++ ath79_register_gpio_keys_polled(-1, FRITZ450E_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(fritz450E_gpio_keys), ++ fritz450E_gpio_keys); ++ ++ /* Register LEDs */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(fritz450E_leds_gpio), ++ fritz450E_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_FRITZ450E, "FRITZ450E", ++ "AVM FRITZ!WLAN Repeater 450E", fritz450E_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar150.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar150.c +new file mode 100644 +index 0000000000..9febc7a839 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar150.c +@@ -0,0 +1,125 @@ ++/* ++ * GL_ar150 board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2013 alzhao ++ * Copyright (C) 2014 Michel Stempin ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define GL_AR150_GPIO_LED_WLAN 0 ++#define GL_AR150_GPIO_LED_LAN 13 ++#define GL_AR150_GPIO_LED_WAN 15 ++ ++#define GL_AR150_GPIO_BIN_USB 6 ++#define GL_AR150_GPIO_BTN_MANUAL 7 ++#define GL_AR150_GPIO_BTN_AUTO 8 ++#define GL_AR150_GPIO_BTN_RESET 11 ++ ++#define GL_AR150_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define GL_AR150_KEYS_DEBOUNCE_INTERVAL (3 * GL_AR150_KEYS_POLL_INTERVAL) ++ ++#define GL_AR150_MAC0_OFFSET 0x0000 ++#define GL_AR150_MAC1_OFFSET 0x0000 ++#define GL_AR150_CALDATA_OFFSET 0x1000 ++#define GL_AR150_WMAC_MAC_OFFSET 0x0000 ++ ++static struct gpio_led gl_ar150_leds_gpio[] __initdata = { ++ { ++ .name = "gl-ar150:orange:wlan", ++ .gpio = GL_AR150_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-ar150:green:lan", ++ .gpio = GL_AR150_GPIO_LED_LAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-ar150:green:wan", ++ .gpio = GL_AR150_GPIO_LED_WAN, ++ .active_low = 0, ++ .default_state = 1, ++ }, ++}; ++ ++static struct gpio_keys_button gl_ar150_gpio_keys[] __initdata = { ++ { ++ .desc = "BTN_7", ++ .type = EV_KEY, ++ .code = BTN_7, ++ .debounce_interval = GL_AR150_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR150_GPIO_BTN_MANUAL, ++ .active_low = 0, ++ }, ++ { ++ .desc = "BTN_8", ++ .type = EV_KEY, ++ .code = BTN_8, ++ .debounce_interval = GL_AR150_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR150_GPIO_BTN_AUTO, ++ .active_low = 0, ++ }, ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_AR150_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR150_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init gl_ar150_setup(void) ++{ ++ ++ /* ART base address */ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ /* register flash. */ ++ ath79_register_m25p80(NULL); ++ ++ /* register gpio LEDs and keys */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_ar150_leds_gpio), ++ gl_ar150_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, GL_AR150_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_ar150_gpio_keys), ++ gl_ar150_gpio_keys); ++ ++ /* enable usb */ ++ gpio_request_one(GL_AR150_GPIO_BIN_USB, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ /* register eth0 as WAN, eth1 as LAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art+GL_AR150_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art+GL_AR150_MAC1_OFFSET, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ /* register wireless mac with cal data */ ++ ath79_register_wmac(art + GL_AR150_CALDATA_OFFSET, art + GL_AR150_WMAC_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_AR150, "GL-AR150", "GL.iNet GL-AR150", gl_ar150_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300.c +new file mode 100644 +index 0000000000..1708d696b8 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300.c +@@ -0,0 +1,103 @@ ++/* ++ * Domino board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2013 alzhao ++ * Copyright (C) 2014 Michel Stempin ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define GL_AR300_GPIO_LED_WLAN 13 ++#define GL_AR300_GPIO_LED_WAN 14 ++#define GL_AR300_GPIO_BTN_RESET 16 ++ ++ ++#define GL_AR300_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define GL_AR300_KEYS_DEBOUNCE_INTERVAL (3 * GL_AR300_KEYS_POLL_INTERVAL) ++ ++#define GL_AR300_MAC0_OFFSET 0x0000 ++#define GL_AR300_MAC1_OFFSET 0x0000 ++#define GL_AR300_CALDATA_OFFSET 0x1000 ++#define GL_AR300_WMAC_MAC_OFFSET 0x0000 ++ ++static struct gpio_led gl_ar300_leds_gpio[] __initdata = { ++ { ++ .name = "gl-ar300:wlan", ++ .gpio = GL_AR300_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "gl-ar300:wan", ++ .gpio = GL_AR300_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button gl_ar300_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_AR300_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR300_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init gl_ar300_setup(void) ++{ ++ ++ /* ART base address */ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ /* register flash. */ ++ ath79_register_m25p80(NULL); ++ ++ /* register gpio LEDs and keys */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_ar300_leds_gpio), ++ gl_ar300_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, GL_AR300_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_ar300_gpio_keys), ++ gl_ar300_gpio_keys); ++ ++ /* enable usb */ ++ ath79_register_usb(); ++ ath79_register_mdio(1, 0x0); ++ ++ /* register eth0 as WAN, eth1 as LAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art+GL_AR300_MAC0_OFFSET, 0); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art+GL_AR300_MAC1_OFFSET, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ /* register wireless mac with cal data */ ++ ath79_register_wmac(art + GL_AR300_CALDATA_OFFSET, art + GL_AR300_WMAC_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_AR300, "GL-AR300", "GL.iNet GL-AR300", gl_ar300_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300m.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300m.c +new file mode 100644 +index 0000000000..d10a910129 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300m.c +@@ -0,0 +1,158 @@ ++/* ++ * GLI AR300M(D) board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2013 alzhao ++ * Copyright (C) 2014 Michel Stempin ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define GL_AR300M_GPIO_LED_WLAN 14 ++#define GL_AR300M_GPIO_LED_LAN 13 ++#define GL_AR300M_GPIO_LED_SYSTEM 12 ++#define GL_AR300M_GPIO_BTN_RESET 3 ++#define GL_AR300M_GPIO_BTN_LEFT 0 ++#define GL_AR300M_GPIO_BTN_RIGHT 1 ++ ++#define GL_AR300M_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define GL_AR300M_KEYS_DEBOUNCE_INTERVAL (3 * GL_AR300M_KEYS_POLL_INTERVAL) ++ ++#define GL_AR300M_MAC0_OFFSET 0 ++#define GL_AR300M_MAC1_OFFSET 6 ++#define GL_AR300M_WMAC_CALDATA_OFFSET 0x1000 ++#define GL_AR300M_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led gl_ar300m_leds_gpio[] __initdata = { ++ { ++ .name = "gl-ar300m:red:wlan", ++ .gpio = GL_AR300M_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "gl-ar300m:green:lan", ++ .gpio = GL_AR300M_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "gl-ar300m:green:system", ++ .gpio = GL_AR300M_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ .default_state = 1, ++ }, ++}; ++ ++static struct gpio_keys_button gl_ar300m_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR300M_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "button right", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR300M_GPIO_BTN_LEFT, ++ .active_low = 0, ++ }, ++ { ++ .desc = "button left", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR300M_GPIO_BTN_RIGHT, ++ .active_low = 0, ++ }, ++}; ++ ++static struct spi_board_info gl_ar300m_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ .platform_data = NULL, ++ }, ++ { ++ .bus_num = 0, ++ .chip_select = 1, ++ .max_speed_hz = 25000000, ++ .modalias = "ath79-spinand", ++ .platform_data = NULL, ++ } ++}; ++ ++static struct ath79_spi_platform_data gl_ar300m_spi_data = { ++ .bus_num = 0, ++ .num_chipselect = 2, ++}; ++ ++static void __init gl_ar300m_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ath79_register_spi(&gl_ar300m_spi_data, gl_ar300m_spi_info, 2); ++ ++ /* register gpio LEDs and keys */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_ar300m_leds_gpio), ++ gl_ar300m_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, GL_AR300M_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_ar300m_gpio_keys), ++ gl_ar300m_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* WAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + GL_AR300M_MAC0_OFFSET, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + GL_AR300M_MAC1_OFFSET, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_init_mac(tmpmac, art + GL_AR300M_WMAC_CALDATA_OFFSET + 2, 0); ++ ath79_register_wmac(art + GL_AR300M_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ /* enable usb */ ++ ath79_register_usb(); ++ /* enable pci */ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_AR300M, "GL-AR300M", "GL.iNet GL-AR300M", gl_ar300m_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750.c +new file mode 100644 +index 0000000000..9ee6e29c02 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750.c +@@ -0,0 +1,146 @@ ++/* ++ * GL.iNet GL-AR750 board support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define GL_AR750_GPIO_LED_POWER 12 ++#define GL_AR750_GPIO_LED_WLAN2G 14 ++#define GL_AR750_GPIO_LED_WLAN5G 13 ++ ++#define GL_AR750_GPIO_BTN_RESET 3 ++#define GL_AR750_GPIO_BTN_SW1 0 ++ ++#define GL_AR750_GPIO_I2C_SCL 16 ++#define GL_AR750_GPIO_I2C_SDA 17 ++ ++#define GL_AR750_GPIO_USB_POWER 2 ++ ++#define GL_AR750_KEYS_POLL_INTERVAL 20 ++#define GL_AR750_KEYS_DEBOUNCE_INTERVAL (3 * GL_AR750_KEYS_POLL_INTERVAL) ++ ++#define GL_AR750_MAC0_OFFSET 0 ++#define GL_AR750_WMAC2G_CALDATA_OFFSET 0x1000 ++#define GL_AR750_WMAC5G_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led gl_ar750_leds_gpio[] __initdata = { ++ { ++ .name = "gl-ar750:white:power", ++ .gpio = GL_AR750_GPIO_LED_POWER, ++ .default_state = LEDS_GPIO_DEFSTATE_KEEP, ++ .active_low = 1, ++ }, { ++ .name = "gl-ar750:white:wlan2g", ++ .gpio = GL_AR750_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, { ++ .name = "gl-ar750:white:wlan5g", ++ .gpio = GL_AR750_GPIO_LED_WLAN5G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button gl_ar750_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_AR750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR750_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "sw1", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = GL_AR750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR750_GPIO_BTN_SW1, ++ .active_low = 1, ++ }, ++}; ++ ++static struct i2c_gpio_platform_data gl_ar750_i2c_gpio_data = { ++ .sda_pin = GL_AR750_GPIO_I2C_SDA, ++ .scl_pin = GL_AR750_GPIO_I2C_SCL, ++}; ++ ++static struct platform_device gl_ar750_i2c_gpio = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &gl_ar750_i2c_gpio_data, ++ }, ++}; ++ ++static void __init gl_ar750_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f050000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = 0xfc; ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + GL_AR750_MAC0_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + GL_AR750_MAC0_OFFSET, 1); ++ ath79_register_eth(1); ++ ++ /* Disable JTAG (enables GPIO0-3) */ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_ar750_leds_gpio), ++ gl_ar750_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, GL_AR750_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_ar750_gpio_keys), ++ gl_ar750_gpio_keys); ++ ++ gpio_request_one(GL_AR750_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ platform_device_register(&gl_ar750_i2c_gpio); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + GL_AR750_WMAC2G_CALDATA_OFFSET, NULL); ++ ++ ap91_pci_init(art + GL_AR750_WMAC5G_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_AR750, "GL-AR750", "GL.iNet GL-AR750", ++ gl_ar750_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750s.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750s.c +new file mode 100644 +index 0000000000..cc5d759273 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750s.c +@@ -0,0 +1,193 @@ ++/* ++ * GL.iNet GL-AR750S board support ++ * ++ * Copyright (C) 2018 luochongjun ++ * ++ * 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 ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++ ++#define GL_AR750S_KEYS_POLL_INTERVAL 20 ++#define GL_AR750S_KEYS_DEBOUNCE_INTERVAL (3 * GL_AR750S_KEYS_POLL_INTERVAL) ++ ++ ++#define GL_AR750S_GPIO_LED_WLAN2G 19 ++#define GL_AR750S_GPIO_LED_WLAN5G 20 ++#define GL_AR750S_GPIO_LED_POWER 1 ++#define GL_AR750S_GPIO_USB_POWER 7 ++ ++#define GL_AR750S_GPIO_BTN_RESET 2 ++#define GL_AR750S_GPIO_BTN_RIGHT 8 ++ ++#define GL_AR750S_MAC0_OFFSET 0x0000 ++#define GL_AR750S_WMAC_CALDATA_OFFSET 0x1000 ++#define GL_AR750S_PCI_CALDATA_OFFSET 0x5000 ++ ++#define GL_AR750S_GPIO_I2C_SDA 5 ++#define GL_AR750S_GPIO_I2C_SCL 21 ++ ++ ++ ++static struct spi_board_info gl_ar750s_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ .platform_data = NULL, ++ }, ++}; ++ ++static struct ath79_spi_platform_data gl_ar750s_spi_data = { ++ .bus_num = 0, ++ .num_chipselect = 2, ++}; ++ ++static struct gpio_led gl_ar750s_leds_gpio[] __initdata = { ++ { ++ .name = "gl-ar750s:green:power", ++ .gpio = GL_AR750S_GPIO_LED_POWER, ++ .default_state = LEDS_GPIO_DEFSTATE_KEEP, ++ .active_low = 1, ++ },{ ++ .name = "gl-ar750s:green:usbpower", ++ .gpio = GL_AR750S_GPIO_USB_POWER, ++ .active_low = 1, ++ },{ ++ .name = "gl-ar750s:green:wlan2g", ++ .gpio = GL_AR750S_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ },{ ++ .name = "gl-ar750s:green:wlan5g", ++ .gpio = GL_AR750S_GPIO_LED_WLAN5G, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button gl_ar750s_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_AR750S_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR750S_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "right", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = GL_AR750S_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR750S_GPIO_BTN_RIGHT, ++ .active_low = 1, ++ }, ++}; ++ ++static struct i2c_gpio_platform_data gl_ar750s_i2c_gpio_data = { ++ .sda_pin = GL_AR750S_GPIO_I2C_SDA, ++ .scl_pin = GL_AR750S_GPIO_I2C_SCL, ++}; ++ ++static struct platform_device gl_ar750s_i2c_gpio_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &gl_ar750s_i2c_gpio_data, ++ } ++ ++}; ++ ++static struct ar8327_pad_cfg gl_ar750s_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data gl_ar750s_ar8327_data = { ++ .pad0_cfg = &gl_ar750s_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++ ++static struct mdio_board_info gl_ar750s_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &gl_ar750s_ar8327_data, ++ }, ++}; ++ ++static void __init gl_ar750s_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1f050000); ++ ++ ath79_register_spi(&gl_ar750s_spi_data, gl_ar750s_spi_info, 1); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ eeprom + GL_AR750S_MAC0_OFFSET, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ mdiobus_register_board_info(gl_ar750s_mdio0_info, ++ ARRAY_SIZE(gl_ar750s_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x00); ++ ath79_register_eth(0); ++ ++ ++ ath79_register_usb(); ++ ++ ++ ath79_register_wmac(eeprom + GL_AR750S_WMAC_CALDATA_OFFSET, NULL); ++ ++ ++ ap91_pci_init(eeprom + GL_AR750S_PCI_CALDATA_OFFSET, NULL); ++ ++ platform_device_register(&gl_ar750s_i2c_gpio_device); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_ar750s_leds_gpio), ++ gl_ar750s_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, GL_AR750S_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_ar750s_gpio_keys), ++ gl_ar750s_gpio_keys); ++} ++ ++ ++MIPS_MACHINE(ATH79_MACH_GL_AR750S, "GL-AR750S", "GL-AR750S", ++ gl_ar750s_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-domino.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-domino.c +new file mode 100644 +index 0000000000..4ff8ff637e +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-domino.c +@@ -0,0 +1,136 @@ ++/* ++ * Domino board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2013 alzhao ++ * Copyright (C) 2014 Michel Stempin ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define DOMINO_GPIO_LED_WLAN 0 ++#define DOMINO_GPIO_LED_WAN 17 ++#define DOMINO_GPIO_LED_USB 1 ++#define DOMINO_GPIO_LED_LAN1 13 ++#define DOMINO_GPIO_LED_LAN2 14 ++#define DOMINO_GPIO_LED_LAN3 15 ++#define DOMINO_GPIO_LED_LAN4 16 ++#define DOMINO_GPIO_LED_SYS 27 ++#define DOMINO_GPIO_LED_WPS 26 ++#define DOMINO_GPIO_USB_POWER 6 ++ ++#define DOMINO_GPIO_BTN_RESET 11 ++#define DOMINO_GPIO_BTN_WPS 20 ++ ++#define DOMINO_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define DOMINO_KEYS_DEBOUNCE_INTERVAL (3 * DOMINO_KEYS_POLL_INTERVAL) ++ ++#define DOMINO_MAC0_OFFSET 0x0000 ++#define DOMINO_MAC1_OFFSET 0x0000 ++#define DOMINO_CALDATA_OFFSET 0x1000 ++#define DOMINO_WMAC_MAC_OFFSET 0x0000 ++ ++static struct gpio_led domino_leds_gpio[] __initdata = { ++ { ++ .name = "gl-domino:blue:wlan", ++ .gpio = DOMINO_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-domino:red:wan", ++ .gpio = DOMINO_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "gl-domino:white:usb", ++ .gpio = DOMINO_GPIO_LED_USB, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-domino:green:lan1", ++ .gpio = DOMINO_GPIO_LED_LAN1, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-domino:yellow:wps", ++ .gpio = DOMINO_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "gl-domino:orange:sys", ++ .gpio = DOMINO_GPIO_LED_SYS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button domino_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = DOMINO_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DOMINO_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = DOMINO_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = DOMINO_GPIO_BTN_WPS, ++ .active_low = 0, ++ } ++}; ++ ++static void __init domino_setup(void) ++{ ++ ++ /* ART base address */ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ /* register flash. */ ++ ath79_register_m25p80(NULL); ++ ++ /* register gpio LEDs and keys */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(domino_leds_gpio), ++ domino_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DOMINO_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(domino_gpio_keys), ++ domino_gpio_keys); ++ ++ gpio_request_one(DOMINO_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ /* enable usb */ ++ ath79_register_usb(); ++ ++ /* register eth0 as WAN, eth1 as LAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art+DOMINO_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art+DOMINO_MAC1_OFFSET, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ /* register wireless mac with cal data */ ++ ath79_register_wmac(art + DOMINO_CALDATA_OFFSET, art + DOMINO_WMAC_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_DOMINO, "DOMINO", "Domino Pi", domino_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-inet.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-inet.c +new file mode 100644 +index 0000000000..6f603d9579 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-inet.c +@@ -0,0 +1,104 @@ ++/* ++ * GL-CONNECT iNet board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2013 alzhao ++ * Copyright (C) 2014 Michel Stempin ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define GL_INET_GPIO_LED_WLAN 0 ++#define GL_INET_GPIO_LED_LAN 13 ++#define GL_INET_GPIO_BTN_RESET 11 ++ ++#define GL_INET_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define GL_INET_KEYS_DEBOUNCE_INTERVAL (3 * GL_INET_KEYS_POLL_INTERVAL) ++ ++static const char * gl_inet_part_probes[] = { ++ "tp-link", /* dont change, this will use tplink parser */ ++ NULL , ++}; ++ ++static struct flash_platform_data gl_inet_flash_data = { ++ .part_probes = gl_inet_part_probes, ++}; ++ ++static struct gpio_led gl_inet_leds_gpio[] __initdata = { ++ { ++ .name = "gl-inet:red:wlan", ++ .gpio = GL_INET_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-inet:green:lan", ++ .gpio = GL_INET_GPIO_LED_LAN, ++ .active_low = 0, ++ .default_state = 1, ++ }, ++}; ++ ++static struct gpio_keys_button gl_inet_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_INET_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_INET_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static void __init gl_inet_setup(void) ++{ ++ /* get the mac address which is stored in the 1st 64k uboot MTD */ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ ++ /* get the art address, which is the last 64K. By using ++ 0x1fff1000, it doesn't matter it is 4M, 8M or 16M flash */ ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ /* register flash. MTD will use tp-link parser to parser MTD */ ++ ath79_register_m25p80(&gl_inet_flash_data); ++ ++ /* register gpio LEDs and keys */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_inet_leds_gpio), ++ gl_inet_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, GL_INET_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_inet_gpio_keys), ++ gl_inet_gpio_keys); ++ ++ /* enable usb */ ++ ath79_register_usb(); ++ ++ /* register eth0 as WAN, eth1 as LAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ /* register wireless mac with cal data */ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_INET, "GL-INET", "GL-CONNECT INET v1", ++ gl_inet_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-mifi.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-mifi.c +new file mode 100644 +index 0000000000..a5c68ed65a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-mifi.c +@@ -0,0 +1,114 @@ ++/* ++ * Mifi board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2013 alzhao ++ * Copyright (C) 2014 Michel Stempin ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define GL_MIFI_GPIO_LED_WAN 27 ++#define GL_MIFI_GPIO_LED_LAN 16 ++#define GL_MIFI_GPIO_LED_WLAN 1 ++#define GL_MIFI_GPIO_LED_NET 0 ++#define GL_MIFI_GPIO_LED_3GCONTROL 7 ++ ++#define GL_MIFI_GPIO_BTN_RESET 11 ++ ++#define GL_MIFI_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define GL_MIFI_KEYS_DEBOUNCE_INTERVAL (3 * GL_MIFI_KEYS_POLL_INTERVAL) ++ ++#define GL_MIFI_MAC0_OFFSET 0x0000 ++#define GL_MIFI_MAC1_OFFSET 0x0000 ++#define GL_MIFI_CALDATA_OFFSET 0x1000 ++#define GL_MIFI_WMAC_MAC_OFFSET 0x0000 ++ ++static struct gpio_led gl_mifi_leds_gpio[] __initdata = { ++ { ++ .name = "gl-mifi:green:wan", ++ .gpio = GL_MIFI_GPIO_LED_WAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-mifi:green:lan", ++ .gpio = GL_MIFI_GPIO_LED_LAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-mifi:green:wlan", ++ .gpio = GL_MIFI_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-mifi:green:net", ++ .gpio = GL_MIFI_GPIO_LED_NET, ++ .active_low = 0, ++ }, ++ { ++ .name = "gl-mifi:green:3gcontrol", ++ .gpio = GL_MIFI_GPIO_LED_3GCONTROL, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button gl_mifi_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_MIFI_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_MIFI_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init gl_mifi_setup(void) ++{ ++ ++ /* ART base address */ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ /* register flash. */ ++ ath79_register_m25p80(NULL); ++ ++ /* register gpio LEDs and keys */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_mifi_leds_gpio), ++ gl_mifi_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, GL_MIFI_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_mifi_gpio_keys), ++ gl_mifi_gpio_keys); ++ ++ /* enable usb */ ++ ath79_register_usb(); ++ ++ /* register eth0 as WAN, eth1 as LAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art+GL_MIFI_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art+GL_MIFI_MAC1_OFFSET, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ /* register wireless mac with cal data */ ++ ath79_register_wmac(art + GL_MIFI_CALDATA_OFFSET, art + GL_MIFI_WMAC_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_MIFI, "GL-MIFI", "GL.iNet GL-MIFI", gl_mifi_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-usb150.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-usb150.c +new file mode 100644 +index 0000000000..6cc27e1ada +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-usb150.c +@@ -0,0 +1,87 @@ ++/* ++ * GL.iNet GL-USB150 board support ++ * ++ * Copyright (C) 2017 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define GL_USB150_GPIO_LED_POWER 13 ++#define GL_USB150_GPIO_LED_WLAN 0 ++#define GL_USB150_GPIO_LAN_RESET 7 ++#define GL_USB150_GPIO_BTN_RESET 11 ++ ++#define GL_USB150_KEYS_POLL_INTERVAL 20 ++#define GL_USB150_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * GL_USB150_KEYS_POLL_INTERVAL) ++ ++#define GL_USB150_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led gl_usb150_leds_gpio[] __initdata = { ++ { ++ .name = "gl-usb150:green:power", ++ .gpio = GL_USB150_GPIO_LED_POWER, ++ .active_low = 0, ++ }, { ++ .name = "gl-usb150:green:wlan", ++ .gpio = GL_USB150_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button gl_usb150_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_USB150_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_USB150_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init gl_usb150_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ /* LAN (PHY4 connected with Realtek RTL8152B) */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_usb150_leds_gpio), ++ gl_usb150_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, GL_USB150_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_usb150_gpio_keys), ++ gl_usb150_gpio_keys); ++ ++ gpio_request_one(GL_USB150_GPIO_LAN_RESET, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "LAN reset"); ++ ++ ath79_register_wmac(art + GL_USB150_WMAC_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_USB150, "GL-USB150", "GL.iNet GL-USB150", ++ gl_usb150_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-minibox-v32.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-minibox-v32.c +new file mode 100644 +index 0000000000..469c6f39ea +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-minibox-v32.c +@@ -0,0 +1,121 @@ ++/* ++ * Atheros GS_MINIBOX_V3.2 reference board support ++ * ++ * Copyright (c) 2018 OpenWRT.org ++ * Copyright (c) 2013 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define GS_MINIBOX_V3_GPIO_LED_STATUS 14 ++#define GS_MINIBOX_V3_GPIO_BTN_RST 17 ++#define GS_MINIBOX_V3_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define GS_MINIBOX_V3_KEYS_DEBOUNCE_INTERVAL (3 * GS_MINIBOX_V3_KEYS_POLL_INTERVAL) ++#define GS_MINIBOX_V3_MAC0_OFFSET 0 ++#define GS_MINIBOX_V3_MAC1_OFFSET 6 ++#define GS_MINIBOX_V3_WMAC_CALDATA_OFFSET 0x1000 ++ ++static const char *gs_minibox_v3_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data gs_minibox_v3_flash_data = { ++ .part_probes = gs_minibox_v3_part_probes, ++}; ++ ++static struct gpio_led gs_minibox_v3_leds_gpio[] __initdata = { ++ { ++ .name = "minibox_v3.2:green:system", ++ .gpio = GS_MINIBOX_V3_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button gs_minibox_v3_gpio_keys[] __initdata = { ++ { ++ .desc = "reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GS_MINIBOX_V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GS_MINIBOX_V3_GPIO_BTN_RST, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init gs_minibox_v3_gpio_led_setup(void) ++{ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gs_minibox_v3_leds_gpio), ++ gs_minibox_v3_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, GS_MINIBOX_V3_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gs_minibox_v3_gpio_keys), ++ gs_minibox_v3_gpio_keys); ++} ++ ++static void __init gs_minibox_v3_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&gs_minibox_v3_flash_data); ++ gs_minibox_v3_gpio_led_setup(); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + GS_MINIBOX_V3_WMAC_CALDATA_OFFSET, NULL); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + GS_MINIBOX_V3_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + GS_MINIBOX_V3_MAC1_OFFSET, 0); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GS_MINIBOX_V32, "MINIBOX-V3.2", "Minibox V3.2", ++ gs_minibox_v3_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-oolite-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-oolite-v1.c +new file mode 100644 +index 0000000000..d424e0f111 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-oolite-v1.c +@@ -0,0 +1,143 @@ ++/* ++ * GainStrong Oolite/MiniBox V1.0 boards support ++ * ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "dev-usb.h" ++ ++#define GS_MINIBOX_V1_GPIO_BTN_RESET 11 ++#define GS_MINIBOX_V1_GPIO_LED_SYSTEM 1 ++ ++#define GS_OOLITE_V1_GPIO_BTN6 6 ++#define GS_OOLITE_V1_GPIO_BTN7 7 ++#define GS_OOLITE_V1_GPIO_BTN_RESET 11 ++#define GS_OOLITE_V1_GPIO_LED_SYSTEM 27 ++ ++#define GS_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define GS_KEYS_DEBOUNCE_INTERVAL (3 * GS_KEYS_POLL_INTERVAL) ++ ++static const char *gs_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data gs_flash_data = { ++ .part_probes = gs_part_probes, ++}; ++ ++static struct gpio_led gs_minibox_v1_leds_gpio[] __initdata = { ++ { ++ .name = "minibox-v1:green:system", ++ .gpio = GS_MINIBOX_V1_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led gs_oolite_v1_leds_gpio[] __initdata = { ++ { ++ .name = "oolite-v1:red:system", ++ .gpio = GS_OOLITE_V1_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button gs_minibox_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GS_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GS_MINIBOX_V1_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button gs_oolite_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GS_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GS_OOLITE_V1_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, { ++ .desc = "BTN_6", ++ .type = EV_KEY, ++ .code = BTN_6, ++ .debounce_interval = GS_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GS_OOLITE_V1_GPIO_BTN6, ++ .active_low = 0, ++ }, { ++ .desc = "BTN_7", ++ .type = EV_KEY, ++ .code = BTN_7, ++ .debounce_interval = GS_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GS_OOLITE_V1_GPIO_BTN7, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init gs_common_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(&gs_flash_data); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art, mac); ++} ++ ++static void __init gs_minibox_v1_setup(void) ++{ ++ gs_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gs_minibox_v1_leds_gpio), ++ gs_minibox_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, GS_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gs_minibox_v1_gpio_keys), ++ gs_minibox_v1_gpio_keys); ++} ++ ++static void __init gs_oolite_v1_setup(void) ++{ ++ gs_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gs_oolite_v1_leds_gpio), ++ gs_oolite_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, GS_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gs_oolite_v1_gpio_keys), ++ gs_oolite_v1_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GS_MINIBOX_V1, "MINIBOX-V1", "GainStrong MiniBox V1.0", ++ gs_minibox_v1_setup); ++ ++MIPS_MACHINE(ATH79_MACH_GS_OOLITE_V1, "OOLITE-V1", "GainStrong Oolite V1.0", ++ gs_oolite_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-oolite-v5-2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-oolite-v5-2.c +new file mode 100644 +index 0000000000..64dc4f3345 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gs-oolite-v5-2.c +@@ -0,0 +1,111 @@ ++/* ++ * GainStrong Oolite V5.2 module and development board support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define GS_OOLITE_V5_2_DEV_GPIO_BTN_RESET 17 ++#define GS_OOLITE_V5_2_DEV_GPIO_LED_SYSTEM 13 ++ ++#define GS_KEYS_POLL_INTERVAL 20 /* msec */ ++#define GS_KEYS_DEBOUNCE_INTERVAL (3 * GS_KEYS_POLL_INTERVAL) ++ ++#define GS_OOLITE_V5_2_WMAC_CALDATA_OFFSET 0x1000 ++ ++static const char *gs_oolite_v5_2_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data gs_oolite_v5_2_flash_data = { ++ .part_probes = gs_oolite_v5_2_part_probes, ++}; ++ ++static struct gpio_led gs_oolite_v5_2_dev_gpio_leds[] __initdata = { ++ { ++ .name = "oolite-v5.2-dev:blue:system", ++ .gpio = GS_OOLITE_V5_2_DEV_GPIO_LED_SYSTEM, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button gs_oolite_v5_2_dev_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GS_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GS_OOLITE_V5_2_DEV_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init gs_oolite_v5_2_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&gs_oolite_v5_2_flash_data); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + 6, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++ ath79_register_wmac(art + GS_OOLITE_V5_2_WMAC_CALDATA_OFFSET, NULL); ++} ++ ++static void __init gs_oolite_v5_2_dev_setup(void) ++{ ++ gs_oolite_v5_2_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gs_oolite_v5_2_dev_gpio_leds), ++ gs_oolite_v5_2_dev_gpio_leds); ++ ++ ath79_register_gpio_keys_polled(-1, GS_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gs_oolite_v5_2_dev_gpio_keys), ++ gs_oolite_v5_2_dev_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GS_OOLITE_V5_2, "OOLITE-V5-2", ++ "GainStrong Oolite V5.2", gs_oolite_v5_2_setup); ++ ++MIPS_MACHINE(ATH79_MACH_GS_OOLITE_V5_2_DEV, "OOLITE-V5-2-DEV", ++ "GainStrong Oolite V5.2-Dev", gs_oolite_v5_2_dev_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-hiveap-121.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-hiveap-121.c +new file mode 100644 +index 0000000000..5cbb2054f7 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-hiveap-121.c +@@ -0,0 +1,153 @@ ++/* ++ * Aerohive HiveAP 121 board support ++ * ++ * Copyright (C) 2017 Chris Blake ++ * ++ * 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 ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "dev-ap9x-pci.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define HIVEAP_121_GPIO_LED_ORANGE 14 ++#define HIVEAP_121_GPIO_LED_WHITE 21 ++#define HIVEAP_121_GPIO_I2C_SCL 12 ++#define HIVEAP_121_GPIO_I2C_SDA 13 ++#define HIVEAP_121_GPIO_XLNA0 20 ++#define HIVEAP_121_GPIO_XLNA1 19 ++#define HIVEAP_121_GPIO_USB_POWER 15 ++ ++#define HIVEAP_121_GPIO_BTN_RESET 4 ++#define HIVEAP_121_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define HIVEAP_121_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * HIVEAP_121_KEYS_POLL_INTERVAL) ++ ++#define HIVEAP_121_MAC_OFFSET 0x90000 ++ ++#define HIVEAP_121_LAN_PHYADDR 0 ++ ++static struct gpio_led hiveap_121_leds_gpio[] __initdata = { ++ { ++ .name = "hiveap-121:orange:power", ++ .gpio = HIVEAP_121_GPIO_LED_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "hiveap-121:white:power", ++ .gpio = HIVEAP_121_GPIO_LED_WHITE, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button hiveap_121_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = HIVEAP_121_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = HIVEAP_121_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct i2c_gpio_platform_data hiveap_121_i2c_gpio_data = { ++ .sda_pin = HIVEAP_121_GPIO_I2C_SDA, ++ .scl_pin = HIVEAP_121_GPIO_I2C_SCL, ++}; ++ ++static struct platform_device hiveap_121_i2c_gpio_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &hiveap_121_i2c_gpio_data, ++ } ++}; ++ ++static struct i2c_board_info tpm_i2c_info[] __initdata = { ++ { ++ I2C_BOARD_INFO("tpm_i2c_atmel", 0x29), ++ } ++}; ++ ++static void __init hiveap_121_setup(void) ++{ ++ u8 *base = (u8 *) KSEG1ADDR(0x1f000000); ++ u8 wlan0_mac[ETH_ALEN]; ++ u8 wlan1_mac[ETH_ALEN]; ++ ++ /* NAND */ ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_HW); ++ ath79_register_nfc(); ++ ++ /* SPI */ ++ ath79_register_m25p80(NULL); ++ ++ /* MDIO Interface */ ++ ath79_register_mdio(0, 0x0); ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_RXD_DELAY | ++ AR934X_ETH_CFG_RDV_DELAY); ++ ++ /* GMAC0 is connected to the RGMII interface to an Atheros AR8035-A */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ base + HIVEAP_121_MAC_OFFSET, 0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(HIVEAP_121_LAN_PHYADDR); ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_eth0_pll_data.pll_100 = 0x00000101; ++ ath79_eth0_pll_data.pll_10 = 0x00001313; ++ ath79_register_eth(0); ++ ++ /* i2c */ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ platform_device_register(&hiveap_121_i2c_gpio_device); ++ ++ /* TPM */ ++ i2c_register_board_info(0, tpm_i2c_info, ARRAY_SIZE(tpm_i2c_info)); ++ ++ /* LEDs and Buttons */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(hiveap_121_leds_gpio), ++ hiveap_121_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, HIVEAP_121_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(hiveap_121_gpio_keys), ++ hiveap_121_gpio_keys); ++ ++ /* USB */ ++ gpio_request_one(HIVEAP_121_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ /* XLNA - SoC Wireless */ ++ ath79_wmac_set_ext_lna_gpio(0, HIVEAP_121_GPIO_XLNA0); ++ ath79_wmac_set_ext_lna_gpio(1, HIVEAP_121_GPIO_XLNA1); ++ ++ /* SoC Wireless */ ++ ath79_init_mac(wlan0_mac, base + HIVEAP_121_MAC_OFFSET, 1); ++ ath79_register_wmac(NULL, wlan0_mac); /* Caldata in OTP */ ++ ++ /* PCIe Wireless */ ++ ath79_init_mac(wlan1_mac, base + HIVEAP_121_MAC_OFFSET, 2); ++ ap91_pci_init(NULL, wlan1_mac); /* Caldata in OTP */ ++} ++ ++MIPS_MACHINE(ATH79_MACH_HIVEAP_121, "HiveAP-121", "Aerohive HiveAP-121", ++ hiveap_121_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-hiwifi-hc6361.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-hiwifi-hc6361.c +new file mode 100644 +index 0000000000..6600595c05 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-hiwifi-hc6361.c +@@ -0,0 +1,115 @@ ++/* ++ * HiWiFi HC6361 board support ++ * ++ * Copyright (C) 2012-2013 eric ++ * Copyright (C) 2014 Yousong Zhou ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define HIWIFI_HC6361_GPIO_LED_WLAN_2P4 0 /* 2.4G WLAN LED */ ++#define HIWIFI_HC6361_GPIO_LED_SYSTEM 1 /* System LED */ ++#define HIWIFI_HC6361_GPIO_LED_INTERNET 27 /* Internet LED */ ++ ++#define HIWIFI_HC6361_GPIO_USBPOWER 20 /* USB power control */ ++#define HIWIFI_HC6361_GPIO_BTN_RST 11 /* Reset button */ ++ ++#define HIWIFI_HC6361_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define HIWIFI_HC6361_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * HIWIFI_HC6361_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led hiwifi_leds_gpio[] __initdata = { ++ { ++ .name = "hiwifi:blue:wlan-2p4", ++ .gpio = HIWIFI_HC6361_GPIO_LED_WLAN_2P4, ++ .active_low = 1, ++ }, { ++ .name = "hiwifi:blue:system", ++ .gpio = HIWIFI_HC6361_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "hiwifi:blue:internet", ++ .gpio = HIWIFI_HC6361_GPIO_LED_INTERNET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button hiwifi_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = HIWIFI_HC6361_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = HIWIFI_HC6361_GPIO_BTN_RST, ++ .active_low = 1, ++ } ++}; ++ ++static void __init get_mac_from_bdinfo(u8 *mac, void *bdinfo) ++{ ++ if (sscanf(bdinfo, "fac_mac = %2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], ++ &mac[4], &mac[5]) == 6) { ++ return; ++ } ++ ++ printk(KERN_WARNING "Parsing MAC address failed.\n"); ++ memcpy(mac, "\x00\xba\xbe\x00\x00\x00", 6); ++} ++ ++static void __init hiwifi_hc6361_setup(void) ++{ ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[6]; ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_m25p80(NULL); ++ ath79_gpio_function_enable( ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(hiwifi_leds_gpio), ++ hiwifi_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, HIWIFI_HC6361_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(hiwifi_gpio_keys), ++ hiwifi_gpio_keys); ++ gpio_request_one(HIWIFI_HC6361_GPIO_USBPOWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ get_mac_from_bdinfo(mac, (void *) KSEG1ADDR(0x1f010180)); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_HIWIFI_HC6361, "HiWiFi-HC6361", ++ "HiWiFi HC6361", hiwifi_hc6361_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-hornet-ub.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-hornet-ub.c +new file mode 100644 +index 0000000000..1d21424585 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-hornet-ub.c +@@ -0,0 +1,142 @@ ++/* ++ * ALFA NETWORK Hornet-UB board support ++ * ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define HORNET_UB_GPIO_LED_WLAN 0 ++#define HORNET_UB_GPIO_LED_USB 1 ++#define HORNET_UB_GPIO_LED_LAN 13 ++#define HORNET_UB_GPIO_LED_WAN 17 ++#define HORNET_UB_GPIO_LED_WPS 27 ++#define HORNET_UB_GPIO_EXT_LNA 28 ++ ++#define HORNET_UB_GPIO_BTN_RESET 12 ++#define HORNET_UB_GPIO_BTN_WPS 11 ++ ++#define HORNET_UB_GPIO_USB_POWER 26 ++ ++#define HORNET_UB_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define HORNET_UB_KEYS_DEBOUNCE_INTERVAL (3 * HORNET_UB_KEYS_POLL_INTERVAL) ++ ++#define HORNET_UB_MAC0_OFFSET 0x0000 ++#define HORNET_UB_MAC1_OFFSET 0x0006 ++#define HORNET_UB_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led hornet_ub_leds_gpio[] __initdata = { ++ { ++ .name = "alfa:blue:lan", ++ .gpio = HORNET_UB_GPIO_LED_LAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "alfa:blue:usb", ++ .gpio = HORNET_UB_GPIO_LED_USB, ++ .active_low = 0, ++ }, ++ { ++ .name = "alfa:blue:wan", ++ .gpio = HORNET_UB_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "alfa:blue:wlan", ++ .gpio = HORNET_UB_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "alfa:blue:wps", ++ .gpio = HORNET_UB_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button hornet_ub_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = HORNET_UB_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = HORNET_UB_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = HORNET_UB_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = HORNET_UB_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init hornet_ub_gpio_setup(void) ++{ ++ u32 t; ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ t |= AR933X_BOOTSTRAP_MDIO_GPIO_EN; ++ ath79_reset_wr(AR933X_RESET_REG_BOOTSTRAP, t); ++ ++ gpio_request_one(HORNET_UB_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ gpio_request_one(HORNET_UB_GPIO_EXT_LNA, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "external LNA0"); ++ ++} ++ ++static void __init hornet_ub_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ hornet_ub_gpio_setup(); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(hornet_ub_leds_gpio), ++ hornet_ub_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, HORNET_UB_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(hornet_ub_gpio_keys), ++ hornet_ub_gpio_keys); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ++ art + HORNET_UB_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + HORNET_UB_MAC1_OFFSET, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art + HORNET_UB_CALDATA_OFFSET, NULL); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_HORNET_UB, "HORNET-UB", "ALFA NETWORK Hornet-UB", ++ hornet_ub_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ja76pf.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ja76pf.c +new file mode 100644 +index 0000000000..d1fe0f8a26 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ja76pf.c +@@ -0,0 +1,190 @@ ++/* ++ * jjPlus JA76PF board support ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define JA76PF_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define JA76PF_KEYS_DEBOUNCE_INTERVAL (3 * JA76PF_KEYS_POLL_INTERVAL) ++ ++#define JA76PF_GPIO_I2C_SCL 0 ++#define JA76PF_GPIO_I2C_SDA 1 ++#define JA76PF_GPIO_LED_1 5 ++#define JA76PF_GPIO_LED_2 4 ++#define JA76PF_GPIO_LED_3 3 ++#define JA76PF_GPIO_BTN_RESET 11 ++ ++static struct gpio_led ja76pf_leds_gpio[] __initdata = { ++ { ++ .name = "jjplus:green:led1", ++ .gpio = JA76PF_GPIO_LED_1, ++ .active_low = 1, ++ }, { ++ .name = "jjplus:green:led2", ++ .gpio = JA76PF_GPIO_LED_2, ++ .active_low = 1, ++ }, { ++ .name = "jjplus:green:led3", ++ .gpio = JA76PF_GPIO_LED_3, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button ja76pf_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = JA76PF_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = JA76PF_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct i2c_gpio_platform_data ja76pf_i2c_gpio_data = { ++ .sda_pin = JA76PF_GPIO_I2C_SDA, ++ .scl_pin = JA76PF_GPIO_I2C_SCL, ++}; ++ ++static struct platform_device ja76pf_i2c_gpio_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &ja76pf_i2c_gpio_data, ++ } ++}; ++ ++static const char *ja76pf_part_probes[] = { ++ "RedBoot", ++ NULL, ++}; ++ ++static struct flash_platform_data ja76pf_flash_data = { ++ .part_probes = ja76pf_part_probes, ++}; ++ ++#define JA76PF_WAN_PHYMASK (1 << 4) ++#define JA76PF_LAN_PHYMASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 < 3)) ++#define JA76PF_MDIO_PHYMASK (JA76PF_LAN_PHYMASK | JA76PF_WAN_PHYMASK) ++ ++static void __init ja76pf_init(void) ++{ ++ ath79_register_m25p80(&ja76pf_flash_data); ++ ++ ath79_register_mdio(0, ~JA76PF_MDIO_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = JA76PF_LAN_PHYMASK; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = JA76PF_WAN_PHYMASK; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ platform_device_register(&ja76pf_i2c_gpio_device); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ja76pf_leds_gpio), ++ ja76pf_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, JA76PF_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ja76pf_gpio_keys), ++ ja76pf_gpio_keys); ++ ++ ath79_register_usb(); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_JA76PF, "JA76PF", "jjPlus JA76PF", ja76pf_init); ++ ++#define JA76PF2_GPIO_LED_D2 5 ++#define JA76PF2_GPIO_LED_D3 4 ++#define JA76PF2_GPIO_LED_D4 3 ++#define JA76PF2_GPIO_BTN_RESET 7 ++#define JA76PF2_GPIO_BTN_WPS 8 ++ ++static struct gpio_led ja76pf2_leds_gpio[] __initdata = { ++ { ++ .name = "jjplus:green:led1", ++ .gpio = JA76PF2_GPIO_LED_D2, ++ .active_low = 1, ++ }, { ++ .name = "jjplus:green:led2", ++ .gpio = JA76PF2_GPIO_LED_D3, ++ .active_low = 0, ++ }, { ++ .name = "jjplus:green:led3", ++ .gpio = JA76PF2_GPIO_LED_D4, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button ja76pf2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = JA76PF_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = JA76PF2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = JA76PF_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = JA76PF2_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++#define JA76PF2_LAN_PHYMASK BIT(0) ++#define JA76PF2_WAN_PHYMASK BIT(4) ++#define JA76PF2_MDIO_PHYMASK (JA76PF2_LAN_PHYMASK | JA76PF2_WAN_PHYMASK) ++ ++static void __init ja76pf2_init(void) ++{ ++ ath79_register_m25p80(&ja76pf_flash_data); ++ ++ ath79_register_mdio(0, ~JA76PF2_MDIO_PHYMASK); ++ ++ /* MAC0 is connected to the CPU port of the AR8316 switch */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ /* MAC1 is connected to the PHY4 of the AR8316 switch */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = BIT(4); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ja76pf2_leds_gpio), ++ ja76pf2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, JA76PF_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ja76pf2_gpio_keys), ++ ja76pf2_gpio_keys); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_JA76PF2, "JA76PF2", "jjPlus JA76PF2", ja76pf2_init); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-jwap003.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-jwap003.c +new file mode 100644 +index 0000000000..a3c93ccd90 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-jwap003.c +@@ -0,0 +1,95 @@ ++/* ++ * jjPlus JWAP003 board support ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define JWAP003_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define JWAP003_KEYS_DEBOUNCE_INTERVAL (3 * JWAP003_KEYS_POLL_INTERVAL) ++ ++#define JWAP003_GPIO_WPS 11 ++#define JWAP003_GPIO_I2C_SCL 0 ++#define JWAP003_GPIO_I2C_SDA 1 ++ ++static struct gpio_keys_button jwap003_gpio_keys[] __initdata = { ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = JWAP003_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = JWAP003_GPIO_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct i2c_gpio_platform_data jwap003_i2c_gpio_data = { ++ .sda_pin = JWAP003_GPIO_I2C_SDA, ++ .scl_pin = JWAP003_GPIO_I2C_SCL, ++}; ++ ++static struct platform_device jwap003_i2c_gpio_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &jwap003_i2c_gpio_data, ++ } ++}; ++ ++static const char *jwap003_part_probes[] = { ++ "RedBoot", ++ NULL, ++}; ++ ++static struct flash_platform_data jwap003_flash_data = { ++ .part_probes = jwap003_part_probes, ++}; ++ ++#define JWAP003_WAN_PHYMASK BIT(0) ++#define JWAP003_LAN_PHYMASK BIT(4) ++ ++static void __init jwap003_init(void) ++{ ++ ath79_register_m25p80(&jwap003_flash_data); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.phy_mask = JWAP003_WAN_PHYMASK; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.has_ar8216 = 1; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = JWAP003_LAN_PHYMASK; ++ ath79_eth1_data.speed = SPEED_100; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ platform_device_register(&jwap003_i2c_gpio_device); ++ ++ ath79_register_usb(); ++ ++ ath79_register_gpio_keys_polled(-1, JWAP003_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(jwap003_gpio_keys), ++ jwap003_gpio_keys); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_JWAP003, "JWAP003", "jjPlus JWAP003", jwap003_init); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-jwap230.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-jwap230.c +new file mode 100644 +index 0000000000..de24db4d4b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-jwap230.c +@@ -0,0 +1,158 @@ ++/* ++ * jjPlus JWAP230 board support ++ * ++ * Copyright (C) 2016 Piotr Dymacz ++ * ++ * Based on mach-wpj558.c and mach-tl-wr1043nd-v2.c ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define JWAP230_GPIO_LED_LED1 23 ++#define JWAP230_GPIO_LED_LED2 22 ++#define JWAP230_GPIO_LED_LED3 21 ++ ++#define JWAP230_MAC0_OFFSET 0x0 ++#define JWAP230_MAC1_OFFSET 0x6 ++#define JWAP230_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led jwap230_leds_gpio[] __initdata = { ++ { ++ .name = "jwap230:green:led1", ++ .gpio = JWAP230_GPIO_LED_LED1, ++ .active_low = 1, ++ }, ++ { ++ .name = "jwap230:green:led2", ++ .gpio = JWAP230_GPIO_LED_LED2, ++ .active_low = 1, ++ }, ++ { ++ .name = "jwap230:green:led3", ++ .gpio = JWAP230_GPIO_LED_LED3, ++ .active_low = 1, ++ } ++}; ++ ++static const struct ar8327_led_info jwap230_leds_qca8337[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "jwap230:green:lan"), ++ AR8327_LED_INFO(PHY4_0, HW, "jwap230:green:wan"), ++}; ++ ++/* Blink rate: 1 Gbps -> 8 hz, 100 Mbs -> 4 Hz, 10 Mbps -> 2 Hz */ ++static struct ar8327_led_cfg jwap230_qca8337_led_cfg = { ++ .led_ctrl0 = 0xcf37cf37, ++ .led_ctrl1 = 0xcf37cf37, ++ .led_ctrl2 = 0xcf37cf37, ++ .led_ctrl3 = 0x0, ++ .open_drain = true, ++}; ++ ++/* QCA8337 GMAC0 is connected with QCA9558 over RGMII */ ++static struct ar8327_pad_cfg jwap230_qca8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++ .mac06_exchange_dis = true, ++}; ++ ++/* QCA8337 GMAC6 is connected with QCA9558 over SGMII */ ++static struct ar8327_pad_cfg jwap230_qca8337_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++}; ++ ++static struct ar8327_platform_data jwap230_qca8337_data = { ++ .pad0_cfg = &jwap230_qca8337_pad0_cfg, ++ .pad6_cfg = &jwap230_qca8337_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &jwap230_qca8337_led_cfg, ++ .num_leds = ARRAY_SIZE(jwap230_leds_qca8337), ++ .leds = jwap230_leds_qca8337, ++}; ++ ++static struct mdio_board_info jwap230_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &jwap230_qca8337_data, ++ }, ++}; ++ ++static void __init jwap230_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(jwap230_leds_gpio), ++ jwap230_leds_gpio); ++ ++ mdiobus_register_board_info(jwap230_mdio0_info, ++ ARRAY_SIZE(jwap230_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* QCA9558 GMAC0 is connected to RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + JWAP230_MAC0_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ /* QCA9558 GMAC1 is connected to SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + JWAP230_MAC1_OFFSET, 0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + JWAP230_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_JWAP230, "JWAP230", "jjPlus JWAP230", jwap230_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-koala.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-koala.c +new file mode 100644 +index 0000000000..41254a6d7a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-koala.c +@@ -0,0 +1,161 @@ ++/* ++ * OCEDO Koala board support ++ * Based on the MR1750 machine file ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Marek Lindner ++ * 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 ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define KOALA_GPIO_LED_POWER 22 ++#define KOALA_GPIO_LED_WLAN_5G 13 ++#define KOALA_GPIO_LED_WLAN_2G 23 ++#define KOALA_GPIO_LED_WLAN_SYS 19 ++ ++#define KOALA_GPIO_BTN_RESET 17 ++ ++#define KOALA_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define KOALA_KEYS_DEBOUNCE_INTERVAL (3 * KOALA_KEYS_POLL_INTERVAL) ++ ++#define KOALA_LAN_MAC_OFFSET 0 ++#define KOALA_WIFI2G_MAC_OFFSET 0x06 ++#define KOALA_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led koala_leds_gpio[] __initdata = { ++ { ++ .name = "koala:green:power", ++ .gpio = KOALA_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "koala:red:wlan58", ++ .gpio = KOALA_GPIO_LED_WLAN_5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "koala:yellow:wlan2", ++ .gpio = KOALA_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "koala:blue:sys", ++ .gpio = KOALA_GPIO_LED_WLAN_SYS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button koala_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = KOALA_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = KOALA_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct at803x_platform_data koala_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 0, ++ .fixup_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info koala_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 5, ++ .platform_data = &koala_at803x_data, ++ }, ++}; ++ ++static void __init koala_setup_qca955x_eth_cfg(u32 mask, ++ unsigned int rxd, ++ unsigned int rxdv, ++ unsigned int txd, ++ unsigned int txe) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ ++ t = mask; ++ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; ++ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; ++ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; ++ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; ++ ++ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++static void __init koala_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ ath79_eth0_pll_data.pll_1000 = 0xae000000; ++ ath79_eth0_pll_data.pll_100 = 0xa0000101; ++ ath79_eth0_pll_data.pll_10 = 0xa0001313; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(koala_leds_gpio), ++ koala_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, KOALA_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(koala_gpio_keys), ++ koala_gpio_keys); ++ ++ ath79_init_mac(mac, art + KOALA_WIFI2G_MAC_OFFSET, 0); ++ ath79_register_wmac(art + KOALA_WMAC_CALDATA_OFFSET, mac); ++ ath79_register_pci(); ++ ++ koala_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 3, 3, 0, 0); ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(koala_mdio0_info, ++ ARRAY_SIZE(koala_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + KOALA_LAN_MAC_OFFSET, 0); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(5); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_KOALA, "KOALA", "OCEDO Koala", koala_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-lan-turtle.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-lan-turtle.c +new file mode 100644 +index 0000000000..d2faa2c740 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-lan-turtle.c +@@ -0,0 +1,178 @@ ++/* ++ * Hak5 LAN Turtle and Packet Squirrel boards support ++ * ++ * Copyright (C) 2018 Sebastian Kinne ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define LAN_TURTLE_GPIO_BTN_RESET 11 ++#define LAN_TURTLE_GPIO_LED_SYS 13 ++ ++#define PACKET_SQUIRREL_GPIO_BTN_SW1 18 ++#define PACKET_SQUIRREL_GPIO_BTN_SW2 20 ++#define PACKET_SQUIRREL_GPIO_BTN_SW3 21 ++#define PACKET_SQUIRREL_GPIO_BTN_SW4 24 ++#define PACKET_SQUIRREL_GPIO_BTN_RESET 11 ++#define PACKET_SQUIRREL_GPIO_LED_B 23 ++#define PACKET_SQUIRREL_GPIO_LED_G 22 ++#define PACKET_SQUIRREL_GPIO_LED_R 19 ++ ++#define HAK5_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define HAK5_KEYS_DEBOUNCE_INTERVAL (3 * HAK5_KEYS_POLL_INTERVAL) ++ ++static const char *hak5_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data hak5_flash_data = { ++ .part_probes = hak5_part_probes, ++}; ++ ++/* LAN Turtle */ ++static struct gpio_led lan_turtle_leds_gpio[] __initdata = { ++ { ++ .name = "lan-turtle:orange:system", ++ .gpio = LAN_TURTLE_GPIO_LED_SYS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button lan_turtle_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = HAK5_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = LAN_TURTLE_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++/* Packet Squirrel */ ++static struct gpio_led packet_squirrel_leds_gpio[] __initdata = { ++ { ++ .name = "packet-squirrel:blue:system", ++ .gpio = PACKET_SQUIRREL_GPIO_LED_B, ++ .active_low = 1, ++ }, { ++ .name = "packet-squirrel:green:system", ++ .gpio = PACKET_SQUIRREL_GPIO_LED_G, ++ .active_low = 1, ++ }, { ++ .name = "packet-squirrel:red:system", ++ .gpio = PACKET_SQUIRREL_GPIO_LED_R, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button packet_squirrel_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = HAK5_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PACKET_SQUIRREL_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "sw1", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = HAK5_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PACKET_SQUIRREL_GPIO_BTN_SW1, ++ .active_low = 1, ++ }, { ++ .desc = "sw2", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = HAK5_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PACKET_SQUIRREL_GPIO_BTN_SW2, ++ .active_low = 1, ++ }, { ++ .desc = "sw3", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = HAK5_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PACKET_SQUIRREL_GPIO_BTN_SW3, ++ .active_low = 1, ++ }, { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = BTN_3, ++ .debounce_interval = HAK5_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PACKET_SQUIRREL_GPIO_BTN_SW4, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init hak5_common_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ ++ ath79_register_m25p80(&hak5_flash_data); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy_poll_mask = 0xfe; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ++ /* GPIO11/12 */ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_UART_RTS_CTS_EN); ++} ++ ++static void __init lan_turtle_setup(void) ++{ ++ hak5_common_setup(); ++ ++ /* GPIO13 */ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(lan_turtle_leds_gpio), ++ lan_turtle_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, HAK5_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(lan_turtle_gpio_keys), ++ lan_turtle_gpio_keys); ++} ++ ++static void __init packet_squirrel_setup(void) ++{ ++ hak5_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(packet_squirrel_leds_gpio), ++ packet_squirrel_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, HAK5_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(packet_squirrel_gpio_keys), ++ packet_squirrel_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_LAN_TURTLE, "LAN-TURTLE", ++ "Hak5 LAN Turtle", lan_turtle_setup); ++ ++MIPS_MACHINE(ATH79_MACH_PACKET_SQUIRREL, "PACKET-SQUIRREL", ++ "Hak5 Packet Squirrel", packet_squirrel_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-lima.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-lima.c +new file mode 100644 +index 0000000000..9867429684 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-lima.c +@@ -0,0 +1,86 @@ ++/* ++ * 8devices Lima board support ++ * ++ * Copyright (C) 2016 Mantas Pucka ++ * Copyright (C) 2017 Karol Dudek ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define LIMA_GPIO_BTN_1_DEFAULT 16 ++#define LIMA_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define LIMA_KEYS_DEBOUNCE_INTERVAL (3 * LIMA_KEYS_POLL_INTERVAL) ++ ++#define LIMA_ETH_PHYS (BIT(0) | BIT(1)) ++ ++#define LIMA_MAC0_OFFSET 0x0000 ++#define LIMA_MAC1_OFFSET 0x0006 ++ ++#define LIMA_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_keys_button lima_gpio_keys[] __initdata = { ++ { ++ .desc = "button1", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = LIMA_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = LIMA_GPIO_BTN_1_DEFAULT, ++ .active_low = 1, ++ } ++}; ++ ++static void __init lima_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f080000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_gpio_keys_polled(-1, LIMA_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(lima_gpio_keys), ++ lima_gpio_keys); ++ ++ ath79_setup_ar933x_phy4_switch(true, true); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + LIMA_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + LIMA_MAC1_OFFSET, 0); ++ ++ ath79_register_mdio(0, ~LIMA_ETH_PHYS); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ++ ath79_switch_data.phy_poll_mask |= BIT(0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_mask = BIT(1); ++ ath79_register_eth(1); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art + LIMA_CALDATA_OFFSET, NULL); ++ ath79_register_usb(); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_LIMA, "LIMA", "8devices Lima board", lima_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mc-mac1200r.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mc-mac1200r.c +new file mode 100644 +index 0000000000..70051cff47 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mc-mac1200r.c +@@ -0,0 +1,155 @@ ++/* ++ * MERCURY MAC1200R board support ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2013 Gui Iribarren ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define MAC1200R_GPIO_LED_WLAN2G 13 ++#define MAC1200R_GPIO_LED_WLAN5G 17 ++#define MAC1200R_GPIO_LED_SYSTEM 14 ++#define MAC1200R_GPIO_LED_WPS 11 ++#define MAC1200R_GPIO_LED_WAN 12 ++#define MAC1200R_GPIO_LED_LAN1 15 ++#define MAC1200R_GPIO_LED_LAN2 21 ++#define MAC1200R_GPIO_LED_LAN3 22 ++#define MAC1200R_GPIO_LED_LAN4 20 ++ ++#define MAC1200R_GPIO_BTN_WPS 16 ++ ++#define MAC1200R_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MAC1200R_KEYS_DEBOUNCE_INTERVAL (3 * MAC1200R_KEYS_POLL_INTERVAL) ++ ++#define MAC1200R_MAC0_OFFSET 0 ++#define MAC1200R_MAC1_OFFSET 6 ++#define MAC1200R_WMAC_CALDATA_OFFSET 0x1000 ++#define MAC1200R_PCIE_CALDATA_OFFSET 0x5000 ++ ++static const char *mac1200r_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data mac1200r_flash_data = { ++ .part_probes = mac1200r_part_probes, ++}; ++ ++static struct gpio_led mac1200r_leds_gpio[] __initdata = { ++ { ++ .name = "mercury:green:wps", ++ .gpio = MAC1200R_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "mercury:green:system", ++ .gpio = MAC1200R_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "mercury:green:wlan2g", ++ .gpio = MAC1200R_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "mercury:green:wlan5g", ++ .gpio = MAC1200R_GPIO_LED_WLAN5G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button mac1200r_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MAC1200R_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MAC1200R_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++ ++static void __init mac1200r_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&mac1200r_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mac1200r_leds_gpio), ++ mac1200r_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, MAC1200R_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mac1200r_gpio_keys), ++ mac1200r_gpio_keys); ++ ++ ath79_init_mac(tmpmac, mac, 0); ++ ath79_wmac_disable_5ghz(); ++ ath79_register_wmac(art + MAC1200R_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_init_mac(tmpmac, mac, 1); ++ ap91_pci_init(art + MAC1200R_PCIE_CALDATA_OFFSET, tmpmac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* LAN */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 2); ++ ++ /* GMAC0 is connected to the PHY4 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ ath79_register_eth(0); ++ ++ ath79_gpio_output_select(MAC1200R_GPIO_LED_LAN1, ++ AR934X_GPIO_OUT_LED_LINK3); ++ ath79_gpio_output_select(MAC1200R_GPIO_LED_LAN2, ++ AR934X_GPIO_OUT_LED_LINK2); ++ ath79_gpio_output_select(MAC1200R_GPIO_LED_LAN3, ++ AR934X_GPIO_OUT_LED_LINK1); ++ ath79_gpio_output_select(MAC1200R_GPIO_LED_LAN4, ++ AR934X_GPIO_OUT_LED_LINK0); ++ ath79_gpio_output_select(MAC1200R_GPIO_LED_WAN, ++ AR934X_GPIO_OUT_LED_LINK4); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MC_MAC1200R, "MC-MAC1200R", ++ "MERCURY MAC1200R", ++ mac1200r_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr12.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr12.c +new file mode 100644 +index 0000000000..5a337e5c9f +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr12.c +@@ -0,0 +1,114 @@ ++/* ++ * Cisco Meraki MR12 board support ++ * ++ * Copyright (C) 2014-2015 Chris Blake ++ * ++ * Based on Atheros AP96 board support configuration ++ * ++ * Copyright (C) 2009 Marco Porsch ++ * Copyright (C) 2009-2012 Gabor Juhos ++ * Copyright (C) 2010 Atheros Communications ++ * ++ * 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 "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define MR12_GPIO_LED_W4_GREEN 14 ++#define MR12_GPIO_LED_W3_GREEN 13 ++#define MR12_GPIO_LED_W2_GREEN 12 ++#define MR12_GPIO_LED_W1_GREEN 11 ++ ++#define MR12_GPIO_LED_WAN 15 ++ ++#define MR12_GPIO_LED_POWER_ORANGE 16 ++#define MR12_GPIO_LED_POWER_GREEN 17 ++ ++#define MR12_GPIO_BTN_RESET 8 ++#define MR12_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MR12_KEYS_DEBOUNCE_INTERVAL (3 * MR12_KEYS_POLL_INTERVAL) ++ ++#define MR12_WAN_PHYMASK BIT(4) ++ ++#define MR12_CALDATA0_OFFSET 0x21000 ++ ++static struct gpio_led MR12_leds_gpio[] __initdata = { ++ { ++ .name = "mr12:green:wan", ++ .gpio = MR12_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "mr12:orange:power", ++ .gpio = MR12_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "mr12:green:power", ++ .gpio = MR12_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "mr12:green:wifi4", ++ .gpio = MR12_GPIO_LED_W4_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "mr12:green:wifi3", ++ .gpio = MR12_GPIO_LED_W3_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "mr12:green:wifi2", ++ .gpio = MR12_GPIO_LED_W2_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "mr12:green:wifi1", ++ .gpio = MR12_GPIO_LED_W1_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button MR12_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MR12_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MR12_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init MR12_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0xbffd0000); ++ u8 wlan_mac[ETH_ALEN]; ++ ++ ath79_register_mdio(0,0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = MR12_WAN_PHYMASK; ++ ath79_register_eth(0); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(MR12_leds_gpio), ++ MR12_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, MR12_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(MR12_gpio_keys), ++ MR12_gpio_keys); ++ ++ ath79_init_mac(wlan_mac, mac, 1); ++ ap91_pci_init(mac + MR12_CALDATA0_OFFSET, wlan_mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MR12, "MR12", "Meraki MR12", MR12_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr16.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr16.c +new file mode 100644 +index 0000000000..9da21eab5a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr16.c +@@ -0,0 +1,118 @@ ++/* ++ * Cisco Meraki MR16 board support ++ * ++ * Copyright (C) 2015 Chris Blake ++ * ++ * Based on Atheros AP96 board support configuration ++ * ++ * Copyright (C) 2009 Marco Porsch ++ * Copyright (C) 2009-2012 Gabor Juhos ++ * Copyright (C) 2010 Atheros Communications ++ * ++ * 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 "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define MR16_GPIO_LED_W4_GREEN 3 ++#define MR16_GPIO_LED_W3_GREEN 2 ++#define MR16_GPIO_LED_W2_GREEN 1 ++#define MR16_GPIO_LED_W1_GREEN 0 ++ ++#define MR16_GPIO_LED_WAN 4 ++ ++#define MR16_GPIO_LED_POWER_ORANGE 5 ++#define MR16_GPIO_LED_POWER_GREEN 6 ++ ++#define MR16_GPIO_BTN_RESET 7 ++#define MR16_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MR16_KEYS_DEBOUNCE_INTERVAL (3 * MR16_KEYS_POLL_INTERVAL) ++ ++#define MR16_WAN_PHYMASK BIT(0) ++ ++#define MR16_CALDATA0_OFFSET 0x21000 ++#define MR16_CALDATA1_OFFSET 0x25000 ++ ++static struct gpio_led MR16_leds_gpio[] __initdata = { ++ { ++ .name = "mr16:green:wan", ++ .gpio = MR16_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "mr16:orange:power", ++ .gpio = MR16_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "mr16:green:power", ++ .gpio = MR16_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "mr16:green:wifi4", ++ .gpio = MR16_GPIO_LED_W4_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "mr16:green:wifi3", ++ .gpio = MR16_GPIO_LED_W3_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "mr16:green:wifi2", ++ .gpio = MR16_GPIO_LED_W2_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "mr16:green:wifi1", ++ .gpio = MR16_GPIO_LED_W1_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button MR16_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MR16_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MR16_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init MR16_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0xbffd0000); ++ u8 wlan0_mac[ETH_ALEN]; ++ u8 wlan1_mac[ETH_ALEN]; ++ ++ ath79_register_mdio(0,0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = MR16_WAN_PHYMASK; ++ ath79_register_eth(0); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(MR16_leds_gpio), ++ MR16_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, MR16_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(MR16_gpio_keys), ++ MR16_gpio_keys); ++ ++ ath79_init_mac(wlan0_mac, mac, 1); ++ ath79_init_mac(wlan1_mac, mac, 2); ++ ap94_pci_init(mac + MR16_CALDATA0_OFFSET, wlan0_mac, ++ mac + MR16_CALDATA1_OFFSET, wlan1_mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MR16, "MR16", "Meraki MR16", MR16_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c +new file mode 100644 +index 0000000000..987ed4bd5d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c +@@ -0,0 +1,171 @@ ++/* ++ * MR1750 board support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Marek Lindner ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define MR1750_GPIO_LED_LAN 12 ++#define MR1750_GPIO_LED_WLAN_2G 13 ++#define MR1750_GPIO_LED_STATUS_GREEN 19 ++#define MR1750_GPIO_LED_STATUS_RED 21 ++#define MR1750_GPIO_LED_POWER 22 ++#define MR1750_GPIO_LED_WLAN_5G 23 ++ ++#define MR1750_GPIO_BTN_RESET 17 ++ ++#define MR1750_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MR1750_KEYS_DEBOUNCE_INTERVAL (3 * MR1750_KEYS_POLL_INTERVAL) ++ ++#define MR1750_MAC0_OFFSET 0 ++#define MR1750_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led mr1750_leds_gpio[] __initdata = { ++ { ++ .name = "mr1750:blue:power", ++ .gpio = MR1750_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr1750:blue:wan", ++ .gpio = MR1750_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr1750:blue:wlan24", ++ .gpio = MR1750_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr1750:blue:wlan58", ++ .gpio = MR1750_GPIO_LED_WLAN_5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr1750:green:status", ++ .gpio = MR1750_GPIO_LED_STATUS_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr1750:red:status", ++ .gpio = MR1750_GPIO_LED_STATUS_RED, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button mr1750_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MR1750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MR1750_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct at803x_platform_data mr1750_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 0, ++ .fixup_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info mr1750_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 5, ++ .platform_data = &mr1750_at803x_data, ++ }, ++}; ++ ++static void __init mr1750_setup_qca955x_eth_cfg(u32 mask, ++ unsigned int rxd, ++ unsigned int rxdv, ++ unsigned int txd, ++ unsigned int txe) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ ++ t = mask; ++ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; ++ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; ++ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; ++ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; ++ ++ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++static void __init mr1750_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ ath79_eth0_pll_data.pll_1000 = 0xae000000; ++ ath79_eth0_pll_data.pll_100 = 0xa0000101; ++ ath79_eth0_pll_data.pll_10 = 0xa0001313; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mr1750_leds_gpio), ++ mr1750_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, MR1750_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mr1750_gpio_keys), ++ mr1750_gpio_keys); ++ ++ ath79_init_mac(mac, art + MR1750_MAC0_OFFSET, 1); ++ ath79_register_wmac(art + MR1750_WMAC_CALDATA_OFFSET, mac); ++ ath79_register_pci(); ++ ++ mr1750_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 3, 3, 0, 0); ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(mr1750_mdio0_info, ++ ARRAY_SIZE(mr1750_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + MR1750_MAC0_OFFSET, 0); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(5); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MR1750, "MR1750", "OpenMesh MR1750", mr1750_setup); ++MIPS_MACHINE(ATH79_MACH_MR1750V2, "MR1750v2", "OpenMesh MR1750v2", mr1750_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr18.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr18.c +new file mode 100644 +index 0000000000..2d2fb6e84c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr18.c +@@ -0,0 +1,286 @@ ++/* ++ * Cisco Meraki MR18 board support ++ * ++ * Copyright (C) 2015 Chris Blake ++ * Copyright (C) 2015 Christian Lamparter ++ * Copyright (C) 2015 Thomas Hebb ++ * ++ * Based on Cisco Meraki GPL Release r23-20150601 MR18 Device Config ++ * ++ * 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 ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-nfc.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define MR18_GPIO_LED_POWER_WHITE 18 ++#define MR18_GPIO_LED_POWER_ORANGE 21 ++ ++#define MR18_GPIO_BTN_RESET 17 ++#define MR18_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MR18_KEYS_DEBOUNCE_INTERVAL (3 * MR18_KEYS_POLL_INTERVAL) ++ ++#define MR18_WAN_PHYADDR 3 ++ ++/* used for eth calibration */ ++#define MR18_OTP_BASE (AR71XX_APB_BASE + 0x130000) ++#define MR18_OTP_SIZE (0x2000) /* just a guess */ ++#define MR18_OTP_MEM_0_REG (0x0000) ++#define MR18_OTP_INTF2_REG (0x1008) ++#define MR18_OTP_STATUS0_REG (0x1018) ++#define MR18_OTP_STATUS0_EFUSE_VALID BIT(2) ++ ++#define MR18_OTP_STATUS1_REG (0x101c) ++#define MR18_OTP_LDO_CTRL_REG (0x1024) ++#define MR18_OTP_LDO_STATUS_REG (0x102c) ++#define MR18_OTP_LDO_STATUS_POWER_ON BIT(0) ++ ++static struct gpio_led MR18_leds_gpio[] __initdata = { ++ { ++ .name = "mr18:white:power", ++ .gpio = MR18_GPIO_LED_POWER_WHITE, ++ .active_low = 1, ++ }, { ++ .name = "mr18:orange:power", ++ .gpio = MR18_GPIO_LED_POWER_ORANGE, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button MR18_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MR18_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MR18_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct led_nu801_template tricolor_led_template = { ++ .device_name = "mr18", ++ .name = "tricolor", ++ .num_leds = 1, ++ .cki = 11, ++ .sdi = 12, ++ .lei = -1, ++ .ndelay = 500, ++ .init_brightness = { ++ LED_OFF, ++ LED_OFF, ++ LED_OFF, ++ }, ++ .default_trigger = "none", ++ .led_colors = { "red", "green", "blue" }, ++}; ++ ++static struct led_nu801_platform_data tricolor_led_data = { ++ .num_controllers = 1, ++ .template = &tricolor_led_template, ++}; ++ ++static struct platform_device tricolor_leds = { ++ .name = "leds-nu801", ++ .id = -1, ++ .dev.platform_data = &tricolor_led_data, ++}; ++ ++static int mr18_extract_sgmii_res_cal(void) ++{ ++ void __iomem *base; ++ unsigned int reversed_sgmii_value; ++ ++ unsigned int otp_value, otp_per_val, rbias_per, read_data; ++ unsigned int rbias_pos_or_neg; ++ unsigned int sgmii_res_cal_value; ++ int res_cal_val; ++ ++ base = ioremap_nocache(MR18_OTP_BASE, MR18_OTP_SIZE); ++ if (!base) ++ return -EIO; ++ ++ __raw_writel(0x7d, base + MR18_OTP_INTF2_REG); ++ __raw_writel(0x00, base + MR18_OTP_LDO_CTRL_REG); ++ ++ while (__raw_readl(base + MR18_OTP_LDO_STATUS_REG) & ++ MR18_OTP_LDO_STATUS_POWER_ON); ++ ++ __raw_readl(base + MR18_OTP_MEM_0_REG + 4); ++ ++ while (!(__raw_readl(base + MR18_OTP_STATUS0_REG) & ++ MR18_OTP_STATUS0_EFUSE_VALID)); ++ ++ read_data = __raw_readl(base + MR18_OTP_STATUS1_REG); ++ ++ iounmap(base); ++ ++ if (!(read_data & 0x1fff)) ++ return -ENODEV; ++ ++ if (read_data & 0x00001000) ++ otp_value = (read_data & 0xfc0) >> 6; ++ else ++ otp_value = read_data & 0x3f; ++ ++ if (otp_value > 31) { ++ otp_per_val = 63 - otp_value; ++ rbias_pos_or_neg = 1; ++ } else { ++ otp_per_val = otp_value; ++ rbias_pos_or_neg = 0; ++ } ++ ++ rbias_per = otp_per_val * 15; ++ ++ if (rbias_pos_or_neg == 1) ++ res_cal_val = (rbias_per + 34) / 21; ++ else if (rbias_per > 34) ++ res_cal_val = -((rbias_per - 34) / 21); ++ else ++ res_cal_val = (34 - rbias_per) / 21; ++ ++ sgmii_res_cal_value = (8 + res_cal_val) & 0xf; ++ ++ reversed_sgmii_value = (sgmii_res_cal_value & 8) >> 3; ++ reversed_sgmii_value |= (sgmii_res_cal_value & 4) >> 1; ++ reversed_sgmii_value |= (sgmii_res_cal_value & 2) << 1; ++ reversed_sgmii_value |= (sgmii_res_cal_value & 1) << 3; ++ printk(KERN_INFO "SGMII cal value = 0x%x\n", reversed_sgmii_value); ++ return reversed_sgmii_value; ++} ++ ++static void mr18_setup_qca955x_eth_serdes_cal(unsigned int sgmii_value) ++{ ++ void __iomem *ethbase, *pllbase; ++ u32 t; ++ ++ ethbase = ioremap_nocache(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ pllbase = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ ++ /* To Check the locking of the SGMII PLL */ ++ t = __raw_readl(ethbase + QCA955X_GMAC_REG_SGMII_SERDES); ++ t &= ~(QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK << ++ QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT); ++ t |= (sgmii_value & QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK) << ++ QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT; ++ __raw_writel(t, ethbase + QCA955X_GMAC_REG_SGMII_SERDES); ++ ++ __raw_writel(QCA955X_PLL_ETH_SGMII_SERDES_LOCK_DETECT | ++ QCA955X_PLL_ETH_SGMII_SERDES_PLL_REFCLK | ++ QCA955X_PLL_ETH_SGMII_SERDES_EN_PLL, ++ pllbase + QCA955X_PLL_ETH_SGMII_SERDES_REG); ++ ++ ath79_device_reset_clear(QCA955X_RESET_SGMII_ANALOG); ++ ath79_device_reset_clear(QCA955X_RESET_SGMII); ++ ++ while (!(__raw_readl(ethbase + QCA955X_GMAC_REG_SGMII_SERDES) & ++ QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS)); ++ ++ iounmap(ethbase); ++ iounmap(pllbase); ++} ++ ++static struct ath9k_platform_data pci_main_wifi_data = { ++ .led_pin = -1, ++}; ++static struct ath9k_platform_data pci_scan_wifi_data = { ++ .led_pin = -1, ++}; ++ ++static int mr18_dual_pci_plat_dev_init(struct pci_dev *dev) ++{ ++ /* The PCIE devices are attached to different busses but they ++ * both share the same slot number. Checking the PCI_SLOT vals ++ * does not work. ++ */ ++ switch (dev->bus->number) { ++ case 0: ++ dev->dev.platform_data = &pci_main_wifi_data; ++ break; ++ case 1: ++ dev->dev.platform_data = &pci_scan_wifi_data; ++ break; ++ } ++ ++ return 0; ++} ++ ++static void __init mr18_setup(void) ++{ ++ int res; ++ ++ /* NAND */ ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_SOFT_BCH); ++ ath79_register_nfc(); ++ ++ /* even though, the PHY is connected via RGMII, ++ * the SGMII/SERDES PLLs need to be calibrated and locked. ++ * Or else, the PHY won't be working for this platfrom. ++ * ++ * Figuring this out took such a long time, that we want to ++ * point this quirk out, before someone wants to remove it. ++ */ ++ res = mr18_extract_sgmii_res_cal(); ++ if (res >= 0) { ++ /* Setup SoC Eth Config */ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN | ++ (3 << QCA955X_ETH_CFG_RXD_DELAY_SHIFT) | ++ (3 << QCA955X_ETH_CFG_RDV_DELAY_SHIFT)); ++ ++ /* MDIO Interface */ ++ ath79_register_mdio(0, 0x0); ++ ++ mr18_setup_qca955x_eth_serdes_cal(res); ++ ++ /* GMAC0 is connected to an Atheros AR8035-A */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, NULL, 0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(MR18_WAN_PHYADDR); ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_eth0_pll_data.pll_100 = 0xa0000101; ++ ath79_eth0_pll_data.pll_10 = 0x80001313; ++ ath79_register_eth(0); ++ } else { ++ printk(KERN_ERR "failed to read EFUSE for ethernet cal\n"); ++ } ++ ++ /* LEDs and Buttons */ ++ platform_device_register(&tricolor_leds); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(MR18_leds_gpio), ++ MR18_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, MR18_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(MR18_gpio_keys), ++ MR18_gpio_keys); ++ ++ /* Clear RTC reset (Needed by SoC WiFi) */ ++ ath79_device_reset_clear(QCA955X_RESET_RTC); ++ ++ /* WiFi */ ++ ath79_register_wmac_simple(); ++ ++ pci_main_wifi_data.eeprom_name = "pci_wmac0.eeprom"; ++ pci_scan_wifi_data.eeprom_name = "pci_wmac1.eeprom"; ++ ath79_pci_set_plat_dev_init(mr18_dual_pci_plat_dev_init); ++ ath79_register_pci(); ++} ++MIPS_MACHINE(ATH79_MACH_MR18, "MR18", "Meraki MR18", mr18_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr600.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr600.c +new file mode 100644 +index 0000000000..701330cebd +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr600.c +@@ -0,0 +1,177 @@ ++/* ++ * OpenMesh OM2P board support ++ * ++ * Copyright (C) 2012 Marek Lindner ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define MR600_GPIO_LED_WLAN58 12 ++#define MR600_GPIO_LED_WPS 13 ++#define MR600_GPIO_LED_POWER 14 ++ ++#define MR600V2_GPIO_LED_WLAN58_RED 12 ++#define MR600V2_GPIO_LED_WPS 13 ++#define MR600V2_GPIO_LED_POWER 14 ++#define MR600V2_GPIO_LED_WLAN24_GREEN 18 ++#define MR600V2_GPIO_LED_WLAN24_YELLOW 19 ++#define MR600V2_GPIO_LED_WLAN24_RED 20 ++#define MR600V2_GPIO_LED_WLAN58_GREEN 21 ++#define MR600V2_GPIO_LED_WLAN58_YELLOW 22 ++ ++#define MR600_GPIO_BTN_RESET 17 ++ ++#define MR600_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MR600_KEYS_DEBOUNCE_INTERVAL (3 * MR600_KEYS_POLL_INTERVAL) ++ ++#define MR600_MAC_OFFSET 0 ++#define MR600_WMAC_CALDATA_OFFSET 0x1000 ++#define MR600_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led mr600_leds_gpio[] __initdata = { ++ { ++ .name = "mr600:orange:power", ++ .gpio = MR600_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:blue:wps", ++ .gpio = MR600_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:green:wlan58", ++ .gpio = MR600_GPIO_LED_WLAN58, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led mr600v2_leds_gpio[] __initdata = { ++ { ++ .name = "mr600:blue:power", ++ .gpio = MR600V2_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:blue:wps", ++ .gpio = MR600V2_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:red:wlan24", ++ .gpio = MR600V2_GPIO_LED_WLAN24_RED, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:yellow:wlan24", ++ .gpio = MR600V2_GPIO_LED_WLAN24_YELLOW, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:green:wlan24", ++ .gpio = MR600V2_GPIO_LED_WLAN24_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:red:wlan58", ++ .gpio = MR600V2_GPIO_LED_WLAN58_RED, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:yellow:wlan58", ++ .gpio = MR600V2_GPIO_LED_WLAN58_YELLOW, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr600:green:wlan58", ++ .gpio = MR600V2_GPIO_LED_WLAN58_GREEN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button mr600_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MR600_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MR600_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init mr600_base_setup(unsigned num_leds, struct gpio_led *leds) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, num_leds, leds); ++ ath79_register_gpio_keys_polled(-1, MR600_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mr600_gpio_keys), ++ mr600_gpio_keys); ++ ++ ath79_init_mac(mac, art + MR600_MAC_OFFSET, 1); ++ ath79_register_wmac(art + MR600_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_init_mac(mac, art + MR600_MAC_OFFSET, 8); ++ ap91_pci_init(art + MR600_PCIE_CALDATA_OFFSET, mac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + MR600_MAC_OFFSET, 0); ++ ++ /* GMAC0 is connected to an external PHY */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++} ++ ++static void __init mr600_setup(void) ++{ ++ mr600_base_setup(ARRAY_SIZE(mr600_leds_gpio), mr600_leds_gpio); ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MR600, "MR600", "OpenMesh MR600", mr600_setup); ++ ++static void __init mr600v2_setup(void) ++{ ++ mr600_base_setup(ARRAY_SIZE(mr600v2_leds_gpio), mr600v2_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MR600V2, "MR600v2", "OpenMesh MR600v2", mr600v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c +new file mode 100644 +index 0000000000..6b83c4cdf4 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c +@@ -0,0 +1,181 @@ ++/* ++ * MR900 board support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Marek Lindner ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define MR900_GPIO_LED_LAN 12 ++#define MR900_GPIO_LED_WLAN_2G 13 ++#define MR900_GPIO_LED_STATUS_GREEN 19 ++#define MR900_GPIO_LED_STATUS_RED 21 ++#define MR900_GPIO_LED_POWER 22 ++#define MR900_GPIO_LED_WLAN_5G 23 ++ ++#define MR900_GPIO_BTN_RESET 17 ++ ++#define MR900_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MR900_KEYS_DEBOUNCE_INTERVAL (3 * MR900_KEYS_POLL_INTERVAL) ++ ++#define MR900_MAC0_OFFSET 0 ++#define MR900_WMAC_CALDATA_OFFSET 0x1000 ++#define MR900_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led mr900_leds_gpio[] __initdata = { ++ { ++ .name = "mr900:blue:power", ++ .gpio = MR900_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr900:blue:wan", ++ .gpio = MR900_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr900:blue:wlan24", ++ .gpio = MR900_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr900:blue:wlan58", ++ .gpio = MR900_GPIO_LED_WLAN_5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr900:green:status", ++ .gpio = MR900_GPIO_LED_STATUS_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "mr900:red:status", ++ .gpio = MR900_GPIO_LED_STATUS_RED, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button mr900_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MR900_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MR900_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct at803x_platform_data mr900_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 0, ++ .fixup_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info mr900_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 5, ++ .platform_data = &mr900_at803x_data, ++ }, ++}; ++ ++static void __init mr900_setup_qca955x_eth_cfg(u32 mask, ++ unsigned int rxd, ++ unsigned int rxdv, ++ unsigned int txd, ++ unsigned int txe) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ ++ t = mask; ++ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; ++ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; ++ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; ++ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; ++ ++ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++static void __init mr900_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6], pcie_mac[6]; ++ struct ath9k_platform_data *pdata; ++ ++ ath79_eth0_pll_data.pll_1000 = 0xae000000; ++ ath79_eth0_pll_data.pll_100 = 0xa0000101; ++ ath79_eth0_pll_data.pll_10 = 0xa0001313; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mr900_leds_gpio), ++ mr900_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, MR900_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mr900_gpio_keys), ++ mr900_gpio_keys); ++ ++ ath79_init_mac(mac, art + MR900_MAC0_OFFSET, 1); ++ ath79_register_wmac(art + MR900_WMAC_CALDATA_OFFSET, mac); ++ ath79_init_mac(pcie_mac, art + MR900_MAC0_OFFSET, 16); ++ ap91_pci_init(art + MR900_PCIE_CALDATA_OFFSET, pcie_mac); ++ pdata = ap9x_pci_get_wmac_data(0); ++ if (!pdata) { ++ pr_err("mr900: unable to get address of wlan data\n"); ++ return; ++ } ++ pdata->use_eeprom = true; ++ ++ mr900_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 3, 3, 0, 0); ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(mr900_mdio0_info, ++ ARRAY_SIZE(mr900_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + MR900_MAC0_OFFSET, 0); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(5); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MR900, "MR900", "OpenMesh MR900", mr900_setup); ++MIPS_MACHINE(ATH79_MACH_MR900v2, "MR900v2", "OpenMesh MR900v2", mr900_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n600.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n600.c +new file mode 100644 +index 0000000000..a87413d201 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n600.c +@@ -0,0 +1,202 @@ ++/* ++ * WD My Net N600 board support ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define MYNET_N600_GPIO_LED_WIFI 0 ++#define MYNET_N600_GPIO_LED_POWER 11 ++#define MYNET_N600_GPIO_LED_INTERNET 12 ++#define MYNET_N600_GPIO_LED_WPS 13 ++ ++#define MYNET_N600_GPIO_LED_LAN1 4 ++#define MYNET_N600_GPIO_LED_LAN2 3 ++#define MYNET_N600_GPIO_LED_LAN3 2 ++#define MYNET_N600_GPIO_LED_LAN4 1 ++ ++#define MYNET_N600_GPIO_BTN_RESET 16 ++#define MYNET_N600_GPIO_BTN_WPS 17 ++ ++#define MYNET_N600_GPIO_EXTERNAL_LNA0 14 ++#define MYNET_N600_GPIO_EXTERNAL_LNA1 15 ++ ++#define MYNET_N600_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MYNET_N600_KEYS_DEBOUNCE_INTERVAL (3 * MYNET_N600_KEYS_POLL_INTERVAL) ++ ++#define MYNET_N600_MAC0_OFFSET 0 ++#define MYNET_N600_MAC1_OFFSET 6 ++#define MYNET_N600_WMAC_CALDATA_OFFSET 0x1000 ++#define MYNET_N600_PCIE_CALDATA_OFFSET 0x5000 ++ ++#define MYNET_N600_NVRAM_ADDR 0x1f058010 ++#define MYNET_N600_NVRAM_SIZE 0x7ff0 ++ ++static struct gpio_led mynet_n600_leds_gpio[] __initdata = { ++ { ++ .name = "wd:blue:power", ++ .gpio = MYNET_N600_GPIO_LED_POWER, ++ .active_low = 0, ++ }, ++ { ++ .name = "wd:blue:wps", ++ .gpio = MYNET_N600_GPIO_LED_WPS, ++ .active_low = 0, ++ }, ++ { ++ .name = "wd:blue:wireless", ++ .gpio = MYNET_N600_GPIO_LED_WIFI, ++ .active_low = 0, ++ }, ++ { ++ .name = "wd:blue:internet", ++ .gpio = MYNET_N600_GPIO_LED_INTERNET, ++ .active_low = 0, ++ }, ++ { ++ .name = "wd:green:lan1", ++ .gpio = MYNET_N600_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, ++ { ++ .name = "wd:green:lan2", ++ .gpio = MYNET_N600_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "wd:green:lan3", ++ .gpio = MYNET_N600_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, ++ { ++ .name = "wd:green:lan4", ++ .gpio = MYNET_N600_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button mynet_n600_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MYNET_N600_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MYNET_N600_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = MYNET_N600_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MYNET_N600_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static void mynet_n600_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(MYNET_N600_NVRAM_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, MYNET_N600_NVRAM_SIZE, ++ name, mac); ++ if (err) ++ pr_err("no MAC address found for %s\n", name); ++} ++ ++#define MYNET_N600_WAN_PHY_MASK BIT(0) ++ ++static void __init mynet_n600_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_gpio_output_select(MYNET_N600_GPIO_LED_LAN1, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_N600_GPIO_LED_LAN2, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_N600_GPIO_LED_LAN3, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_N600_GPIO_LED_LAN4, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_N600_GPIO_LED_INTERNET, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mynet_n600_leds_gpio), ++ mynet_n600_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, MYNET_N600_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mynet_n600_gpio_keys), ++ mynet_n600_gpio_keys); ++ ++ /* ++ * Control signal for external LNAs 0 and 1 ++ * Taken from GPL bootloader source: ++ * board/ar7240/db12x/alpha_gpio.c ++ */ ++ ath79_wmac_set_ext_lna_gpio(0, MYNET_N600_GPIO_EXTERNAL_LNA0); ++ ath79_wmac_set_ext_lna_gpio(1, MYNET_N600_GPIO_EXTERNAL_LNA1); ++ ++ mynet_n600_get_mac("wlan24mac=", tmpmac); ++ ath79_register_wmac(art + MYNET_N600_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ mynet_n600_get_mac("wlan5mac=", tmpmac); ++ ap91_pci_init(art + MYNET_N600_PCIE_CALDATA_OFFSET, tmpmac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE | ++ AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* LAN */ ++ mynet_n600_get_mac("lanmac=", ath79_eth1_data.mac_addr); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ mynet_n600_get_mac("wanmac=", ath79_eth0_data.mac_addr); ++ ++ /* GMAC0 is connected to the PHY4 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = MYNET_N600_WAN_PHY_MASK; ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = MYNET_N600_WAN_PHY_MASK; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ ath79_register_eth(0); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MYNET_N600, "MYNET-N600", "WD My Net N600", ++ mynet_n600_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n750.c +new file mode 100644 +index 0000000000..a822b6c3e2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n750.c +@@ -0,0 +1,226 @@ ++/* ++ * WD My Net N750 board support ++ * ++ * Copyright (C) 2013 Felix Kaechele ++ * Copyright (C) 2013 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++ ++/* ++ * Taken from GPL bootloader source: ++ * board/ar7240/db12x/alpha_gpio.c ++ */ ++#define MYNET_N750_GPIO_LED_WIFI 11 ++#define MYNET_N750_GPIO_LED_INTERNET 12 ++#define MYNET_N750_GPIO_LED_WPS 13 ++#define MYNET_N750_GPIO_LED_POWER 14 ++ ++#define MYNET_N750_GPIO_BTN_RESET 17 ++#define MYNET_N750_GPIO_BTN_WPS 19 ++ ++#define MYNET_N750_GPIO_EXTERNAL_LNA0 15 ++#define MYNET_N750_GPIO_EXTERNAL_LNA1 18 ++ ++#define MYNET_N750_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MYNET_N750_KEYS_DEBOUNCE_INTERVAL (3 * MYNET_N750_KEYS_POLL_INTERVAL) ++ ++#define MYNET_N750_WMAC_CALDATA_OFFSET 0x1000 ++#define MYNET_N750_PCIE_CALDATA_OFFSET 0x5000 ++ ++#define MYNET_N750_NVRAM_ADDR 0x1f058010 ++#define MYNET_N750_NVRAM_SIZE 0x7ff0 ++ ++static struct gpio_led mynet_n750_leds_gpio[] __initdata = { ++ { ++ .name = "wd:blue:power", ++ .gpio = MYNET_N750_GPIO_LED_POWER, ++ .active_low = 0, ++ }, ++ { ++ .name = "wd:blue:wps", ++ .gpio = MYNET_N750_GPIO_LED_WPS, ++ .active_low = 0, ++ }, ++ { ++ .name = "wd:blue:wireless", ++ .gpio = MYNET_N750_GPIO_LED_WIFI, ++ .active_low = 0, ++ }, ++ { ++ .name = "wd:blue:internet", ++ .gpio = MYNET_N750_GPIO_LED_INTERNET, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button mynet_n750_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MYNET_N750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MYNET_N750_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = MYNET_N750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MYNET_N750_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info mynet_n750_leds_ar8327[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "wd:green:lan1"), ++ AR8327_LED_INFO(PHY1_0, HW, "wd:green:lan2"), ++ AR8327_LED_INFO(PHY2_0, HW, "wd:green:lan3"), ++ AR8327_LED_INFO(PHY3_0, HW, "wd:green:lan4"), ++ AR8327_LED_INFO(PHY4_0, HW, "wd:green:wan"), ++ AR8327_LED_INFO(PHY0_1, HW, "wd:yellow:lan1"), ++ AR8327_LED_INFO(PHY1_1, HW, "wd:yellow:lan2"), ++ AR8327_LED_INFO(PHY2_1, HW, "wd:yellow:lan3"), ++ AR8327_LED_INFO(PHY3_1, HW, "wd:yellow:lan4"), ++ AR8327_LED_INFO(PHY4_1, HW, "wd:yellow:wan"), ++}; ++ ++static struct ar8327_pad_cfg mynet_n750_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg mynet_n750_ar8327_led_cfg = { ++ .led_ctrl0 = 0xcc35cc35, ++ .led_ctrl1 = 0xca35ca35, ++ .led_ctrl2 = 0xc935c935, ++ .led_ctrl3 = 0x03ffff00, ++ .open_drain = false, ++}; ++ ++static struct ar8327_platform_data mynet_n750_ar8327_data = { ++ .pad0_cfg = &mynet_n750_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &mynet_n750_ar8327_led_cfg, ++ .num_leds = ARRAY_SIZE(mynet_n750_leds_ar8327), ++ .leds = mynet_n750_leds_ar8327, ++}; ++ ++static struct mdio_board_info mynet_n750_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &mynet_n750_ar8327_data, ++ }, ++}; ++ ++static void mynet_n750_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(MYNET_N750_NVRAM_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, MYNET_N750_NVRAM_SIZE, ++ name, mac); ++ if (err) ++ pr_err("no MAC address found for %s\n", name); ++} ++ ++/* ++ * The bootloader on this board powers down all PHYs on the switch ++ * before booting the kernel. We bring all PHYs back up so that they are ++ * discoverable by the mdio bus scan and the switch is detected ++ * correctly. ++ */ ++static void mynet_n750_mdio_fixup(struct mii_bus *bus) ++{ ++ int i; ++ ++ for (i = 0; i < 5; i++) ++ bus->write(bus, i, MII_BMCR, ++ (BMCR_RESET | BMCR_ANENABLE | BMCR_SPEED1000)); ++ ++ mdelay(1000); ++} ++ ++static void __init mynet_n750_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mynet_n750_leds_gpio), ++ mynet_n750_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, MYNET_N750_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mynet_n750_gpio_keys), ++ mynet_n750_gpio_keys); ++ /* ++ * Control signal for external LNAs 0 and 1 ++ * Taken from GPL bootloader source: ++ * board/ar7240/db12x/alpha_gpio.c ++ */ ++ ath79_wmac_set_ext_lna_gpio(0, MYNET_N750_GPIO_EXTERNAL_LNA0); ++ ath79_wmac_set_ext_lna_gpio(1, MYNET_N750_GPIO_EXTERNAL_LNA1); ++ ++ mynet_n750_get_mac("wlan24mac=", tmpmac); ++ ath79_register_wmac(art + MYNET_N750_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ mynet_n750_get_mac("wlan5mac=", tmpmac); ++ ap91_pci_init(art + MYNET_N750_PCIE_CALDATA_OFFSET, tmpmac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ++ mdiobus_register_board_info(mynet_n750_mdio0_info, ++ ARRAY_SIZE(mynet_n750_mdio0_info)); ++ ++ ath79_mdio0_data.reset = mynet_n750_mdio_fixup; ++ ath79_register_mdio(0, 0x0); ++ ++ mynet_n750_get_mac("lanmac=", ath79_eth0_data.mac_addr); ++ ++ /* GMAC0 is connected to an AR8327N switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MYNET_N750, "MYNET-N750", "WD My Net N750", ++ mynet_n750_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c +new file mode 100644 +index 0000000000..cfb075b681 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c +@@ -0,0 +1,208 @@ ++/* ++ * WD My Net WI-FI Range Extender (Codename:Starfish db12x) board support ++ * ++ * Copyright (C) 2013 Christian Lamparter ++ * ++ * 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 ++ ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define MYNET_REXT_GPIO_LED_POWER 11 ++#define MYNET_REXT_GPIO_LED_ETHERNET 12 ++#define MYNET_REXT_GPIO_LED_WIFI 19 ++ ++#define MYNET_REXT_GPIO_LED_RF_QTY1 20 ++#define MYNET_REXT_GPIO_LED_RF_QTY2 21 ++#define MYNET_REXT_GPIO_LED_RF_QTY3 22 ++ ++#define MYNET_REXT_GPIO_BTN_RESET 13 ++#define MYNET_REXT_GPIO_BTN_WPS 15 ++#define MYNET_REXT_GPIO_SW_RF 14 ++ ++#define MYNET_REXT_GPIO_PHY_SWRST 16 /* disables Ethernet PHY */ ++#define MYNET_REXT_GPIO_PHY_INT 17 ++#define MYNET_REXT_GPIO_18 18 ++ ++#define MYNET_REXT_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MYNET_REXT_KEYS_DEBOUNCE_INTERVAL (3 * MYNET_REXT_KEYS_POLL_INTERVAL) ++ ++#define MYNET_REXT_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define MYNET_REXT_NVRAM_ADDR 0x1f7e0010 ++#define MYNET_REXT_NVRAM_SIZE 0xfff0 ++ ++#define MYNET_REXT_ART_ADDR 0x1f7f0000 ++ ++static const char *mynet_rext_part_probes[] = { ++ "cybertan", ++ NULL, ++}; ++ ++static struct flash_platform_data mynet_rext_flash_data = { ++ .type = "s25fl064k", ++ .part_probes = mynet_rext_part_probes, ++}; ++ ++static struct gpio_led mynet_rext_leds_gpio[] __initdata = { ++ { ++ .name = "wd:blue:power", ++ .gpio = MYNET_REXT_GPIO_LED_POWER, ++ .active_low = 0, ++ }, ++ { ++ .name = "wd:blue:wireless", ++ .gpio = MYNET_REXT_GPIO_LED_WIFI, ++ .active_low = 1, ++ }, ++ { ++ .name = "wd:blue:ethernet", ++ .gpio = MYNET_REXT_GPIO_LED_ETHERNET, ++ .active_low = 1, ++ }, ++ { ++ .name = "wd:blue:quality1", ++ .gpio = MYNET_REXT_GPIO_LED_RF_QTY1, ++ .active_low = 1, ++ }, ++ { ++ .name = "wd:blue:quality2", ++ .gpio = MYNET_REXT_GPIO_LED_RF_QTY2, ++ .active_low = 1, ++ }, ++ { ++ .name = "wd:blue:quality3", ++ .gpio = MYNET_REXT_GPIO_LED_RF_QTY3, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button mynet_rext_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MYNET_REXT_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MYNET_REXT_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = MYNET_REXT_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MYNET_REXT_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RF Band switch", ++ .type = EV_SW, ++ .code = BTN_1, ++ .debounce_interval = MYNET_REXT_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MYNET_REXT_GPIO_SW_RF, ++ }, ++}; ++ ++static struct at803x_platform_data mynet_rext_at803x_data = { ++ .disable_smarteee = 0, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 0, ++ .fixup_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info mynet_rext_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 4, ++ .platform_data = &mynet_rext_at803x_data, ++ }, ++}; ++ ++static void mynet_rext_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(MYNET_REXT_NVRAM_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, MYNET_REXT_NVRAM_SIZE, ++ name, mac); ++ if (err) ++ pr_err("no MAC address found for %s\n", name); ++} ++ ++static void __init mynet_rext_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(MYNET_REXT_ART_ADDR); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&mynet_rext_flash_data); ++ ++ /* GPIO configuration from drivers/char/GPIO8.c */ ++ ++ ath79_gpio_output_select(MYNET_REXT_GPIO_LED_POWER, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_REXT_GPIO_LED_WIFI, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_REXT_GPIO_LED_RF_QTY1, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_REXT_GPIO_LED_RF_QTY2, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_REXT_GPIO_LED_RF_QTY3, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(MYNET_REXT_GPIO_LED_ETHERNET, ++ AR934X_GPIO_OUT_GPIO); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mynet_rext_leds_gpio), ++ mynet_rext_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, MYNET_REXT_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mynet_rext_gpio_keys), ++ mynet_rext_gpio_keys); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_RXD_DELAY | ++ AR934X_ETH_CFG_RDV_DELAY); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(mynet_rext_mdio0_info, ++ ARRAY_SIZE(mynet_rext_mdio0_info)); ++ ++ /* LAN */ ++ mynet_rext_get_mac("et0macaddr=", ath79_eth0_data.mac_addr); ++ ++ /* GMAC0 is connected to an external PHY on Port 4 */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_pll_data.pll_10 = 0x00001313; /* athrs_mac.c */ ++ ath79_eth0_pll_data.pll_1000 = 0x0e000000; /* athrs_mac.c */ ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_register_eth(0); ++ ++ /* WLAN */ ++ mynet_rext_get_mac("wl0_hwaddr=", tmpmac); ++ ap91_pci_init(art + MYNET_REXT_WMAC_CALDATA_OFFSET, tmpmac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MYNET_REXT, "MYNET-REXT", ++ "WD My Net Wi-Fi Range Extender", mynet_rext_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mzk-w04nu.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mzk-w04nu.c +new file mode 100644 +index 0000000000..c2460ce33c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mzk-w04nu.c +@@ -0,0 +1,124 @@ ++/* ++ * Planex MZK-W04NU board support ++ * ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define MZK_W04NU_GPIO_LED_USB 0 ++#define MZK_W04NU_GPIO_LED_STATUS 1 ++#define MZK_W04NU_GPIO_LED_WPS 3 ++#define MZK_W04NU_GPIO_LED_WLAN 6 ++#define MZK_W04NU_GPIO_LED_AP 15 ++#define MZK_W04NU_GPIO_LED_ROUTER 16 ++ ++#define MZK_W04NU_GPIO_BTN_APROUTER 5 ++#define MZK_W04NU_GPIO_BTN_WPS 12 ++#define MZK_W04NU_GPIO_BTN_RESET 21 ++ ++#define MZK_W04NU_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MZK_W04NU_KEYS_DEBOUNCE_INTERVAL (3 * MZK_W04NU_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led mzk_w04nu_leds_gpio[] __initdata = { ++ { ++ .name = "planex:green:status", ++ .gpio = MZK_W04NU_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "planex:blue:wps", ++ .gpio = MZK_W04NU_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "planex:green:wlan", ++ .gpio = MZK_W04NU_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "planex:green:usb", ++ .gpio = MZK_W04NU_GPIO_LED_USB, ++ .active_low = 1, ++ }, { ++ .name = "planex:green:ap", ++ .gpio = MZK_W04NU_GPIO_LED_AP, ++ .active_low = 1, ++ }, { ++ .name = "planex:green:router", ++ .gpio = MZK_W04NU_GPIO_LED_ROUTER, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button mzk_w04nu_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MZK_W04NU_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MZK_W04NU_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = MZK_W04NU_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MZK_W04NU_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, { ++ .desc = "aprouter", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = MZK_W04NU_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MZK_W04NU_GPIO_BTN_APROUTER, ++ .active_low = 0, ++ } ++}; ++ ++#define MZK_W04NU_WAN_PHYMASK BIT(4) ++#define MZK_W04NU_MDIO_MASK (~MZK_W04NU_WAN_PHYMASK) ++ ++static void __init mzk_w04nu_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_mdio(0, MZK_W04NU_MDIO_MASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, eeprom, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.has_ar8216 = 1; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, eeprom, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = MZK_W04NU_WAN_PHYMASK; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mzk_w04nu_leds_gpio), ++ mzk_w04nu_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, MZK_W04NU_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mzk_w04nu_gpio_keys), ++ mzk_w04nu_gpio_keys); ++ ath79_register_usb(); ++ ++ ath79_register_wmac(eeprom, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MZK_W04NU, "MZK-W04NU", "Planex MZK-W04NU", ++ mzk_w04nu_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mzk-w300nh.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mzk-w300nh.c +new file mode 100644 +index 0000000000..8c40365283 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mzk-w300nh.c +@@ -0,0 +1,115 @@ ++/* ++ * Planex MZK-W300NH board support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define MZK_W300NH_GPIO_LED_STATUS 1 ++#define MZK_W300NH_GPIO_LED_WPS 3 ++#define MZK_W300NH_GPIO_LED_WLAN 6 ++#define MZK_W300NH_GPIO_LED_AP_GREEN 15 ++#define MZK_W300NH_GPIO_LED_AP_AMBER 16 ++ ++#define MZK_W300NH_GPIO_BTN_APROUTER 5 ++#define MZK_W300NH_GPIO_BTN_WPS 12 ++#define MZK_W300NH_GPIO_BTN_RESET 21 ++ ++#define MZK_W300NH_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define MZK_W300NH_KEYS_DEBOUNCE_INTERVAL (3 * MZK_W300NH_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led mzk_w300nh_leds_gpio[] __initdata = { ++ { ++ .name = "planex:green:status", ++ .gpio = MZK_W300NH_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "planex:blue:wps", ++ .gpio = MZK_W300NH_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "planex:green:wlan", ++ .gpio = MZK_W300NH_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "planex:green:aprouter", ++ .gpio = MZK_W300NH_GPIO_LED_AP_GREEN, ++ }, { ++ .name = "planex:amber:aprouter", ++ .gpio = MZK_W300NH_GPIO_LED_AP_AMBER, ++ } ++}; ++ ++static struct gpio_keys_button mzk_w300nh_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = MZK_W300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MZK_W300NH_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = MZK_W300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MZK_W300NH_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, { ++ .desc = "aprouter", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = MZK_W300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = MZK_W300NH_GPIO_BTN_APROUTER, ++ .active_low = 0, ++ } ++}; ++ ++#define MZK_W300NH_WAN_PHYMASK BIT(4) ++#define MZK_W300NH_MDIO_MASK (~MZK_W300NH_WAN_PHYMASK) ++ ++static void __init mzk_w300nh_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_mdio(0, MZK_W300NH_MDIO_MASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, eeprom, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.has_ar8216 = 1; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, eeprom, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = MZK_W300NH_WAN_PHYMASK; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(mzk_w300nh_leds_gpio), ++ mzk_w300nh_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, MZK_W300NH_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(mzk_w300nh_gpio_keys), ++ mzk_w300nh_gpio_keys); ++ ath79_register_wmac(eeprom, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_MZK_W300NH, "MZK-W300NH", "Planex MZK-W300NH", ++ mzk_w300nh_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-n5q.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-n5q.c +new file mode 100644 +index 0000000000..895fc32933 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-n5q.c +@@ -0,0 +1,132 @@ ++/* ++ * ALFA Network N5Q board support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define N5Q_GPIO_LED_LAN 19 ++#define N5Q_GPIO_LED_SIGNAL1 0 ++#define N5Q_GPIO_LED_SIGNAL2 1 ++#define N5Q_GPIO_LED_SIGNAL3 2 ++#define N5Q_GPIO_LED_SIGNAL4 3 ++#define N5Q_GPIO_LED_WAN 18 ++#define N5Q_GPIO_LED_WLAN 12 ++ ++#define N5Q_GPIO_WDT_EN 16 ++#define N5Q_GPIO_WDT_IN 17 ++ ++#define N5Q_GPIO_BTN_RESET 11 ++ ++#define N5Q_MAC0_OFFSET 0 ++#define N5Q_MAC1_OFFSET 6 ++#define N5Q_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define N5Q_KEYS_POLL_INTERVAL 20 ++#define N5Q_KEYS_DEBOUNCE_INTERVAL (3 * N5Q_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led n5q_leds_gpio[] __initdata = { ++ { ++ .name = "n5q:green:lan", ++ .gpio = N5Q_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "n5q:red:signal1", ++ .gpio = N5Q_GPIO_LED_SIGNAL1, ++ .active_low = 1, ++ }, { ++ .name = "n5q:orange:signal2", ++ .gpio = N5Q_GPIO_LED_SIGNAL2, ++ .active_low = 1, ++ }, { ++ .name = "n5q:green:signal3", ++ .gpio = N5Q_GPIO_LED_SIGNAL3, ++ .active_low = 1, ++ }, { ++ .name = "n5q:green:signal4", ++ .gpio = N5Q_GPIO_LED_SIGNAL4, ++ .active_low = 1, ++ }, { ++ .name = "n5q:green:wan", ++ .gpio = N5Q_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "n5q:green:wlan", ++ .gpio = N5Q_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button n5q_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = N5Q_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = N5Q_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init n5q_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f070000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = 0xf7; ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + N5Q_MAC1_OFFSET, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + N5Q_MAC0_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(n5q_leds_gpio), ++ n5q_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, N5Q_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(n5q_gpio_keys), ++ n5q_gpio_keys); ++ ++ gpio_request_one(N5Q_GPIO_WDT_IN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "WDT input"); ++ ++ gpio_request_one(N5Q_GPIO_WDT_EN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "WDT enable"); ++ ++ ath79_register_wmac(art + N5Q_WMAC_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_N5Q, "N5Q", "ALFA Network N5Q", n5q_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg460n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg460n.c +new file mode 100644 +index 0000000000..ca007779ec +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg460n.c +@@ -0,0 +1,220 @@ ++/* ++ * Zyxel NBG 460N/550N/550NH board support ++ * ++ * Copyright (C) 2010 Michael Kurz ++ * ++ * based on mach-tl-wr1043nd.c ++ * ++ * 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 ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++/* LEDs */ ++#define NBG460N_GPIO_LED_WPS 3 ++#define NBG460N_GPIO_LED_WAN 6 ++#define NBG460N_GPIO_LED_POWER 14 ++#define NBG460N_GPIO_LED_WLAN 15 ++ ++/* Buttons */ ++#define NBG460N_GPIO_BTN_WPS 12 ++#define NBG460N_GPIO_BTN_RESET 21 ++ ++#define NBG460N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define NBG460N_KEYS_DEBOUNCE_INTERVAL (3 * NBG460N_KEYS_POLL_INTERVAL) ++ ++/* RTC chip PCF8563 I2C interface */ ++#define NBG460N_GPIO_PCF8563_SDA 8 ++#define NBG460N_GPIO_PCF8563_SCK 7 ++ ++/* Switch configuration I2C interface */ ++#define NBG460N_GPIO_RTL8366_SDA 16 ++#define NBG460N_GPIO_RTL8366_SCK 18 ++ ++static struct mtd_partition nbg460n_partitions[] = { ++ { ++ .name = "Bootbase", ++ .offset = 0, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "U-Boot Config", ++ .offset = 0x010000, ++ .size = 0x030000, ++ }, { ++ .name = "U-Boot", ++ .offset = 0x040000, ++ .size = 0x030000, ++ }, { ++ .name = "linux", ++ .offset = 0x070000, ++ .size = 0x0e0000, ++ }, { ++ .name = "rootfs", ++ .offset = 0x150000, ++ .size = 0x2a0000, ++ }, { ++ .name = "CalibData", ++ .offset = 0x3f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x070000, ++ .size = 0x380000, ++ } ++}; ++ ++static struct flash_platform_data nbg460n_flash_data = { ++ .parts = nbg460n_partitions, ++ .nr_parts = ARRAY_SIZE(nbg460n_partitions), ++}; ++ ++static struct gpio_led nbg460n_leds_gpio[] __initdata = { ++ { ++ .name = "nbg460n:green:power", ++ .gpio = NBG460N_GPIO_LED_POWER, ++ .active_low = 0, ++ .default_trigger = "default-on", ++ }, { ++ .name = "nbg460n:green:wps", ++ .gpio = NBG460N_GPIO_LED_WPS, ++ .active_low = 0, ++ }, { ++ .name = "nbg460n:green:wlan", ++ .gpio = NBG460N_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, { ++ /* Not really for controlling the LED, ++ when set low the LED blinks uncontrollable */ ++ .name = "nbg460n:green:wan", ++ .gpio = NBG460N_GPIO_LED_WAN, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button nbg460n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = NBG460N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG460N_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = NBG460N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG460N_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct i2c_gpio_platform_data nbg460n_i2c_device_platdata = { ++ .sda_pin = NBG460N_GPIO_PCF8563_SDA, ++ .scl_pin = NBG460N_GPIO_PCF8563_SCK, ++ .udelay = 10, ++}; ++ ++static struct platform_device nbg460n_i2c_device = { ++ .name = "i2c-gpio", ++ .id = -1, ++ .num_resources = 0, ++ .resource = NULL, ++ .dev = { ++ .platform_data = &nbg460n_i2c_device_platdata, ++ }, ++}; ++ ++static struct i2c_board_info nbg460n_i2c_devs[] __initdata = { ++ { ++ I2C_BOARD_INFO("pcf8563", 0x51), ++ }, ++}; ++ ++static void nbg460n_i2c_init(void) ++{ ++ /* The gpio interface */ ++ platform_device_register(&nbg460n_i2c_device); ++ /* I2C devices */ ++ i2c_register_board_info(0, nbg460n_i2c_devs, ++ ARRAY_SIZE(nbg460n_i2c_devs)); ++} ++ ++ ++static struct rtl8366_platform_data nbg460n_rtl8366s_data = { ++ .gpio_sda = NBG460N_GPIO_RTL8366_SDA, ++ .gpio_sck = NBG460N_GPIO_RTL8366_SCK, ++}; ++ ++static struct platform_device nbg460n_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &nbg460n_rtl8366s_data, ++ } ++}; ++ ++static void __init nbg460n_setup(void) ++{ ++ /* end of bootloader sector contains mac address */ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fc0fff8); ++ /* last sector contains wlan calib data */ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* LAN Port */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.mii_bus_dev = &nbg460n_rtl8366s_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ /* WAN Port */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ath79_eth1_data.mii_bus_dev = &nbg460n_rtl8366s_device.dev; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ /* register the switch phy */ ++ platform_device_register(&nbg460n_rtl8366s_device); ++ ++ /* register flash */ ++ ath79_register_m25p80(&nbg460n_flash_data); ++ ++ ath79_register_wmac(eeprom, mac); ++ ++ /* register RTC chip */ ++ nbg460n_i2c_init(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(nbg460n_leds_gpio), ++ nbg460n_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, NBG460N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(nbg460n_gpio_keys), ++ nbg460n_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_NBG460N, "NBG460N", "Zyxel NBG460N/550N/550NH", ++ nbg460n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg6716.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg6716.c +new file mode 100644 +index 0000000000..b0fbb78d82 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-nbg6716.c +@@ -0,0 +1,385 @@ ++/* ++ * ZyXEL NBG6716/NBG6616 board support ++ * ++ * Based on the Qualcomm Atheros AP135/AP136 reference board support code ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * Copyright (c) 2013 Andre Valentin ++ * ++ * 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 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++ ++#include ++ ++#include "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-nfc.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define NBG6716_GPIO_LED_INTERNET 18 ++#define NBG6716_GPIO_LED_POWER 15 ++#define NBG6716_GPIO_LED_USB1 4 ++#define NBG6716_GPIO_LED_USB2 13 ++#define NBG6716_GPIO_LED_WIFI2G 19 ++#define NBG6716_GPIO_LED_WIFI5G 17 ++#define NBG6716_GPIO_LED_WPS 21 ++ ++#define NBG6716_GPIO_BTN_RESET 23 ++#define NBG6716_GPIO_BTN_RFKILL 1 ++#define NBG6716_GPIO_BTN_USB1 0 ++#define NBG6716_GPIO_BTN_USB2 14 ++#define NBG6716_GPIO_BTN_WPS 22 ++ ++#define NBG6716_GPIO_USB_POWER 16 ++ ++#define NBG6716_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define NBG6716_KEYS_DEBOUNCE_INTERVAL (3 * NBG6716_KEYS_POLL_INTERVAL) ++ ++#define NBG6716_MAC0_OFFSET 0 ++#define NBG6716_MAC1_OFFSET 6 ++#define NBG6716_WMAC_CALDATA_OFFSET 0x1000 ++#define NBG6716_PCIE_CALDATA_OFFSET 0x5000 ++ ++/* NBG6616 has a different GPIO usage as it does not have USB Buttons */ ++#define NBG6616_GPIO_LED_USB0 14 ++#define NBG6616_GPIO_LED_USB1 21 ++#define NBG6616_GPIO_LED_WPS 0 ++ ++static struct gpio_led nbg6716_leds_gpio[] __initdata = { ++ { ++ .name = "nbg6716:white:internet", ++ .gpio = NBG6716_GPIO_LED_INTERNET, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6716:white:power", ++ .gpio = NBG6716_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6716:white:usb1", ++ .gpio = NBG6716_GPIO_LED_USB1, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6716:white:usb2", ++ .gpio = NBG6716_GPIO_LED_USB2, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6716:white:wifi2g", ++ .gpio = NBG6716_GPIO_LED_WIFI2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6716:white:wifi5g", ++ .gpio = NBG6716_GPIO_LED_WIFI5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6716:white:wps", ++ .gpio = NBG6716_GPIO_LED_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button nbg6716_gpio_keys[] __initdata = { ++ { ++ .desc = "RESET button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = NBG6716_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG6716_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = NBG6716_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG6716_GPIO_BTN_RFKILL, ++ .active_low = 0, ++ }, ++ { ++ .desc = "USB1 eject button", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = NBG6716_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG6716_GPIO_BTN_USB1, ++ .active_low = 1, ++ }, ++ { ++ .desc = "USB2 eject button", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = NBG6716_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG6716_GPIO_BTN_USB2, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = NBG6716_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG6716_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++ ++ ++static struct gpio_led nbg6616_leds_gpio[] __initdata = { ++ { ++ .name = "nbg6616:green:power", ++ .gpio = NBG6716_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6616:green:usb2", ++ .gpio = NBG6616_GPIO_LED_USB0, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6616:green:usb1", ++ .gpio = NBG6616_GPIO_LED_USB1, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6616:green:wifi2g", ++ .gpio = NBG6716_GPIO_LED_WIFI2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6616:green:wifi5g", ++ .gpio = NBG6716_GPIO_LED_WIFI5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "nbg6616:green:wps", ++ .gpio = NBG6616_GPIO_LED_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button nbg6616_gpio_keys[] __initdata = { ++ { ++ .desc = "RESET button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = NBG6716_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG6716_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = NBG6716_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG6716_GPIO_BTN_RFKILL, ++ .active_low = 0, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = NBG6716_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = NBG6716_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++ ++static struct ar8327_pad_cfg nbg6716_ar8327_pad0_cfg; ++static struct ar8327_pad_cfg nbg6716_ar8327_pad6_cfg; ++static struct ar8327_led_cfg nbg6716_ar8327_led_cfg; ++ ++static struct ar8327_platform_data nbg6716_ar8327_data = { ++ .pad0_cfg = &nbg6716_ar8327_pad0_cfg, ++ .pad6_cfg = &nbg6716_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &nbg6716_ar8327_led_cfg ++}; ++ ++static struct mdio_board_info nbg6716_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &nbg6716_ar8327_data, ++ }, ++}; ++ ++static void nbg6716_get_mac(void* nvram_addr, const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(nvram_addr); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, 0x10000, ++ name, mac); ++ if (err) ++ pr_err("no MAC address found for %s\n", name); ++} ++ ++static void __init nbg6716_common_setup(u32 leds_num, struct gpio_led* leds, ++ u32 keys_num, ++ struct gpio_keys_button* keys, ++ void* art_addr, void* nvram) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(art_addr); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, leds_num, leds); ++ ath79_register_gpio_keys_polled(-1, NBG6716_KEYS_POLL_INTERVAL, ++ keys_num, keys); ++ ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_HW); ++ ath79_register_nfc(); ++ ++ gpio_request_one(NBG6716_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ ath79_register_usb(); ++ ++ nbg6716_get_mac(nvram, "ethaddr=", tmpmac); ++ ++ ath79_register_pci(); ++ ++ ath79_register_wmac(art + NBG6716_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, tmpmac, 2); ++ ath79_init_mac(ath79_eth1_data.mac_addr, tmpmac, 3); ++ ++ mdiobus_register_board_info(nbg6716_mdio0_info, ++ ARRAY_SIZE(nbg6716_mdio0_info)); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++} ++ ++static void __init nbg6716_010_setup(void) ++{ ++ /* GMAC0 of the AR8337 switch is connected to GMAC0 via RGMII */ ++ nbg6716_ar8327_pad0_cfg.mode = AR8327_PAD_MAC_RGMII; ++ nbg6716_ar8327_pad0_cfg.txclk_delay_en = true; ++ nbg6716_ar8327_pad0_cfg.rxclk_delay_en = true; ++ nbg6716_ar8327_pad0_cfg.txclk_delay_sel = AR8327_CLK_DELAY_SEL1; ++ nbg6716_ar8327_pad0_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL2; ++ ++ /* GMAC6 of the AR8337 switch is connected to GMAC1 via SGMII */ ++ nbg6716_ar8327_pad6_cfg.mode = AR8327_PAD_MAC_SGMII; ++ nbg6716_ar8327_pad6_cfg.rxclk_delay_en = true; ++ nbg6716_ar8327_pad6_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL0; ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ nbg6716_ar8327_led_cfg.open_drain = 0; ++ nbg6716_ar8327_led_cfg.led_ctrl0 = 0xffb7ffb7; ++ nbg6716_ar8327_led_cfg.led_ctrl1 = 0xffb7ffb7; ++ nbg6716_ar8327_led_cfg.led_ctrl2 = 0xffb7ffb7; ++ nbg6716_ar8327_led_cfg.led_ctrl3 = 0x03ffff00; ++ ++ nbg6716_common_setup(ARRAY_SIZE(nbg6716_leds_gpio), nbg6716_leds_gpio, ++ ARRAY_SIZE(nbg6716_gpio_keys), nbg6716_gpio_keys, ++ (void*) 0x1f050000, (void*) 0x1f040000); ++} ++ ++static void __init nbg6616_010_setup(void) ++{ ++ /* GMAC0 of the AR8337 switch is connected to GMAC0 via RGMII */ ++ nbg6716_ar8327_pad0_cfg.mode = AR8327_PAD_MAC_RGMII; ++ nbg6716_ar8327_pad0_cfg.txclk_delay_en = true; ++ nbg6716_ar8327_pad0_cfg.rxclk_delay_en = true; ++ nbg6716_ar8327_pad0_cfg.txclk_delay_sel = AR8327_CLK_DELAY_SEL1; ++ nbg6716_ar8327_pad0_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL2; ++ ++ /* GMAC6 of the AR8337 switch is connected to GMAC1 via SGMII */ ++ nbg6716_ar8327_pad6_cfg.mode = AR8327_PAD_MAC_SGMII; ++ nbg6716_ar8327_pad6_cfg.rxclk_delay_en = true; ++ nbg6716_ar8327_pad6_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL0; ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ nbg6716_ar8327_led_cfg.open_drain = 0; ++ nbg6716_ar8327_led_cfg.led_ctrl0 = 0xffb7ffb7; ++ nbg6716_ar8327_led_cfg.led_ctrl1 = 0xffb7ffb7; ++ nbg6716_ar8327_led_cfg.led_ctrl2 = 0xffb7ffb7; ++ nbg6716_ar8327_led_cfg.led_ctrl3 = 0x03ffff00; ++ ++ ++ nbg6716_common_setup(ARRAY_SIZE(nbg6616_leds_gpio), nbg6616_leds_gpio, ++ ARRAY_SIZE(nbg6616_gpio_keys), nbg6616_gpio_keys, ++ (void*) 0x1f040000, (void*) 0x1f030000); ++} ++ ++ ++MIPS_MACHINE(ATH79_MACH_NBG6716, "NBG6716", ++ "Zyxel NBG6716", ++ nbg6716_010_setup); ++ ++MIPS_MACHINE(ATH79_MACH_NBG6616, "NBG6616", ++ "Zyxel NBG6616", ++ nbg6616_010_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-om2p.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-om2p.c +new file mode 100644 +index 0000000000..c888f7d1a8 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-om2p.c +@@ -0,0 +1,320 @@ ++/* ++ * OpenMesh OM2P support ++ * ++ * Copyright (C) 2011 Marek Lindner ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define OM2P_GPIO_LED_POWER 0 ++#define OM2P_GPIO_LED_GREEN 13 ++#define OM2P_GPIO_LED_RED 14 ++#define OM2P_GPIO_LED_YELLOW 15 ++#define OM2P_GPIO_LED_LAN 16 ++#define OM2P_GPIO_LED_WAN 17 ++#define OM2P_GPIO_BTN_RESET 1 ++ ++#define OM2P_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define OM2P_KEYS_DEBOUNCE_INTERVAL (3 * OM2P_KEYS_POLL_INTERVAL) ++ ++#define OM2P_WAN_PHYMASK BIT(4) ++ ++#define OM2P_LC_GPIO_LED_POWER 1 ++#define OM2P_LC_GPIO_LED_GREEN 15 ++#define OM2P_LC_GPIO_LED_RED 16 ++#define OM2P_LC_GPIO_LED_YELLOW 0 ++#define OM2P_LC_GPIO_LED_LAN 13 ++#define OM2P_LC_GPIO_LED_WAN 17 ++#define OM2P_LC_GPIO_BTN_RESET 12 ++ ++#define OM2Pv4_GPIO_LED_POWER 0 ++#define OM2Pv4_GPIO_LED_GREEN 2 ++#define OM2Pv4_GPIO_LED_RED 4 ++#define OM2Pv4_GPIO_LED_YELLOW 3 ++#define OM2Pv4_GPIO_LED_LAN 14 ++#define OM2Pv4_GPIO_LED_WAN 13 ++#define OM2Pv4_GPIO_BTN_RESET 1 ++ ++#define OM2P_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct flash_platform_data om2p_flash_data = { ++ .type = "s25sl12800", ++ .name = "ar7240-nor0", ++}; ++ ++static struct gpio_led om2p_leds_gpio[] __initdata = { ++ { ++ .name = "om2p:blue:power", ++ .gpio = OM2P_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "om2p:red:wifi", ++ .gpio = OM2P_GPIO_LED_RED, ++ .active_low = 1, ++ }, { ++ .name = "om2p:yellow:wifi", ++ .gpio = OM2P_GPIO_LED_YELLOW, ++ .active_low = 1, ++ }, { ++ .name = "om2p:green:wifi", ++ .gpio = OM2P_GPIO_LED_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "om2p:blue:lan", ++ .gpio = OM2P_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "om2p:blue:wan", ++ .gpio = OM2P_GPIO_LED_WAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button om2p_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = OM2P_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = OM2P_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init om2p_setup(void) ++{ ++ u8 *mac1 = (u8 *)KSEG1ADDR(0x1ffc0000); ++ u8 *mac2 = (u8 *)KSEG1ADDR(0x1ffc0000 + ETH_ALEN); ++ u8 *ee = (u8 *)KSEG1ADDR(0x1ffc1000); ++ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_m25p80(&om2p_flash_data); ++ ++ ath79_register_mdio(0, ~OM2P_WAN_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ap91_pci_init(ee, NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(om2p_leds_gpio), ++ om2p_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, OM2P_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(om2p_gpio_keys), ++ om2p_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OM2P, "OM2P", "OpenMesh OM2P", om2p_setup); ++ ++ ++static struct flash_platform_data om2p_lc_flash_data = { ++ .type = "s25sl12800", ++}; ++ ++static void __init om2p_lc_setup(void) ++{ ++ u8 *mac1 = (u8 *)KSEG1ADDR(0x1ffc0000); ++ u8 *mac2 = (u8 *)KSEG1ADDR(0x1ffc0000 + ETH_ALEN); ++ u8 *art = (u8 *)KSEG1ADDR(0x1ffc1000); ++ u32 t; ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ t |= AR933X_BOOTSTRAP_MDIO_GPIO_EN; ++ ath79_reset_wr(AR933X_RESET_REG_BOOTSTRAP, t); ++ ++ ath79_register_m25p80(&om2p_lc_flash_data); ++ ++ om2p_leds_gpio[0].gpio = OM2P_LC_GPIO_LED_POWER; ++ om2p_leds_gpio[1].gpio = OM2P_LC_GPIO_LED_RED; ++ om2p_leds_gpio[2].gpio = OM2P_LC_GPIO_LED_YELLOW; ++ om2p_leds_gpio[3].gpio = OM2P_LC_GPIO_LED_GREEN; ++ om2p_leds_gpio[4].gpio = OM2P_LC_GPIO_LED_LAN; ++ om2p_leds_gpio[5].gpio = OM2P_LC_GPIO_LED_WAN; ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(om2p_leds_gpio), ++ om2p_leds_gpio); ++ ++ om2p_gpio_keys[0].gpio = OM2P_LC_GPIO_BTN_RESET; ++ ath79_register_gpio_keys_polled(-1, OM2P_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(om2p_gpio_keys), ++ om2p_gpio_keys); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OM2P_LC, "OM2P-LC", "OpenMesh OM2P LC", om2p_lc_setup); ++MIPS_MACHINE(ATH79_MACH_OM2Pv2, "OM2Pv2", "OpenMesh OM2Pv2", om2p_lc_setup); ++ ++static void __init om2p_hs_setup(void) ++{ ++ u8 *mac1 = (u8 *)KSEG1ADDR(0x1ffc0000); ++ u8 *mac2 = (u8 *)KSEG1ADDR(0x1ffc0000 + ETH_ALEN); ++ u8 *art = (u8 *)KSEG1ADDR(0x1ffc1000); ++ ++ /* make lan / wan leds software controllable */ ++ ath79_gpio_output_select(OM2P_GPIO_LED_LAN, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(OM2P_GPIO_LED_WAN, AR934X_GPIO_OUT_GPIO); ++ ++ /* enable reset button */ ++ ath79_gpio_output_select(OM2P_GPIO_BTN_RESET, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ om2p_leds_gpio[4].gpio = OM2P_GPIO_LED_WAN; ++ om2p_leds_gpio[5].gpio = OM2P_GPIO_LED_LAN; ++ ++ ath79_register_m25p80(&om2p_lc_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(om2p_leds_gpio), ++ om2p_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, OM2P_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(om2p_gpio_keys), ++ om2p_gpio_keys); ++ ++ ath79_register_wmac(art, NULL); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OM2P_HS, "OM2P-HS", "OpenMesh OM2P HS", om2p_hs_setup); ++MIPS_MACHINE(ATH79_MACH_OM2P_HSv2, "OM2P-HSv2", "OpenMesh OM2P HSv2", om2p_hs_setup); ++MIPS_MACHINE(ATH79_MACH_OM2P_HSv3, "OM2P-HSv3", "OpenMesh OM2P HSv3", om2p_hs_setup); ++ ++static struct flash_platform_data om2pv4_flash_data = { ++ .type = "s25sl12800", ++}; ++ ++static struct gpio_led om2pv4_leds_gpio[] __initdata = { ++ { ++ .name = "om2p:blue:power", ++ .gpio = OM2Pv4_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "om2p:red:wifi", ++ .gpio = OM2Pv4_GPIO_LED_RED, ++ .active_low = 1, ++ }, { ++ .name = "om2p:yellow:wifi", ++ .gpio = OM2Pv4_GPIO_LED_YELLOW, ++ .active_low = 1, ++ }, { ++ .name = "om2p:green:wifi", ++ .gpio = OM2Pv4_GPIO_LED_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "om2p:blue:lan", ++ .gpio = OM2Pv4_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "om2p:blue:wan", ++ .gpio = OM2Pv4_GPIO_LED_WAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button om2pv4_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = OM2P_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = OM2Pv4_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init om2pv4_setup(void) ++{ ++ u8 *mac1 = (u8 *)KSEG1ADDR(0x1ffc0000); ++ u8 *mac2 = (u8 *)KSEG1ADDR(0x1ffc0000 + ETH_ALEN); ++ u8 *art = (u8 *)KSEG1ADDR(0x1ffc0000); ++ u8 wmac[6]; ++ ++ ath79_register_m25p80(&om2pv4_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(om2pv4_leds_gpio), ++ om2pv4_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, OM2P_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(om2pv4_gpio_keys), ++ om2pv4_gpio_keys); ++ ++ ath79_init_mac(wmac, art, 0x02); ++ ath79_register_wmac(art + OM2P_WMAC_CALDATA_OFFSET, wmac); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); ++ ath79_register_eth(0); ++ ++ /* WAN */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OM2Pv4, "OM2Pv4", "OpenMesh OM2Pv4", om2pv4_setup); ++MIPS_MACHINE(ATH79_MACH_OM2P_HSv4, "OM2P-HSv4", "OpenMesh OM2P HSv4", om2pv4_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-om5p.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5p.c +new file mode 100644 +index 0000000000..61ff6a755d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5p.c +@@ -0,0 +1,218 @@ ++/* ++ * OpenMesh OM5P support ++ * ++ * Copyright (C) 2013 Marek Lindner ++ * Copyright (C) 2014 Sven Eckelmann ++ * ++ * 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 ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define OM5P_GPIO_LED_POWER 13 ++#define OM5P_GPIO_LED_GREEN 16 ++#define OM5P_GPIO_LED_RED 19 ++#define OM5P_GPIO_LED_YELLOW 17 ++#define OM5P_GPIO_LED_LAN 14 ++#define OM5P_GPIO_LED_WAN 15 ++#define OM5P_GPIO_BTN_RESET 4 ++#define OM5P_GPIO_I2C_SCL 20 ++#define OM5P_GPIO_I2C_SDA 21 ++ ++#define OM5P_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define OM5P_KEYS_DEBOUNCE_INTERVAL (3 * OM5P_KEYS_POLL_INTERVAL) ++ ++#define OM5P_WMAC_CALDATA_OFFSET 0x1000 ++#define OM5P_PCI_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led om5p_leds_gpio[] __initdata = { ++ { ++ .name = "om5p:blue:power", ++ .gpio = OM5P_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "om5p:red:wifi", ++ .gpio = OM5P_GPIO_LED_RED, ++ .active_low = 1, ++ }, { ++ .name = "om5p:yellow:wifi", ++ .gpio = OM5P_GPIO_LED_YELLOW, ++ .active_low = 1, ++ }, { ++ .name = "om5p:green:wifi", ++ .gpio = OM5P_GPIO_LED_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "om5p:blue:lan", ++ .gpio = OM5P_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "om5p:blue:wan", ++ .gpio = OM5P_GPIO_LED_WAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button om5p_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = OM5P_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = OM5P_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct flash_platform_data om5p_flash_data = { ++ .type = "mx25l12805d", ++}; ++ ++static void __init om5p_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ /* make lan / wan leds software controllable */ ++ ath79_gpio_output_select(OM5P_GPIO_LED_LAN, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(OM5P_GPIO_LED_WAN, AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_m25p80(&om5p_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(om5p_leds_gpio), ++ om5p_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, OM5P_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(om5p_gpio_keys), ++ om5p_gpio_keys); ++ ++ ath79_init_mac(mac, art, 2); ++ ath79_register_wmac(art + OM5P_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art, 1); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OM5P, "OM5P", "OpenMesh OM5P", om5p_setup); ++ ++static struct i2c_gpio_platform_data om5pan_i2c_device_platdata = { ++ .sda_pin = OM5P_GPIO_I2C_SDA, ++ .scl_pin = OM5P_GPIO_I2C_SCL, ++ .udelay = 10, ++ .sda_is_open_drain = 1, ++ .scl_is_open_drain = 1, ++}; ++ ++static struct platform_device om5pan_i2c_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &om5pan_i2c_device_platdata, ++ }, ++}; ++ ++static struct i2c_board_info om5pan_i2c_devs[] __initdata = { ++ { ++ I2C_BOARD_INFO("tmp423", 0x4c), ++ }, ++}; ++ ++static struct at803x_platform_data om5p_an_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info om5p_an_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 7, ++ .platform_data = &om5p_an_at803x_data, ++ }, ++}; ++ ++static void __init om5p_an_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ /* temperature sensor */ ++ platform_device_register(&om5pan_i2c_device); ++ i2c_register_board_info(0, om5pan_i2c_devs, ++ ARRAY_SIZE(om5pan_i2c_devs)); ++ ++ /* make lan / wan leds software controllable */ ++ ath79_gpio_output_select(OM5P_GPIO_LED_LAN, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(OM5P_GPIO_LED_WAN, AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_m25p80(&om5p_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(om5p_leds_gpio), ++ om5p_leds_gpio); ++ ++ ath79_init_mac(mac, art, 0x02); ++ ath79_register_wmac(art + OM5P_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ath79_setup_ar934x_eth_rx_delay(2, 2); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ mdiobus_register_board_info(om5p_an_mdio0_info, ++ ARRAY_SIZE(om5p_an_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0x00); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art, 0x01); ++ ++ /* GMAC0 is connected to the PHY7 */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(7); ++ ath79_eth0_pll_data.pll_1000 = 0x02000000; ++ ath79_eth0_pll_data.pll_100 = 0x00000101; ++ ath79_eth0_pll_data.pll_10 = 0x00001313; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(1); ++ ++ ath79_init_mac(mac, art, 0x10); ++ ap91_pci_init(art + OM5P_PCI_CALDATA_OFFSET, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OM5P_AN, "OM5P-AN", "OpenMesh OM5P AN", om5p_an_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pac.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pac.c +new file mode 100644 +index 0000000000..10771ea7b1 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pac.c +@@ -0,0 +1,193 @@ ++/* ++ * OpenMesh OM5P-AC support ++ * ++ * Copyright (C) 2013 Marek Lindner ++ * Copyright (C) 2014 Sven Eckelmann ++ * ++ * 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 ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define OM5PAC_GPIO_LED_POWER 18 ++#define OM5PAC_GPIO_LED_GREEN 21 ++#define OM5PAC_GPIO_LED_RED 23 ++#define OM5PAC_GPIO_LED_YELLOW 22 ++#define OM5PAC_GPIO_LED_LAN 20 ++#define OM5PAC_GPIO_LED_WAN 19 ++#define OM5PAC_GPIO_I2C_SCL 12 ++#define OM5PAC_GPIO_I2C_SDA 11 ++ ++#define OM5PAC_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define OM5PAC_KEYS_DEBOUNCE_INTERVAL (3 * OM5PAC_KEYS_POLL_INTERVAL) ++ ++#define OM5PAC_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led om5pac_leds_gpio[] __initdata = { ++ { ++ .name = "om5pac:blue:power", ++ .gpio = OM5PAC_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "om5pac:red:wifi", ++ .gpio = OM5PAC_GPIO_LED_RED, ++ .active_low = 1, ++ }, { ++ .name = "om5pac:yellow:wifi", ++ .gpio = OM5PAC_GPIO_LED_YELLOW, ++ .active_low = 1, ++ }, { ++ .name = "om5pac:green:wifi", ++ .gpio = OM5PAC_GPIO_LED_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "om5pac:blue:lan", ++ .gpio = OM5PAC_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "om5pac:blue:wan", ++ .gpio = OM5PAC_GPIO_LED_WAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct flash_platform_data om5pac_flash_data = { ++ .type = "mx25l12805d", ++}; ++ ++static struct i2c_gpio_platform_data om5pac_i2c_device_platdata = { ++ .sda_pin = OM5PAC_GPIO_I2C_SDA, ++ .scl_pin = OM5PAC_GPIO_I2C_SCL, ++ .udelay = 10, ++ .sda_is_open_drain = 1, ++ .scl_is_open_drain = 1, ++}; ++ ++static struct platform_device om5pac_i2c_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &om5pac_i2c_device_platdata, ++ }, ++}; ++ ++static struct i2c_board_info om5pac_i2c_devs[] __initdata = { ++ { ++ I2C_BOARD_INFO("tmp423", 0x4c), ++ }, ++}; ++ ++static struct at803x_platform_data om5pac_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info om5pac_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 1, ++ .platform_data = &om5pac_at803x_data, ++ }, ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 2, ++ .platform_data = &om5pac_at803x_data, ++ }, ++}; ++ ++static void __init om5p_ac_setup_qca955x_eth_cfg(u32 mask, ++ unsigned int rxd, ++ unsigned int rxdv, ++ unsigned int txd, ++ unsigned int txe) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ ++ t = mask; ++ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; ++ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; ++ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; ++ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; ++ ++ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++static void __init om5p_ac_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ /* temperature sensor */ ++ platform_device_register(&om5pac_i2c_device); ++ i2c_register_board_info(0, om5pac_i2c_devs, ++ ARRAY_SIZE(om5pac_i2c_devs)); ++ ++ ath79_gpio_output_select(OM5PAC_GPIO_LED_WAN, QCA955X_GPIO_OUT_GPIO); ++ ++ ath79_register_m25p80(&om5pac_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(om5pac_leds_gpio), ++ om5pac_leds_gpio); ++ ++ ath79_init_mac(mac, art, 0x02); ++ ath79_register_wmac(art + OM5PAC_WMAC_CALDATA_OFFSET, mac); ++ ++ om5p_ac_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 3, 3, 0, 0); ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(om5pac_mdio0_info, ++ ARRAY_SIZE(om5pac_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0x00); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art, 0x01); ++ ++ /* GMAC0 is connected to the PHY1 */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(1); ++ ath79_eth0_pll_data.pll_1000 = 0x82000101; ++ ath79_eth0_pll_data.pll_100 = 0x80000101; ++ ath79_eth0_pll_data.pll_10 = 0x80001313; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to MDIO1 in SGMII mode */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth1_data.phy_mask = BIT(2); ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ath79_eth1_pll_data.pll_100 = 0x80000101; ++ ath79_eth1_pll_data.pll_10 = 0x80001313; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OM5P_AC, "OM5P-AC", "OpenMesh OM5P AC", om5p_ac_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pacv2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pacv2.c +new file mode 100644 +index 0000000000..f72700138f +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pacv2.c +@@ -0,0 +1,215 @@ ++/* ++ * OpenMesh OM5P-ACv2 support ++ * ++ * Copyright (C) 2013 Marek Lindner ++ * Copyright (C) 2014-2016 Sven Eckelmann ++ * Copyright (C) 2015 Open-Mesh - Jim Collar ++ * ++ * 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 ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define OM5PACV2_GPIO_LED_POWER 14 ++#define OM5PACV2_GPIO_LED_GREEN 13 ++#define OM5PACV2_GPIO_LED_RED 23 ++#define OM5PACV2_GPIO_LED_YELLOW 15 ++#define OM5PACV2_GPIO_BTN_RESET 1 ++#define OM5PACV2_GPIO_I2C_SCL 18 ++#define OM5PACV2_GPIO_I2C_SDA 19 ++#define OM5PACV2_GPIO_PA_DCDC 2 ++#define OM5PACV2_GPIO_PA_HIGH 16 ++ ++#define OM5PACV2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define OM5PACV2_KEYS_DEBOUNCE_INTERVAL (3 * OM5PACV2_KEYS_POLL_INTERVAL) ++ ++#define OM5PACV2_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led om5pacv2_leds_gpio[] __initdata = { ++ { ++ .name = "om5pac:blue:power", ++ .gpio = OM5PACV2_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "om5pac:red:wifi", ++ .gpio = OM5PACV2_GPIO_LED_RED, ++ .active_low = 1, ++ }, { ++ .name = "om5pac:yellow:wifi", ++ .gpio = OM5PACV2_GPIO_LED_YELLOW, ++ .active_low = 1, ++ }, { ++ .name = "om5pac:green:wifi", ++ .gpio = OM5PACV2_GPIO_LED_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button om5pacv2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = OM5PACV2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = OM5PACV2_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct i2c_gpio_platform_data om5pacv2_i2c_device_platdata = { ++ .sda_pin = OM5PACV2_GPIO_I2C_SDA, ++ .scl_pin = OM5PACV2_GPIO_I2C_SCL, ++ .udelay = 10, ++ .sda_is_open_drain = 1, ++ .scl_is_open_drain = 1, ++}; ++ ++static struct platform_device om5pacv2_i2c_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &om5pacv2_i2c_device_platdata, ++ }, ++}; ++ ++static struct i2c_board_info om5pacv2_i2c_devs[] __initdata = { ++ { ++ I2C_BOARD_INFO("tmp423", 0x4e), ++ }, ++}; ++ ++static struct flash_platform_data om5pacv2_flash_data = { ++ .type = "mx25l12805d", ++}; ++ ++static struct at803x_platform_data om5pacv2_an_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 1, ++}; ++ ++static struct at803x_platform_data om5pacv2_an_at8031_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info om5pacv2_an_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 4, ++ .platform_data = &om5pacv2_an_at803x_data, ++ }, ++ { ++ .bus_id = "ag71xx-mdio.1", ++ .mdio_addr = 1, ++ .platform_data = &om5pacv2_an_at8031_data, ++ }, ++}; ++ ++static void __init om5p_acv2_setup_qca955x_eth_cfg(u32 mask, ++ unsigned int rxd, ++ unsigned int rxdv, ++ unsigned int txd, ++ unsigned int txe) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ ++ t = mask; ++ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; ++ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; ++ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; ++ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; ++ ++ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); ++ ++ iounmap(base); ++} ++ ++static void __init om5p_acv2_setup(void) ++{ ++ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ ++ /* power amplifier high power, 4.2V at RFFM4203/4503 instead of 3.3 */ ++ ath79_gpio_function_enable(QCA955X_GPIO_FUNC_JTAG_DISABLE); ++ ath79_gpio_output_select(OM5PACV2_GPIO_PA_DCDC, QCA955X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(OM5PACV2_GPIO_PA_HIGH, QCA955X_GPIO_OUT_GPIO); ++ gpio_request_one(OM5PACV2_GPIO_PA_DCDC, GPIOF_OUT_INIT_HIGH, ++ "PA DC/DC"); ++ gpio_request_one(OM5PACV2_GPIO_PA_HIGH, GPIOF_OUT_INIT_HIGH, "PA HIGH"); ++ ++ /* temperature sensor */ ++ platform_device_register(&om5pacv2_i2c_device); ++ i2c_register_board_info(0, om5pacv2_i2c_devs, ++ ARRAY_SIZE(om5pacv2_i2c_devs)); ++ ++ ath79_register_m25p80(&om5pacv2_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(om5pacv2_leds_gpio), ++ om5pacv2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, OM5PACV2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(om5pacv2_gpio_keys), ++ om5pacv2_gpio_keys); ++ ++ ath79_init_mac(mac, art, 0x02); ++ ath79_register_wmac(art + OM5PACV2_WMAC_CALDATA_OFFSET, mac); ++ ++ om5p_acv2_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 2, 2, 0, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ mdiobus_register_board_info(om5pacv2_an_mdio0_info, ++ ARRAY_SIZE(om5pacv2_an_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0x00); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art, 0x01); ++ ++ /* GMAC0 is connected to the PHY4 */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_pll_data.pll_1000 = 0x82000101; ++ ath79_eth0_pll_data.pll_100 = 0x80000101; ++ ath79_eth0_pll_data.pll_10 = 0x80001313; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to MDIO1 in SGMII mode */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_eth1_data.phy_mask = BIT(1); ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ath79_eth1_pll_data.pll_100 = 0x80000101; ++ ath79_eth1_pll_data.pll_10 = 0x80001313; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OM5P_ACv2, "OM5P-ACv2", "OpenMesh OM5P ACv2", om5p_acv2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-omy-g1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-omy-g1.c +new file mode 100644 +index 0000000000..25ca27cba8 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-omy-g1.c +@@ -0,0 +1,123 @@ ++/* ++ * OMYlink OMY-G1 board support ++ * ++ * Copyright (C) 2016 L. D. Pinney ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define OMY_G1_GPIO_LED_WLAN 13 ++#define OMY_G1_GPIO_LED_WAN 18 ++#define OMY_G1_GPIO_LED_LAN 19 ++ ++#define OMY_G1_GPIO_USB_POWER 4 ++ ++#define OMY_G1_GPIO_BTN_RESET 17 ++ ++#define OMY_G1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define OMY_G1_KEYS_DEBOUNCE_INTERVAL (3 * OMY_G1_KEYS_POLL_INTERVAL) ++ ++static const char *omy_g1_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data omy_g1_flash_data = { ++ .part_probes = omy_g1_part_probes, ++}; ++ ++static struct gpio_led omy_g1_leds_gpio[] __initdata = { ++ { ++ .name = "omy:green:wlan", ++ .gpio = OMY_G1_GPIO_LED_WLAN, ++ .active_low = 1, ++ },{ ++ .name = "omy:green:wan", ++ .gpio = OMY_G1_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "omy:green:lan", ++ .gpio = OMY_G1_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button omy_g1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = OMY_G1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = OMY_G1_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init omy_g1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, ++ AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ ath79_register_m25p80(&omy_g1_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(omy_g1_leds_gpio), ++ omy_g1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, OMY_G1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(omy_g1_gpio_keys), ++ omy_g1_gpio_keys); ++ ++ ath79_gpio_output_select(OMY_G1_GPIO_USB_POWER, ++ AR934X_GPIO_OUT_GPIO); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++ ++ ath79_gpio_output_select(OMY_G1_GPIO_USB_POWER, ++ AR934X_GPIO_OUT_GPIO); ++ ++ gpio_request_one(OMY_G1_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_OMY_G1, "OMY-G1", "OMYlink OMY-G1", ++ omy_g1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-omy-x1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-omy-x1.c +new file mode 100644 +index 0000000000..c99e3d7457 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-omy-x1.c +@@ -0,0 +1,106 @@ ++/* ++ * OMYlink OMY-X1 board support ++ * ++ * Copyright (C) 2016 L. D. Pinney ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++ ++#define OMY_X1_GPIO_LED_POWER 19 ++#define OMY_X1_GPIO_LED_WAN 22 ++ ++#define OMY_X1_GPIO_BTN_RESET 17 ++ ++#define OMY_X1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define OMY_X1_KEYS_DEBOUNCE_INTERVAL (3 * OMY_X1_KEYS_POLL_INTERVAL) ++ ++static const char *omy_x1_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data omy_x1_flash_data = { ++ .part_probes = omy_x1_part_probes, ++}; ++ ++static struct gpio_led omy_x1_leds_gpio[] __initdata = { ++ { ++ .name = "omy:green:wan", ++ .gpio = OMY_X1_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "omy:green:power", ++ .gpio = OMY_X1_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button omy_x1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = OMY_X1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = OMY_X1_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init omy_x1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, ++ AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ ath79_register_m25p80(&omy_x1_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(omy_x1_leds_gpio), ++ omy_x1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, OMY_X1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(omy_x1_gpio_keys), ++ omy_x1_gpio_keys); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++ ++} ++ ++MIPS_MACHINE(ATH79_MACH_OMY_X1, "OMY-X1", "OMYlink OMY-X1", ++ omy_x1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-onion-omega.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-onion-omega.c +new file mode 100644 +index 0000000000..c739840377 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-onion-omega.c +@@ -0,0 +1,84 @@ ++/* ++ * Onion Omega board support ++ * ++ * Copyright (C) 2015 Boken Lin ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define OMEGA_GPIO_LED_SYSTEM 27 ++#define OMEGA_GPIO_BTN_RESET 11 ++ ++#define OMEGA_GPIO_USB_POWER 8 ++ ++#define OMEGA_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define OMEGA_KEYS_DEBOUNCE_INTERVAL (3 * OMEGA_KEYS_POLL_INTERVAL) ++ ++static const char *omega_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data omega_flash_data = { ++ .part_probes = omega_part_probes, ++}; ++ ++static struct gpio_led omega_leds_gpio[] __initdata = { ++ { ++ .name = "onion:amber:system", ++ .gpio = OMEGA_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button omega_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = OMEGA_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = OMEGA_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static void __init onion_omega_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&omega_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(omega_leds_gpio), ++ omega_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, OMEGA_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(omega_gpio_keys), ++ omega_gpio_keys); ++ ++ gpio_request_one(OMEGA_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ONION_OMEGA, "ONION-OMEGA", "Onion Omega", onion_omega_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-pb42.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-pb42.c +new file mode 100644 +index 0000000000..3a350e90a1 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-pb42.c +@@ -0,0 +1,83 @@ ++/* ++ * Atheros PB42 board support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define PB42_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define PB42_KEYS_DEBOUNCE_INTERVAL (3 * PB42_KEYS_POLL_INTERVAL) ++ ++#define PB42_GPIO_BTN_SW4 8 ++#define PB42_GPIO_BTN_SW5 3 ++ ++static struct gpio_keys_button pb42_gpio_keys[] __initdata = { ++ { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = PB42_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PB42_GPIO_BTN_SW4, ++ .active_low = 1, ++ }, { ++ .desc = "sw5", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = PB42_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PB42_GPIO_BTN_SW5, ++ .active_low = 1, ++ } ++}; ++ ++static const char *pb42_part_probes[] = { ++ "RedBoot", ++ NULL, ++}; ++ ++static struct flash_platform_data pb42_flash_data = { ++ .part_probes = pb42_part_probes, ++}; ++ ++#define PB42_WAN_PHYMASK BIT(20) ++#define PB42_LAN_PHYMASK (BIT(16) | BIT(17) | BIT(18) | BIT(19)) ++#define PB42_MDIO_PHYMASK (PB42_LAN_PHYMASK | PB42_WAN_PHYMASK) ++ ++static void __init pb42_init(void) ++{ ++ ath79_register_m25p80(&pb42_flash_data); ++ ++ ath79_register_mdio(0, ~PB42_MDIO_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = PB42_WAN_PHYMASK; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.speed = SPEED_100; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_gpio_keys_polled(-1, PB42_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(pb42_gpio_keys), ++ pb42_gpio_keys); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_PB42, "PB42", "Atheros PB42", pb42_init); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-pqi-air-pen.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-pqi-air-pen.c +new file mode 100644 +index 0000000000..56769bfb61 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-pqi-air-pen.c +@@ -0,0 +1,99 @@ ++/* ++ * PQI Air Pen stick support ++ * ++ * Copyright (C) 2016 YuheiOKAWA ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define PQI_AIR_PEN_GPIO_LED_WLAN 0 ++#define PQI_AIR_PEN_GPIO_LED_WPS 23 ++ ++#define PQI_AIR_PEN_GPIO_BTN_WPS 22 ++#define PQI_AIR_PEN_GPIO_BTN_RESET 12 ++ ++#define PQI_AIR_PEN_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define PQI_AIR_PEN_KEYS_DEBOUNCE_INTERVAL (3 * PQI_AIR_PEN_KEYS_POLL_INTERVAL) ++ ++#define PQI_AIR_PEN_WMAC_CALDATA_OFFSET 0x1000 ++#define PQI_AIR_PEN_LAN_MAC_OFFSET 0x1002 ++#define PQI_AIR_PEN_WMAC_MAC_OFFSET 0x1002 ++ ++static struct gpio_led pqi_air_pen_leds_gpio[] __initdata = { ++ { ++ .name = "pqi-air-pen:blue:wlan", ++ .gpio = PQI_AIR_PEN_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "pqi-air-pen:blue:wps", ++ .gpio = PQI_AIR_PEN_GPIO_LED_WPS, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button pqi_air_pen_gpio_keys[] __initdata = { ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = PQI_AIR_PEN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PQI_AIR_PEN_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = PQI_AIR_PEN_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PQI_AIR_PEN_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init pqi_air_pen_setup(void) ++{ ++ /* ART base address */ ++ u8 *art = (u8 *) KSEG1ADDR(0x9f050000); ++ ++ /* register flash. */ ++ ath79_register_m25p80(NULL); ++ ++ /* register wireless mac with cal data */ ++ ath79_register_wmac(art + PQI_AIR_PEN_WMAC_CALDATA_OFFSET, art + PQI_AIR_PEN_WMAC_MAC_OFFSET); ++ ++ /* false PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ /* register gpio LEDs and keys */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(pqi_air_pen_leds_gpio), ++ pqi_air_pen_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, PQI_AIR_PEN_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(pqi_air_pen_gpio_keys), ++ pqi_air_pen_gpio_keys); ++ ++ /* enable usb */ ++ ath79_register_usb(); ++ ++ /* register eth0 as LAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + PQI_AIR_PEN_LAN_MAC_OFFSET, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_PQI_AIR_PEN, "PQI-AIR-PEN", "PQI Air Pen",pqi_air_pen_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-qihoo-c301.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-qihoo-c301.c +new file mode 100644 +index 0000000000..a682f35e2c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-qihoo-c301.c +@@ -0,0 +1,166 @@ ++/* ++ * Qihoo 360 C301 board support ++ * ++ * Copyright (C) 2013 Gabor Juhos ++ * Copyright (C) 2014 Weijie Gao ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define QIHOO_C301_GPIO_LED_STATUS_GREEN 0 ++#define QIHOO_C301_GPIO_LED_STATUS_RED 11 ++ ++#define QIHOO_C301_GPIO_LED_WAN 1 ++#define QIHOO_C301_GPIO_LED_LAN1 2 ++#define QIHOO_C301_GPIO_LED_LAN2 3 ++#define QIHOO_C301_GPIO_ETH_LEN_EN 18 ++ ++#define QIHOO_C301_GPIO_BTN_RESET 16 ++ ++#define QIHOO_C301_GPIO_USB_POWER 19 ++ ++#define QIHOO_C301_GPIO_SPI_CS1 12 ++ ++#define QIHOO_C301_GPIO_EXTERNAL_LNA0 14 ++#define QIHOO_C301_GPIO_EXTERNAL_LNA1 15 ++ ++#define QIHOO_C301_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define QIHOO_C301_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * QIHOO_C301_KEYS_POLL_INTERVAL) ++ ++#define QIHOO_C301_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define QIHOO_C301_NVRAM_ADDR 0x1f058010 ++#define QIHOO_C301_NVRAM_SIZE 0x7ff0 ++ ++static struct gpio_led qihoo_c301_leds_gpio[] __initdata = { ++ { ++ .name = "qihoo:green:status", ++ .gpio = QIHOO_C301_GPIO_LED_STATUS_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "qihoo:red:status", ++ .gpio = QIHOO_C301_GPIO_LED_STATUS_RED, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button qihoo_c301_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = QIHOO_C301_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = QIHOO_C301_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct flash_platform_data flash __initdata = {NULL, NULL, 0}; ++ ++static void qihoo_c301_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(QIHOO_C301_NVRAM_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, QIHOO_C301_NVRAM_SIZE, ++ name, mac); ++ if (err) ++ pr_err("no MAC address found for %s\n", name); ++} ++ ++static void __init qihoo_c301_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80_multi(&flash); ++ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_gpio_output_select(QIHOO_C301_GPIO_LED_WAN, ++ AR934X_GPIO_OUT_LED_LINK4); ++ ath79_gpio_output_select(QIHOO_C301_GPIO_LED_LAN1, ++ AR934X_GPIO_OUT_LED_LINK1); ++ ath79_gpio_output_select(QIHOO_C301_GPIO_LED_LAN2, ++ AR934X_GPIO_OUT_LED_LINK2); ++ ++ ath79_gpio_output_select(QIHOO_C301_GPIO_SPI_CS1, ++ AR934X_GPIO_OUT_SPI_CS1); ++ ++ gpio_request_one(QIHOO_C301_GPIO_ETH_LEN_EN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "Ethernet LED enable"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(qihoo_c301_leds_gpio), ++ qihoo_c301_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, QIHOO_C301_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(qihoo_c301_gpio_keys), ++ qihoo_c301_gpio_keys); ++ ++ ath79_wmac_set_ext_lna_gpio(0, QIHOO_C301_GPIO_EXTERNAL_LNA0); ++ ath79_wmac_set_ext_lna_gpio(1, QIHOO_C301_GPIO_EXTERNAL_LNA1); ++ ++ qihoo_c301_get_mac("wlan24mac=", tmpmac); ++ ath79_register_wmac(art + QIHOO_C301_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_register_pci(); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE | ++ AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* LAN */ ++ qihoo_c301_get_mac("lanmac=", ath79_eth1_data.mac_addr); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ qihoo_c301_get_mac("wanmac=", ath79_eth0_data.mac_addr); ++ ++ /* GMAC0 is connected to the PHY4 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ ath79_register_eth(0); ++ ++ gpio_request_one(QIHOO_C301_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_QIHOO_C301, "QIHOO-C301", "Qihoo 360 C301", ++ qihoo_c301_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-r36a.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-r36a.c +new file mode 100644 +index 0000000000..b3493e2c42 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-r36a.c +@@ -0,0 +1,140 @@ ++/* ++ * ALFA Network R36A board support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define R36A_GPIO_LED_LAN 4 ++#define R36A_GPIO_LED_STATUS 14 ++#define R36A_GPIO_LED_USB 12 ++#define R36A_GPIO_LED_WAN 16 ++#define R36A_GPIO_LED_WLAN 15 ++ ++#define R36A_GPIO_WDT_EN 1 ++#define R36A_GPIO_WDT_IN 0 ++#define R36A_GPIO_USB_PWR 3 ++ ++#define R36A_GPIO_BTN_RESET 2 ++#define R36A_GPIO_BTN_RFKILL 17 ++ ++#define R36A_KEYS_POLL_INTERVAL 20 ++#define R36A_KEYS_DEBOUNCE_INTERVAL (3 * R36A_KEYS_POLL_INTERVAL) ++ ++#define R36A_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led r36a_leds_gpio[] __initdata = { ++ { ++ .name = "r36a:blue:lan", ++ .gpio = R36A_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "r36a:blue:status", ++ .gpio = R36A_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "r36a:blue:usb", ++ .gpio = R36A_GPIO_LED_USB, ++ .active_low = 1, ++ }, { ++ .name = "r36a:blue:wan", ++ .gpio = R36A_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "r36a:blue:wlan", ++ .gpio = R36A_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button r36a_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = R36A_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = R36A_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "rfkill", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = R36A_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = R36A_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init r36a_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f070000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = 0xf7; ++ ++ /* LAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0); ++ ath79_register_eth(0); ++ ++ /* WAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, art, 1); ++ ath79_register_eth(1); ++ ++ /* Disable JTAG (enables GPIO0-3) */ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(r36a_leds_gpio), ++ r36a_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, R36A_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(r36a_gpio_keys), ++ r36a_gpio_keys); ++ ++ gpio_request_one(R36A_GPIO_WDT_IN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "WDT input"); ++ ++ gpio_request_one(R36A_GPIO_WDT_EN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "WDT enable"); ++ ++ gpio_request_one(R36A_GPIO_USB_PWR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ ath79_register_wmac(art + R36A_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_R36A, "R36A", "ALFA Network R36A", r36a_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-r602n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-r602n.c +new file mode 100644 +index 0000000000..4aef0a932a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-r602n.c +@@ -0,0 +1,213 @@ ++/* ++ * P&W (Shenzhen Progress&Win Technologies) R602N and CPE505N boards support ++ * ++ * Copyright (C) 2017 Piotr Dymacz ++ * ++ * Based on mach-zbt-we1526.c ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define PW_GPIO_BTN_RESET 17 ++ ++#define PW_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define PW_KEYS_DEBOUNCE_INTERVAL (3 * PW_KEYS_POLL_INTERVAL) ++ ++#define PW_MAC0_OFFSET 0x0 ++#define PW_MAC1_OFFSET 0x6 ++#define PW_WMAC_CALDATA_OFFSET 0x1000 ++ ++/* CPE505N GPIO LEDs */ ++#define CPE505N_GPIO_LED_DIAG 12 ++#define CPE505N_GPIO_LED_LAN 11 ++#define CPE505N_GPIO_LED_STATUS 14 ++#define CPE505N_GPIO_LED_WAN 4 ++#define CPE505N_GPIO_LED_WLAN 15 ++ ++static struct gpio_led cpe505n_leds_gpio[] __initdata = { ++ { ++ .name = "cpe505n:red:diag", ++ .gpio = CPE505N_GPIO_LED_DIAG, ++ .active_low = 1, ++ }, { ++ .name = "cpe505n:green:lan", ++ .gpio = CPE505N_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "cpe505n:green:status", ++ .gpio = CPE505N_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "cpe505n:green:wan", ++ .gpio = CPE505N_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "cpe505n:blue:wlan", ++ .gpio = CPE505N_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init cpe505n_gpio_setup(void) ++{ ++ /* For LED on GPIO4 */ ++ ath79_gpio_function_disable(AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ath79_gpio_output_select(CPE505N_GPIO_LED_WAN, 0); ++ ++ ath79_gpio_direction_select(CPE505N_GPIO_LED_DIAG, true); ++ ath79_gpio_direction_select(CPE505N_GPIO_LED_LAN, true); ++ ath79_gpio_direction_select(CPE505N_GPIO_LED_STATUS, true); ++ ath79_gpio_direction_select(CPE505N_GPIO_LED_WAN, true); ++ ath79_gpio_direction_select(CPE505N_GPIO_LED_WLAN, true); ++ ++ /* Mute LEDs */ ++ gpio_set_value(CPE505N_GPIO_LED_DIAG, 1); ++ gpio_set_value(CPE505N_GPIO_LED_LAN, 1); ++ gpio_set_value(CPE505N_GPIO_LED_STATUS, 1); ++ gpio_set_value(CPE505N_GPIO_LED_WAN, 1); ++ gpio_set_value(CPE505N_GPIO_LED_WLAN, 1); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe505n_leds_gpio), ++ cpe505n_leds_gpio); ++} ++ ++/* R602N GPIO LEDs */ ++#define R602N_GPIO_LED_LAN1 16 ++#define R602N_GPIO_LED_LAN2 15 ++#define R602N_GPIO_LED_LAN3 14 ++#define R602N_GPIO_LED_LAN4 11 ++#define R602N_GPIO_LED_WAN 4 ++#define R602N_GPIO_LED_WLAN 12 ++ ++static struct gpio_led r602n_leds_gpio[] __initdata = { ++ { ++ .name = "r602n:green:lan1", ++ .gpio = R602N_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "r602n:green:lan2", ++ .gpio = R602N_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "r602n:green:lan3", ++ .gpio = R602N_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "r602n:green:lan4", ++ .gpio = R602N_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "r602n:green:wan", ++ .gpio = R602N_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "r602n:green:wlan", ++ .gpio = R602N_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init r602n_gpio_setup(void) ++{ ++ /* For LED on GPIO4 */ ++ ath79_gpio_function_disable(AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ath79_gpio_output_select(R602N_GPIO_LED_WAN, 0); ++ ++ ath79_gpio_direction_select(R602N_GPIO_LED_LAN1, true); ++ ath79_gpio_direction_select(R602N_GPIO_LED_LAN2, true); ++ ath79_gpio_direction_select(R602N_GPIO_LED_LAN3, true); ++ ath79_gpio_direction_select(R602N_GPIO_LED_LAN4, true); ++ ath79_gpio_direction_select(R602N_GPIO_LED_WAN, true); ++ ath79_gpio_direction_select(R602N_GPIO_LED_WLAN, true); ++ ++ /* Mute LEDs */ ++ gpio_set_value(R602N_GPIO_LED_LAN1, 1); ++ gpio_set_value(R602N_GPIO_LED_LAN2, 1); ++ gpio_set_value(R602N_GPIO_LED_LAN3, 1); ++ gpio_set_value(R602N_GPIO_LED_LAN4, 1); ++ gpio_set_value(R602N_GPIO_LED_WAN, 1); ++ gpio_set_value(R602N_GPIO_LED_WLAN, 1); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(r602n_leds_gpio), ++ r602n_leds_gpio); ++} ++ ++static struct gpio_keys_button pw_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = PW_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = PW_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init r602n_cpe505n_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + PW_MAC1_OFFSET, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + PW_MAC0_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art + PW_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_gpio_keys_polled(-1, PW_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(pw_gpio_keys), ++ pw_gpio_keys); ++} ++ ++static void __init cpe505n_setup(void) ++{ ++ r602n_cpe505n_setup(); ++ ++ cpe505n_gpio_setup(); ++} ++ ++static void __init r602n_setup(void) ++{ ++ r602n_cpe505n_setup(); ++ ++ r602n_gpio_setup(); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_CPE505N, "CPE505N", "P&W CPE505N", cpe505n_setup); ++MIPS_MACHINE(ATH79_MACH_R602N, "R602N", "P&W R602N", r602n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-r6100.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-r6100.c +new file mode 100644 +index 0000000000..c1f0e2c400 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-r6100.c +@@ -0,0 +1,146 @@ ++/* ++ * NETGEAR R6100 board support ++ * ++ * Copyright (C) 2014 Gabor Juhos ++ * Copyright (C) 2014 Imre Kaloz ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define R6100_GPIO_LED_WLAN 0 ++#define R6100_GPIO_LED_USB 11 ++#define R6100_GPIO_LED_WAN_GREEN 13 ++#define R6100_GPIO_LED_POWER_AMBER 14 ++#define R6100_GPIO_LED_WAN_AMBER 15 ++#define R6100_GPIO_LED_POWER_GREEN 17 ++ ++#define R6100_GPIO_BTN_WIRELESS 1 ++#define R6100_GPIO_BTN_WPS 3 ++#define R6100_GPIO_BTN_RESET 12 ++ ++#define R6100_GPIO_USB_POWER 16 ++ ++#define R6100_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define R6100_KEYS_DEBOUNCE_INTERVAL (3 * R6100_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led r6100_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:green:power", ++ .gpio = R6100_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:power", ++ .gpio = R6100_GPIO_LED_POWER_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:wan", ++ .gpio = R6100_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:wan", ++ .gpio = R6100_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:blue:usb", ++ .gpio = R6100_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:blue:wlan", ++ .gpio = R6100_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button r6100_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = R6100_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = R6100_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = R6100_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = R6100_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, ++ { ++ .desc = "RFKILL switch", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = R6100_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = R6100_GPIO_BTN_WIRELESS, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init r6100_setup(void) ++{ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(r6100_leds_gpio), ++ r6100_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, R6100_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(r6100_gpio_keys), ++ r6100_gpio_keys); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ gpio_request_one(R6100_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_HW); ++ ath79_register_nfc(); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac_simple(); ++ ++ ap91_pci_init_simple(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_R6100, "R6100", "NETGEAR R6100", ++ r6100_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rambutan.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rambutan.c +new file mode 100644 +index 0000000000..1730a29f33 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rambutan.c +@@ -0,0 +1,92 @@ ++/* ++ * 8devices Rambutan board support ++ * ++ * Copyright (C) 2017 Mantas Pucka ++ * ++ * 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 ++#include ++#include ++#include ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++static struct at803x_platform_data rambutan_ar8032_data = { ++ .has_reset_gpio = 1, ++ .reset_gpio = 17, ++}; ++ ++static struct mdio_board_info rambutan_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &rambutan_ar8032_data, ++ }, ++}; ++ ++static struct at803x_platform_data rambutan_ar8033_data = { ++ .has_reset_gpio = 1, ++ .override_sgmii_aneg = 1, ++ .reset_gpio = 23, ++}; ++ ++static struct mdio_board_info rambutan_mdio1_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.1", ++ .mdio_addr = 0, ++ .platform_data = &rambutan_ar8033_data, ++ }, ++}; ++ ++static void __init rambutan_setup(void) ++{ ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_HW); ++ ath79_register_nfc(); ++ ath79_register_usb(); ++ ath79_register_pci(); ++ ath79_register_wmac_simple(); ++ ++ mdiobus_register_board_info(rambutan_mdio0_info, ++ ARRAY_SIZE(rambutan_mdio0_info)); ++ mdiobus_register_board_info(rambutan_mdio1_info, ++ ARRAY_SIZE(rambutan_mdio1_info)); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_register_eth(0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.phy_mask = BIT(0); ++ ath79_eth1_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_eth1_data.enable_sgmii_fixup = 1; ++ ath79_eth1_pll_data.pll_1000 = 0x17000000; ++ ath79_eth1_pll_data.pll_10 = 0x1313; ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RAMBUTAN, "RAMBUTAN", "8devices Rambutan board", ++ rambutan_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c +new file mode 100644 +index 0000000000..aee0fb2014 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c +@@ -0,0 +1,406 @@ ++/* ++ * MikroTik RouterBOARD 2011 support ++ * ++ * Copyright (C) 2012 Stijn Tintel ++ * Copyright (C) 2012 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. ++ */ ++ ++#define pr_fmt(fmt) "rb2011: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "routerboot.h" ++ ++#define RB2011_GPIO_NAND_NCE 14 ++#define RB2011_GPIO_SFP_LOS 21 ++ ++#define RB_ROUTERBOOT_OFFSET 0x0000 ++#define RB_ROUTERBOOT_MIN_SIZE 0xb000 ++#define RB_HARD_CFG_SIZE 0x1000 ++#define RB_BIOS_OFFSET 0xd000 ++#define RB_BIOS_SIZE 0x1000 ++#define RB_SOFT_CFG_OFFSET 0xf000 ++#define RB_SOFT_CFG_SIZE 0x1000 ++ ++#define RB_ART_SIZE 0x10000 ++ ++#define RB2011_FLAG_SFP BIT(0) ++#define RB2011_FLAG_USB BIT(1) ++#define RB2011_FLAG_WLAN BIT(2) ++ ++static struct mtd_partition rb2011_spi_partitions[] = { ++ { ++ .name = "routerboot", ++ .offset = RB_ROUTERBOOT_OFFSET, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "hard_config", ++ .size = RB_HARD_CFG_SIZE, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "bios", ++ .offset = RB_BIOS_OFFSET, ++ .size = RB_BIOS_SIZE, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "soft_config", ++ .size = RB_SOFT_CFG_SIZE, ++ } ++}; ++ ++static void __init rb2011_init_partitions(const struct rb_info *info) ++{ ++ rb2011_spi_partitions[0].size = info->hard_cfg_offs; ++ rb2011_spi_partitions[1].offset = info->hard_cfg_offs; ++ rb2011_spi_partitions[3].offset = info->soft_cfg_offs; ++} ++ ++static struct mtd_partition rb2011_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, ++ { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, ++ { ++ .name = "ubi", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static struct flash_platform_data rb2011_spi_flash_data = { ++ .parts = rb2011_spi_partitions, ++ .nr_parts = ARRAY_SIZE(rb2011_spi_partitions), ++}; ++ ++static struct ar8327_pad_cfg rb2011_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL3, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++}; ++ ++static struct ar8327_pad_cfg rb2011_ar8327_pad6_cfg; ++static struct ar8327_sgmii_cfg rb2011_ar8327_sgmii_cfg; ++ ++static struct ar8327_led_cfg rb2011_ar8327_led_cfg = { ++ .led_ctrl0 = 0xc731c731, ++ .led_ctrl1 = 0x00000000, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x0030c300, ++ .open_drain = false, ++}; ++ ++static const struct ar8327_led_info rb2011_ar8327_leds[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "rb:green:eth1"), ++ AR8327_LED_INFO(PHY1_0, HW, "rb:green:eth2"), ++ AR8327_LED_INFO(PHY2_0, HW, "rb:green:eth3"), ++ AR8327_LED_INFO(PHY3_0, HW, "rb:green:eth4"), ++ AR8327_LED_INFO(PHY4_0, HW, "rb:green:eth5"), ++ AR8327_LED_INFO(PHY0_1, SW, "rb:green:eth6"), ++ AR8327_LED_INFO(PHY1_1, SW, "rb:green:eth7"), ++ AR8327_LED_INFO(PHY2_1, SW, "rb:green:eth8"), ++ AR8327_LED_INFO(PHY3_1, SW, "rb:green:eth9"), ++ AR8327_LED_INFO(PHY4_1, SW, "rb:green:eth10"), ++ AR8327_LED_INFO(PHY4_2, SW, "rb:green:usr"), ++}; ++ ++static struct ar8327_platform_data rb2011_ar8327_data = { ++ .pad0_cfg = &rb2011_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &rb2011_ar8327_led_cfg, ++ .num_leds = ARRAY_SIZE(rb2011_ar8327_leds), ++ .leds = rb2011_ar8327_leds, ++}; ++ ++static struct mdio_board_info rb2011_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &rb2011_ar8327_data, ++ }, ++}; ++ ++static void __init rb2011_wlan_init(void) ++{ ++ char *art_buf; ++ u8 wlan_mac[ETH_ALEN]; ++ ++ art_buf = rb_get_wlan_data(); ++ if (art_buf == NULL) ++ return; ++ ++ ath79_init_mac(wlan_mac, ath79_mac_base, 11); ++ ath79_register_wmac(art_buf + 0x1000, wlan_mac); ++ ++ kfree(art_buf); ++} ++ ++static void rb2011_nand_select_chip(int chip_no) ++{ ++ switch (chip_no) { ++ case 0: ++ gpio_set_value(RB2011_GPIO_NAND_NCE, 0); ++ break; ++ default: ++ gpio_set_value(RB2011_GPIO_NAND_NCE, 1); ++ break; ++ } ++ ndelay(500); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++static struct nand_ecclayout rb2011_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++#else ++ ++static int rb2011_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 8; ++ oobregion->length = 3; ++ return 0; ++ case 1: ++ oobregion->offset = 13; ++ oobregion->length = 3; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static int rb2011_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = 4; ++ return 0; ++ case 1: ++ oobregion->offset = 4; ++ oobregion->length = 1; ++ return 0; ++ case 2: ++ oobregion->offset = 6; ++ oobregion->length = 2; ++ return 0; ++ case 3: ++ oobregion->offset = 11; ++ oobregion->length = 2; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops rb2011_nand_ecclayout_ops = { ++ .ecc = rb2011_ooblayout_ecc, ++ .free = rb2011_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static int rb2011_nand_scan_fixup(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct nand_chip *chip = mtd->priv; ++#else ++ struct nand_chip *chip = mtd_to_nand(mtd); ++#endif /* < 4.6.0 */ ++ ++ if (mtd->writesize == 512) { ++ /* ++ * Use the OLD Yaffs-1 OOB layout, otherwise RouterBoot ++ * will not be able to find the kernel that we load. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ chip->ecc.layout = &rb2011_nand_ecclayout; ++#else ++ mtd_set_ooblayout(mtd, &rb2011_nand_ecclayout_ops); ++#endif ++ } ++ ++ chip->options = NAND_NO_SUBPAGE_WRITE; ++ ++ return 0; ++} ++ ++static void __init rb2011_nand_init(void) ++{ ++ gpio_request_one(RB2011_GPIO_NAND_NCE, GPIOF_OUT_INIT_HIGH, "NAND nCE"); ++ ++ ath79_nfc_set_scan_fixup(rb2011_nand_scan_fixup); ++ ath79_nfc_set_parts(rb2011_nand_partitions, ++ ARRAY_SIZE(rb2011_nand_partitions)); ++ ath79_nfc_set_select_chip(rb2011_nand_select_chip); ++ ath79_nfc_set_swap_dma(true); ++ ath79_register_nfc(); ++} ++ ++static int rb2011_get_port_link(unsigned port) ++{ ++ if (port != 6) ++ return -EINVAL; ++ ++ /* The Loss of signal line is active low */ ++ return !gpio_get_value(RB2011_GPIO_SFP_LOS); ++} ++ ++static void __init rb2011_sfp_init(void) ++{ ++ gpio_request_one(RB2011_GPIO_SFP_LOS, GPIOF_IN, "SFP LOS"); ++ ++ rb2011_ar8327_pad6_cfg.mode = AR8327_PAD_MAC_SGMII; ++ ++ rb2011_ar8327_data.pad6_cfg = &rb2011_ar8327_pad6_cfg; ++ ++ rb2011_ar8327_sgmii_cfg.sgmii_ctrl = 0xc70167d0; ++ rb2011_ar8327_sgmii_cfg.serdes_aen = true; ++ ++ rb2011_ar8327_data.sgmii_cfg = &rb2011_ar8327_sgmii_cfg; ++ ++ rb2011_ar8327_data.port6_cfg.force_link = 1; ++ rb2011_ar8327_data.port6_cfg.speed = AR8327_PORT_SPEED_1000; ++ rb2011_ar8327_data.port6_cfg.duplex = 1; ++ ++ rb2011_ar8327_data.get_port_link = rb2011_get_port_link; ++} ++ ++static int __init rb2011_setup(u32 flags) ++{ ++ const struct rb_info *info; ++ char buf[64]; ++ ++ info = rb_init_info((void *) KSEG1ADDR(0x1f000000), 0x10000); ++ if (!info) ++ return -ENODEV; ++ ++ scnprintf(buf, sizeof(buf), "Mikrotik RouterBOARD %s", ++ (info->board_name) ? info->board_name : ""); ++ mips_set_machine_name(buf); ++ ++ rb2011_init_partitions(info); ++ ++ ath79_register_m25p80(&rb2011_spi_flash_data); ++ rb2011_nand_init(); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_RXD_DELAY | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(rb2011_mdio0_info, ++ ARRAY_SIZE(rb2011_mdio0_info)); ++ ++ /* GMAC0 is connected to an ar8327 switch */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x6f000000; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 5); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++ ++ if (flags & RB2011_FLAG_SFP) ++ rb2011_sfp_init(); ++ ++ if (flags & RB2011_FLAG_WLAN) ++ rb2011_wlan_init(); ++ ++ if (flags & RB2011_FLAG_USB) ++ ath79_register_usb(); ++ ++ return 0; ++} ++ ++static void __init rb2011l_setup(void) ++{ ++ rb2011_setup(0); ++} ++ ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_2011L, "2011L", rb2011l_setup); ++ ++static void __init rb2011us_setup(void) ++{ ++ rb2011_setup(RB2011_FLAG_SFP | RB2011_FLAG_USB); ++} ++ ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_2011US, "2011US", rb2011us_setup); ++ ++static void __init rb2011r5_setup(void) ++{ ++ rb2011_setup(RB2011_FLAG_SFP | RB2011_FLAG_USB | RB2011_FLAG_WLAN); ++} ++ ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_2011R5, "2011r5", rb2011r5_setup); ++ ++static void __init rb2011g_setup(void) ++{ ++ rb2011_setup(RB2011_FLAG_SFP | ++ RB2011_FLAG_USB | ++ RB2011_FLAG_WLAN); ++} ++ ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_2011G, "2011G", rb2011g_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb4xx.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb4xx.c +new file mode 100644 +index 0000000000..edf90e1872 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb4xx.c +@@ -0,0 +1,465 @@ ++/* ++ * MikroTik RouterBOARD 4xx series support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define RB4XX_GPIO_USER_LED 4 ++#define RB4XX_GPIO_RESET_SWITCH 7 ++ ++#define RB4XX_GPIO_CPLD_BASE 32 ++#define RB4XX_GPIO_CPLD_LED1 (RB4XX_GPIO_CPLD_BASE + CPLD_GPIO_nLED1) ++#define RB4XX_GPIO_CPLD_LED2 (RB4XX_GPIO_CPLD_BASE + CPLD_GPIO_nLED2) ++#define RB4XX_GPIO_CPLD_LED3 (RB4XX_GPIO_CPLD_BASE + CPLD_GPIO_nLED3) ++#define RB4XX_GPIO_CPLD_LED4 (RB4XX_GPIO_CPLD_BASE + CPLD_GPIO_nLED4) ++#define RB4XX_GPIO_CPLD_LED5 (RB4XX_GPIO_CPLD_BASE + CPLD_GPIO_nLED5) ++ ++#define RB4XX_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define RB4XX_KEYS_DEBOUNCE_INTERVAL (3 * RB4XX_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led rb4xx_leds_gpio[] __initdata = { ++ { ++ .name = "rb4xx:yellow:user", ++ .gpio = RB4XX_GPIO_USER_LED, ++ .active_low = 0, ++ }, { ++ .name = "rb4xx:green:led1", ++ .gpio = RB4XX_GPIO_CPLD_LED1, ++ .active_low = 1, ++ }, { ++ .name = "rb4xx:green:led2", ++ .gpio = RB4XX_GPIO_CPLD_LED2, ++ .active_low = 1, ++ }, { ++ .name = "rb4xx:green:led3", ++ .gpio = RB4XX_GPIO_CPLD_LED3, ++ .active_low = 1, ++ }, { ++ .name = "rb4xx:green:led4", ++ .gpio = RB4XX_GPIO_CPLD_LED4, ++ .active_low = 1, ++ }, { ++ .name = "rb4xx:green:led5", ++ .gpio = RB4XX_GPIO_CPLD_LED5, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button rb4xx_gpio_keys[] __initdata = { ++ { ++ .desc = "reset_switch", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = RB4XX_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RB4XX_GPIO_RESET_SWITCH, ++ .active_low = 1, ++ } ++}; ++ ++static struct platform_device rb4xx_nand_device = { ++ .name = "rb4xx-nand", ++ .id = -1, ++}; ++ ++static struct ath79_pci_irq rb4xx_pci_irqs[] = { ++ { ++ .slot = 17, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(2), ++ }, { ++ .slot = 18, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(0), ++ }, { ++ .slot = 18, ++ .pin = 2, ++ .irq = ATH79_PCI_IRQ(1), ++ }, { ++ .slot = 19, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(1), ++ }, { ++ .slot = 19, ++ .pin = 2, ++ .irq = ATH79_PCI_IRQ(2), ++ }, { ++ .slot = 20, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(2), ++ }, { ++ .slot = 20, ++ .pin = 2, ++ .irq = ATH79_PCI_IRQ(0), ++ }, { ++ .slot = 21, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(0), ++ }, { ++ .slot = 22, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(1), ++ }, { ++ .slot = 22, ++ .pin = 2, ++ .irq = ATH79_PCI_IRQ(2), ++ }, { ++ .slot = 23, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(2), ++ }, { ++ .slot = 23, ++ .pin = 2, ++ .irq = ATH79_PCI_IRQ(0), ++ } ++}; ++ ++static struct mtd_partition rb4xx_partitions[] = { ++ { ++ .name = "routerboot", ++ .offset = 0, ++ .size = 0x0b000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "hard_config", ++ .offset = 0x0b000, ++ .size = 0x01000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "bios", ++ .offset = 0x0d000, ++ .size = 0x02000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "soft_config", ++ .offset = 0x0f000, ++ .size = 0x01000, ++ } ++}; ++ ++static struct flash_platform_data rb4xx_flash_data = { ++ .type = "pm25lv512", ++ .parts = rb4xx_partitions, ++ .nr_parts = ARRAY_SIZE(rb4xx_partitions), ++}; ++ ++static struct rb4xx_cpld_platform_data rb4xx_cpld_data = { ++ .gpio_base = RB4XX_GPIO_CPLD_BASE, ++}; ++ ++static struct mmc_spi_platform_data rb4xx_mmc_data = { ++ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, ++}; ++ ++static struct spi_board_info rb4xx_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ .platform_data = &rb4xx_flash_data, ++ }, { ++ .bus_num = 0, ++ .chip_select = 1, ++ .max_speed_hz = 25000000, ++ .modalias = "spi-rb4xx-cpld", ++ .platform_data = &rb4xx_cpld_data, ++ } ++}; ++ ++static struct spi_board_info rb4xx_microsd_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 2, ++ .max_speed_hz = 25000000, ++ .modalias = "mmc_spi", ++ .platform_data = &rb4xx_mmc_data, ++ } ++}; ++ ++ ++static struct resource rb4xx_spi_resources[] = { ++ { ++ .start = AR71XX_SPI_BASE, ++ .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device rb4xx_spi_device = { ++ .name = "rb4xx-spi", ++ .id = -1, ++ .resource = rb4xx_spi_resources, ++ .num_resources = ARRAY_SIZE(rb4xx_spi_resources), ++}; ++ ++static void __init rb4xx_generic_setup(void) ++{ ++ ath79_gpio_function_enable(AR71XX_GPIO_FUNC_SPI_CS1_EN | ++ AR71XX_GPIO_FUNC_SPI_CS2_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb4xx_leds_gpio), ++ rb4xx_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, RB4XX_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(rb4xx_gpio_keys), ++ rb4xx_gpio_keys); ++ ++ spi_register_board_info(rb4xx_spi_info, ARRAY_SIZE(rb4xx_spi_info)); ++ platform_device_register(&rb4xx_spi_device); ++ platform_device_register(&rb4xx_nand_device); ++} ++ ++static void __init rb411_setup(void) ++{ ++ rb4xx_generic_setup(); ++ spi_register_board_info(rb4xx_microsd_info, ++ ARRAY_SIZE(rb4xx_microsd_info)); ++ ++ ath79_register_mdio(0, 0xfffffffc); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = 0x00000003; ++ ++ ath79_register_eth(0); ++ ++ ath79_pci_set_irq_map(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_411, "411", "MikroTik RouterBOARD 411/A/AH", ++ rb411_setup); ++ ++static void __init rb411u_setup(void) ++{ ++ rb411_setup(); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_411U, "411U", "MikroTik RouterBOARD 411U", ++ rb411u_setup); ++ ++#define RB433_LAN_PHYMASK BIT(0) ++#define RB433_WAN_PHYMASK BIT(4) ++#define RB433_MDIO_PHYMASK (RB433_LAN_PHYMASK | RB433_WAN_PHYMASK) ++ ++static void __init rb433_setup(void) ++{ ++ rb4xx_generic_setup(); ++ spi_register_board_info(rb4xx_microsd_info, ++ ARRAY_SIZE(rb4xx_microsd_info)); ++ ++ ath79_register_mdio(0, ~RB433_MDIO_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = RB433_LAN_PHYMASK; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = RB433_WAN_PHYMASK; ++ ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_pci_set_irq_map(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_433, "433", "MikroTik RouterBOARD 433/AH", ++ rb433_setup); ++ ++static void __init rb433u_setup(void) ++{ ++ rb433_setup(); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_433U, "433U", "MikroTik RouterBOARD 433UAH", ++ rb433u_setup); ++ ++static void __init rb435g_setup(void) ++{ ++ rb4xx_generic_setup(); ++ ++ spi_register_board_info(rb4xx_microsd_info, ++ ARRAY_SIZE(rb4xx_microsd_info)); ++ ++ ath79_register_mdio(0, ~RB433_MDIO_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = RB433_LAN_PHYMASK; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = RB433_WAN_PHYMASK; ++ ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_pci_set_irq_map(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); ++ ath79_register_pci(); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_435G, "435G", "MikroTik RouterBOARD 435G", ++ rb435g_setup); ++ ++#define RB450_LAN_PHYMASK BIT(0) ++#define RB450_WAN_PHYMASK BIT(4) ++#define RB450_MDIO_PHYMASK (RB450_LAN_PHYMASK | RB450_WAN_PHYMASK) ++ ++static void __init rb450_generic_setup(int gige) ++{ ++ rb4xx_generic_setup(); ++ ath79_register_mdio(0, ~RB450_MDIO_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth0_data.phy_if_mode = (gige) ? ++ PHY_INTERFACE_MODE_RGMII : PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = RB450_LAN_PHYMASK; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth1_data.phy_if_mode = (gige) ? ++ PHY_INTERFACE_MODE_RGMII : PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = RB450_WAN_PHYMASK; ++ ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++} ++ ++static void __init rb450_setup(void) ++{ ++ rb450_generic_setup(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_450, "450", "MikroTik RouterBOARD 450", ++ rb450_setup); ++ ++static void __init rb450g_setup(void) ++{ ++ rb450_generic_setup(1); ++ spi_register_board_info(rb4xx_microsd_info, ++ ARRAY_SIZE(rb4xx_microsd_info)); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_450G, "450G", "MikroTik RouterBOARD 450G", ++ rb450g_setup); ++ ++static void __init rb493_setup(void) ++{ ++ rb4xx_generic_setup(); ++ ++ ath79_register_mdio(0, 0x3fffff00); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = 0x00000001; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_pci_set_irq_map(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_493, "493", "MikroTik RouterBOARD 493/AH", ++ rb493_setup); ++ ++#define RB493G_GPIO_MDIO_MDC 7 ++#define RB493G_GPIO_MDIO_DATA 8 ++ ++#define RB493G_MDIO_PHYMASK BIT(0) ++ ++static struct mdio_gpio_platform_data rb493g_mdio_data = { ++ .mdc = RB493G_GPIO_MDIO_MDC, ++ .mdio = RB493G_GPIO_MDIO_DATA, ++ ++ .phy_mask = ~RB493G_MDIO_PHYMASK, ++}; ++ ++static struct platform_device rb493g_mdio_device = { ++ .name = "mdio-gpio", ++ .id = -1, ++ .dev = { ++ .platform_data = &rb493g_mdio_data, ++ }, ++}; ++ ++static void __init rb493g_setup(void) ++{ ++ ath79_gpio_function_enable(AR71XX_GPIO_FUNC_SPI_CS1_EN | ++ AR71XX_GPIO_FUNC_SPI_CS2_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb4xx_leds_gpio), ++ rb4xx_leds_gpio); ++ ++ spi_register_board_info(rb4xx_spi_info, ARRAY_SIZE(rb4xx_spi_info)); ++ spi_register_board_info(rb4xx_microsd_info, ++ ARRAY_SIZE(rb4xx_microsd_info)); ++ ++ platform_device_register(&rb4xx_spi_device); ++ platform_device_register(&rb4xx_nand_device); ++ ++ ath79_register_mdio(0, ~RB493G_MDIO_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = RB493G_MDIO_PHYMASK; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.mii_bus_dev = &rb493g_mdio_device.dev; ++ ath79_eth1_data.phy_mask = RB493G_MDIO_PHYMASK; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ platform_device_register(&rb493g_mdio_device); ++ ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_register_usb(); ++ ++ ath79_pci_set_irq_map(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_493G, "493G", "MikroTik RouterBOARD 493G", ++ rb493g_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c +new file mode 100644 +index 0000000000..0ec94a80e3 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c +@@ -0,0 +1,349 @@ ++/* ++ * MikroTik RouterBOARD 750/750GL support ++ * ++ * Copyright (C) 2010-2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-usb.h" ++#include "dev-eth.h" ++#include "machtypes.h" ++#include "routerboot.h" ++ ++static struct rb750_led_data rb750_leds[] = { ++ { ++ .name = "rb750:green:act", ++ .mask = RB750_LED_ACT, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port1", ++ .mask = RB750_LED_PORT5, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port2", ++ .mask = RB750_LED_PORT4, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port3", ++ .mask = RB750_LED_PORT3, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port4", ++ .mask = RB750_LED_PORT2, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port5", ++ .mask = RB750_LED_PORT1, ++ .active_low = 1, ++ } ++}; ++ ++static struct rb750_led_data rb750gr3_leds[] = { ++ { ++ .name = "rb750:green:act", ++ .mask = RB7XX_LED_ACT, ++ .active_low = 1, ++ }, ++}; ++ ++static struct rb750_led_platform_data rb750_leds_data; ++static struct platform_device rb750_leds_device = { ++ .name = "leds-rb750", ++ .dev = { ++ .platform_data = &rb750_leds_data, ++ } ++}; ++ ++static struct rb7xx_nand_platform_data rb750_nand_data; ++static struct platform_device rb750_nand_device = { ++ .name = "rb750-nand", ++ .id = -1, ++ .dev = { ++ .platform_data = &rb750_nand_data, ++ } ++}; ++ ++static void rb750_latch_change(u32 mask_clr, u32 mask_set) ++{ ++ static DEFINE_SPINLOCK(lock); ++ static u32 latch_set = RB750_LED_BITS | RB750_LVC573_LE; ++ static u32 latch_oe; ++ static u32 latch_clr; ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ if ((mask_clr & BIT(31)) != 0 && ++ (latch_set & RB750_LVC573_LE) == 0) { ++ goto unlock; ++ } ++ ++ latch_set = (latch_set | mask_set) & ~mask_clr; ++ latch_clr = (latch_clr | mask_clr) & ~mask_set; ++ ++ if (latch_oe == 0) ++ latch_oe = __raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_OE); ++ ++ if (likely(latch_set & RB750_LVC573_LE)) { ++ void __iomem *base = ath79_gpio_base; ++ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ t |= mask_clr | latch_oe | mask_set; ++ ++ __raw_writel(t, base + AR71XX_GPIO_REG_OE); ++ __raw_writel(latch_clr, base + AR71XX_GPIO_REG_CLEAR); ++ __raw_writel(latch_set, base + AR71XX_GPIO_REG_SET); ++ } else if (mask_clr & RB750_LVC573_LE) { ++ void __iomem *base = ath79_gpio_base; ++ ++ latch_oe = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ __raw_writel(RB750_LVC573_LE, base + AR71XX_GPIO_REG_CLEAR); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_CLEAR); ++ } ++ ++unlock: ++ spin_unlock_irqrestore(&lock, flags); ++} ++ ++static void rb750_nand_enable_pins(void) ++{ ++ rb750_latch_change(RB750_LVC573_LE, 0); ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE, ++ AR724X_GPIO_FUNC_SPI_EN); ++} ++ ++static void rb750_nand_disable_pins(void) ++{ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_SPI_EN, ++ AR724X_GPIO_FUNC_JTAG_DISABLE); ++ rb750_latch_change(0, RB750_LVC573_LE); ++} ++ ++static void __init rb750_setup(void) ++{ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ rb750_leds_data.num_leds = ARRAY_SIZE(rb750_leds); ++ rb750_leds_data.leds = rb750_leds; ++ rb750_leds_data.latch_change = rb750_latch_change; ++ platform_device_register(&rb750_leds_device); ++ ++ rb750_nand_data.nce_line = RB750_NAND_NCE; ++ rb750_nand_data.enable_pins = rb750_nand_enable_pins; ++ rb750_nand_data.disable_pins = rb750_nand_disable_pins; ++ rb750_nand_data.latch_change = rb750_latch_change; ++ platform_device_register(&rb750_nand_device); ++ ++ /* USB */ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_750, "750i", "MikroTik RouterBOARD 750", ++ rb750_setup); ++ ++static struct ar8327_pad_cfg rb750gr3_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data rb750gr3_ar8327_data = { ++ .pad0_cfg = &rb750gr3_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ } ++}; ++ ++static struct mdio_board_info rb750g3_mdio_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &rb750gr3_ar8327_data, ++ }, ++}; ++ ++static void rb750gr3_nand_enable_pins(void) ++{ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE, ++ AR724X_GPIO_FUNC_SPI_EN | ++ AR724X_GPIO_FUNC_SPI_CS_EN2); ++} ++ ++static void rb750gr3_nand_disable_pins(void) ++{ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_SPI_EN | ++ AR724X_GPIO_FUNC_SPI_CS_EN2, ++ AR724X_GPIO_FUNC_JTAG_DISABLE); ++} ++ ++static void rb750gr3_latch_change(u32 mask_clr, u32 mask_set) ++{ ++ static DEFINE_SPINLOCK(lock); ++ static u32 latch_set = RB7XX_LED_ACT; ++ static u32 latch_clr; ++ void __iomem *base = ath79_gpio_base; ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ latch_set = (latch_set | mask_set) & ~mask_clr; ++ latch_clr = (latch_clr | mask_clr) & ~mask_set; ++ ++ mask_set = latch_set & (RB7XX_USB_POWERON | RB7XX_MONITOR); ++ mask_clr = latch_clr & (RB7XX_USB_POWERON | RB7XX_MONITOR); ++ ++ if ((latch_set ^ RB7XX_LED_ACT) & RB7XX_LED_ACT) { ++ /* enable output mode */ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ t |= RB7XX_LED_ACT; ++ __raw_writel(t, base + AR71XX_GPIO_REG_OE); ++ ++ mask_clr |= RB7XX_LED_ACT; ++ } else { ++ /* disable output mode */ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ t &= ~RB7XX_LED_ACT; ++ __raw_writel(t, base + AR71XX_GPIO_REG_OE); ++ } ++ ++ __raw_writel(mask_set, base + AR71XX_GPIO_REG_SET); ++ __raw_writel(mask_clr, base + AR71XX_GPIO_REG_CLEAR); ++ ++ spin_unlock_irqrestore(&lock, flags); ++} ++ ++static void __init rb750gr3_setup(void) ++{ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(rb750g3_mdio_info, ++ ARRAY_SIZE(rb750g3_mdio_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_pll_data.pll_1000 = 0x62000000; ++ ++ ath79_register_eth(0); ++ ++ rb750_leds_data.num_leds = ARRAY_SIZE(rb750gr3_leds); ++ rb750_leds_data.leds = rb750gr3_leds; ++ rb750_leds_data.latch_change = rb750gr3_latch_change; ++ platform_device_register(&rb750_leds_device); ++ ++ rb750_nand_data.nce_line = RB7XX_NAND_NCE; ++ rb750_nand_data.enable_pins = rb750gr3_nand_enable_pins; ++ rb750_nand_data.disable_pins = rb750gr3_nand_disable_pins; ++ rb750_nand_data.latch_change = rb750gr3_latch_change; ++ platform_device_register(&rb750_nand_device); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_750G_R3, "750Gr3", "MikroTik RouterBOARD 750GL", ++ rb750gr3_setup); ++ ++#define RB751_HARDCONFIG 0x1f00b000 ++#define RB751_HARDCONFIG_SIZE 0x1000 ++ ++static void __init rb751_wlan_setup(void) ++{ ++ u8 *hardconfig = (u8 *) KSEG1ADDR(RB751_HARDCONFIG); ++ struct ath9k_platform_data *wmac_data; ++ u16 tag_len; ++ u8 *tag; ++ u16 mac_len; ++ u8 *mac; ++ int err; ++ ++ wmac_data = ap9x_pci_get_wmac_data(0); ++ if (!wmac_data) { ++ pr_err("rb75x: unable to get address of wlan data\n"); ++ return; ++ } ++ ++ ap9x_pci_setup_wmac_led_pin(0, 9); ++ ++ err = routerboot_find_tag(hardconfig, RB751_HARDCONFIG_SIZE, ++ RB_ID_WLAN_DATA, &tag, &tag_len); ++ if (err) { ++ pr_err("rb75x: no calibration data found\n"); ++ return; ++ } ++ ++ err = rle_decode(tag, tag_len, (unsigned char *) wmac_data->eeprom_data, ++ sizeof(wmac_data->eeprom_data), NULL, NULL); ++ if (err) { ++ pr_err("rb75x: unable to decode wlan eeprom data\n"); ++ return; ++ } ++ ++ err = routerboot_find_tag(hardconfig, RB751_HARDCONFIG_SIZE, ++ RB_ID_MAC_ADDRESS_PACK, &mac, &mac_len); ++ if (err) { ++ pr_err("rb75x: no mac address found\n"); ++ return; ++ } ++ ++ ap91_pci_init(NULL, mac); ++} ++ ++static void __init rb751_setup(void) ++{ ++ rb750_setup(); ++ ath79_register_usb(); ++ rb751_wlan_setup(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_751, "751", "MikroTik RouterBOARD 751", ++ rb751_setup); ++ ++static void __init rb751g_setup(void) ++{ ++ rb750gr3_setup(); ++ ath79_register_usb(); ++ rb751_wlan_setup(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_751G, "751g", "MikroTik RouterBOARD 751G", ++ rb751g_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb91x.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb91x.c +new file mode 100644 +index 0000000000..9620718962 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb91x.c +@@ -0,0 +1,348 @@ ++/* ++ * MikroTik RouterBOARD 91X support ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++#define pr_fmt(fmt) "rb91x: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "routerboot.h" ++ ++#define RB_ROUTERBOOT_OFFSET 0x0000 ++#define RB_ROUTERBOOT_MIN_SIZE 0xb000 ++#define RB_HARD_CFG_SIZE 0x1000 ++#define RB_BIOS_OFFSET 0xd000 ++#define RB_BIOS_SIZE 0x1000 ++#define RB_SOFT_CFG_OFFSET 0xf000 ++#define RB_SOFT_CFG_SIZE 0x1000 ++ ++#define RB91X_FLAG_USB BIT(0) ++#define RB91X_FLAG_PCIE BIT(1) ++ ++#define RB91X_LATCH_GPIO_BASE 32 ++#define RB91X_LATCH_GPIO(_x) (RB91X_LATCH_GPIO_BASE + (_x)) ++ ++#define RB91X_SSR_GPIO_BASE (RB91X_LATCH_GPIO_BASE + AR934X_GPIO_COUNT) ++#define RB91X_SSR_GPIO(_x) (RB91X_SSR_GPIO_BASE + (_x)) ++ ++#define RB91X_SSR_BIT_LED1 0 ++#define RB91X_SSR_BIT_LED2 1 ++#define RB91X_SSR_BIT_LED3 2 ++#define RB91X_SSR_BIT_LED4 3 ++#define RB91X_SSR_BIT_LED5 4 ++#define RB91X_SSR_BIT_5 5 ++#define RB91X_SSR_BIT_USB_POWER 6 ++#define RB91X_SSR_BIT_PCIE_POWER 7 ++ ++#define RB91X_GPIO_SSR_STROBE RB91X_LATCH_GPIO(0) ++#define RB91X_GPIO_LED_POWER RB91X_LATCH_GPIO(1) ++#define RB91X_GPIO_LED_USER RB91X_LATCH_GPIO(2) ++#define RB91X_GPIO_NAND_READ RB91X_LATCH_GPIO(3) ++#define RB91X_GPIO_NAND_RDY RB91X_LATCH_GPIO(4) ++#define RB91X_GPIO_NLE RB91X_LATCH_GPIO(11) ++#define RB91X_GPIO_NAND_NRW RB91X_LATCH_GPIO(12) ++#define RB91X_GPIO_NAND_NCE RB91X_LATCH_GPIO(13) ++#define RB91X_GPIO_NAND_CLE RB91X_LATCH_GPIO(14) ++#define RB91X_GPIO_NAND_ALE RB91X_LATCH_GPIO(15) ++ ++#define RB91X_GPIO_LED_1 RB91X_SSR_GPIO(RB91X_SSR_BIT_LED1) ++#define RB91X_GPIO_LED_2 RB91X_SSR_GPIO(RB91X_SSR_BIT_LED2) ++#define RB91X_GPIO_LED_3 RB91X_SSR_GPIO(RB91X_SSR_BIT_LED3) ++#define RB91X_GPIO_LED_4 RB91X_SSR_GPIO(RB91X_SSR_BIT_LED4) ++#define RB91X_GPIO_LED_5 RB91X_SSR_GPIO(RB91X_SSR_BIT_LED5) ++#define RB91X_GPIO_USB_POWER RB91X_SSR_GPIO(RB91X_SSR_BIT_USB_POWER) ++#define RB91X_GPIO_PCIE_POWER RB91X_SSR_GPIO(RB91X_SSR_BIT_PCIE_POWER) ++ ++struct rb_board_info { ++ const char *name; ++ u32 flags; ++}; ++ ++static struct mtd_partition rb711gr100_spi_partitions[] = { ++ { ++ .name = "routerboot", ++ .offset = RB_ROUTERBOOT_OFFSET, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "hard_config", ++ .size = RB_HARD_CFG_SIZE, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "bios", ++ .offset = RB_BIOS_OFFSET, ++ .size = RB_BIOS_SIZE, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "soft_config", ++ .size = RB_SOFT_CFG_SIZE, ++ } ++}; ++ ++static struct flash_platform_data rb711gr100_spi_flash_data = { ++ .parts = rb711gr100_spi_partitions, ++ .nr_parts = ARRAY_SIZE(rb711gr100_spi_partitions), ++}; ++ ++static int rb711gr100_gpio_latch_gpios[AR934X_GPIO_COUNT] __initdata = { ++ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ++ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 ++}; ++ ++static struct gpio_latch_platform_data rb711gr100_gpio_latch_data __initdata = { ++ .base = RB91X_LATCH_GPIO_BASE, ++ .num_gpios = ARRAY_SIZE(rb711gr100_gpio_latch_gpios), ++ .gpios = rb711gr100_gpio_latch_gpios, ++ .le_gpio_index = 11, ++ .le_active_low = true, ++}; ++ ++static struct rb91x_nand_platform_data rb711gr100_nand_data __initdata = { ++ .gpio_nce = RB91X_GPIO_NAND_NCE, ++ .gpio_ale = RB91X_GPIO_NAND_ALE, ++ .gpio_cle = RB91X_GPIO_NAND_CLE, ++ .gpio_rdy = RB91X_GPIO_NAND_RDY, ++ .gpio_read = RB91X_GPIO_NAND_READ, ++ .gpio_nrw = RB91X_GPIO_NAND_NRW, ++ .gpio_nle = RB91X_GPIO_NLE, ++}; ++ ++static u8 rb711gr100_ssr_initdata[] = { ++ BIT(RB91X_SSR_BIT_PCIE_POWER) | ++ BIT(RB91X_SSR_BIT_USB_POWER) | ++ BIT(RB91X_SSR_BIT_5) ++}; ++ ++static struct gen_74x164_chip_platform_data rb711gr100_ssr_data = { ++ .base = RB91X_SSR_GPIO_BASE, ++ .num_registers = ARRAY_SIZE(rb711gr100_ssr_initdata), ++ .init_data = rb711gr100_ssr_initdata, ++}; ++ ++static struct spi_board_info rb711gr100_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ .platform_data = &rb711gr100_spi_flash_data, ++ }, { ++ .bus_num = 0, ++ .chip_select = 1, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &rb711gr100_ssr_data, ++ } ++}; ++ ++static int rb711gr100_spi_cs_gpios[2] = { ++ -ENOENT, ++ RB91X_GPIO_SSR_STROBE, ++}; ++ ++static struct ath79_spi_platform_data rb711gr100_spi_data __initdata = { ++ .bus_num = 0, ++ .num_chipselect = 2, ++ .cs_gpios = rb711gr100_spi_cs_gpios, ++}; ++ ++static struct gpio_led rb711gr100_leds[] __initdata = { ++ { ++ .name = "rb:green:led1", ++ .gpio = RB91X_GPIO_LED_1, ++ .active_low = 0, ++ }, ++ { ++ .name = "rb:green:led2", ++ .gpio = RB91X_GPIO_LED_2, ++ .active_low = 0, ++ }, ++ { ++ .name = "rb:green:led3", ++ .gpio = RB91X_GPIO_LED_3, ++ .active_low = 0, ++ }, ++ { ++ .name = "rb:green:led4", ++ .gpio = RB91X_GPIO_LED_4, ++ .active_low = 0, ++ }, ++ { ++ .name = "rb:green:led5", ++ .gpio = RB91X_GPIO_LED_5, ++ .active_low = 0, ++ }, ++ { ++ .name = "rb:green:user", ++ .gpio = RB91X_GPIO_LED_USER, ++ .active_low = 0, ++ }, ++ { ++ .name = "rb:green:power", ++ .gpio = RB91X_GPIO_LED_POWER, ++ .active_low = 0, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, ++}; ++ ++static struct at803x_platform_data rb91x_at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 1, ++}; ++ ++static struct mdio_board_info rb91x_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &rb91x_at803x_data, ++ }, ++}; ++ ++static void __init rb711gr100_init_partitions(const struct rb_info *info) ++{ ++ rb711gr100_spi_partitions[0].size = info->hard_cfg_offs; ++ rb711gr100_spi_partitions[1].offset = info->hard_cfg_offs; ++ ++ rb711gr100_spi_partitions[3].offset = info->soft_cfg_offs; ++} ++ ++void __init rb711gr100_wlan_init(void) ++{ ++ char *caldata; ++ u8 wlan_mac[ETH_ALEN]; ++ ++ caldata = rb_get_wlan_data(); ++ if (caldata == NULL) ++ return; ++ ++ ath79_init_mac(wlan_mac, ath79_mac_base, 1); ++ ath79_register_wmac(caldata + 0x1000, wlan_mac); ++ ++ kfree(caldata); ++} ++ ++#define RB_BOARD_INFO(_name, _flags) \ ++ { \ ++ .name = (_name), \ ++ .flags = (_flags), \ ++ } ++ ++static const struct rb_board_info rb711gr100_boards[] __initconst = { ++ RB_BOARD_INFO("911G-2HPnD", 0), ++ RB_BOARD_INFO("911G-5HPnD", 0), ++ RB_BOARD_INFO("912UAG-2HPnD", RB91X_FLAG_USB | RB91X_FLAG_PCIE), ++ RB_BOARD_INFO("912UAG-5HPnD", RB91X_FLAG_USB | RB91X_FLAG_PCIE), ++}; ++ ++static u32 rb711gr100_get_flags(const struct rb_info *info) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(rb711gr100_boards); i++) { ++ const struct rb_board_info *bi; ++ ++ bi = &rb711gr100_boards[i]; ++ if (strcmp(info->board_name, bi->name) == 0) ++ return bi->flags; ++ } ++ ++ return 0; ++} ++ ++static void __init rb711gr100_setup(void) ++{ ++ const struct rb_info *info; ++ char buf[64]; ++ u32 flags; ++ ++ info = rb_init_info((void *) KSEG1ADDR(0x1f000000), 0x10000); ++ if (!info) ++ return; ++ ++ scnprintf(buf, sizeof(buf), "Mikrotik RouterBOARD %s", ++ (info->board_name) ? info->board_name : ""); ++ mips_set_machine_name(buf); ++ ++ rb711gr100_init_partitions(info); ++ ath79_register_spi(&rb711gr100_spi_data, rb711gr100_spi_info, ++ ARRAY_SIZE(rb711gr100_spi_info)); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_RXD_DELAY | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(rb91x_mdio0_info, ++ ARRAY_SIZE(rb91x_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_pll_data.pll_1000 = 0x02000000; ++ ++ ath79_register_eth(0); ++ ++ rb711gr100_wlan_init(); ++ ++ platform_device_register_data(NULL, "rb91x-nand", -1, ++ &rb711gr100_nand_data, ++ sizeof(rb711gr100_nand_data)); ++ ++ platform_device_register_data(NULL, "gpio-latch", -1, ++ &rb711gr100_gpio_latch_data, ++ sizeof(rb711gr100_gpio_latch_data)); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb711gr100_leds), ++ rb711gr100_leds); ++ ++ flags = rb711gr100_get_flags(info); ++ ++ if (flags & RB91X_FLAG_USB) ++ ath79_register_usb(); ++ ++ if (flags & RB91X_FLAG_PCIE) ++ ath79_register_pci(); ++ ++} ++ ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_711GR100, "711Gr100", rb711gr100_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb922.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb922.c +new file mode 100644 +index 0000000000..1c1cae1e76 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb922.c +@@ -0,0 +1,361 @@ ++/* ++ * MikroTik RouterBOARD 92X support ++ * ++ * Copyright (C) 2015 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-spi.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "routerboot.h" ++ ++#define RB922_GPIO_LED_USR 12 ++#define RB922_GPIO_USB_POWER 13 ++#define RB922_GPIO_FAN_CTRL 14 ++#define RB922_GPIO_BTN_RESET 20 ++#define RB922_GPIO_NAND_NCE 23 ++ ++#define RB92X_FLAG_USB BIT(0) ++#define RB92X_FLAG_USB_POWER BIT(1) ++#define RB92X_FLAG_PCIE BIT(2) ++ ++#define RB922_PHY_ADDR 4 ++ ++#define RB922_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define RB922_KEYS_DEBOUNCE_INTERVAL (3 * RB922_KEYS_POLL_INTERVAL) ++ ++#define RB_ROUTERBOOT_OFFSET 0x0000 ++#define RB_ROUTERBOOT_MIN_SIZE 0xb000 ++#define RB_HARD_CFG_SIZE 0x1000 ++#define RB_BIOS_OFFSET 0xd000 ++#define RB_BIOS_SIZE 0x1000 ++#define RB_SOFT_CFG_OFFSET 0xf000 ++#define RB_SOFT_CFG_SIZE 0x1000 ++ ++struct rb_board_info { ++ const char *name; ++ u32 flags; ++}; ++ ++static struct mtd_partition rb922gs_spi_partitions[] = { ++ { ++ .name = "routerboot", ++ .offset = RB_ROUTERBOOT_OFFSET, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "hard_config", ++ .size = RB_HARD_CFG_SIZE, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "bios", ++ .offset = RB_BIOS_OFFSET, ++ .size = RB_BIOS_SIZE, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "soft_config", ++ .size = RB_SOFT_CFG_SIZE, ++ } ++}; ++ ++static void __init rb922gs_init_partitions(const struct rb_info *info) ++{ ++ rb922gs_spi_partitions[0].size = info->hard_cfg_offs; ++ rb922gs_spi_partitions[1].offset = info->hard_cfg_offs; ++ rb922gs_spi_partitions[3].offset = info->soft_cfg_offs; ++} ++ ++static struct mtd_partition rb922gs_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, ++ { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, ++ { ++ .name = "ubi", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static struct flash_platform_data rb922gs_spi_flash_data = { ++ .parts = rb922gs_spi_partitions, ++ .nr_parts = ARRAY_SIZE(rb922gs_spi_partitions), ++}; ++ ++static struct gpio_led rb922gs_leds[] __initdata = { ++ { ++ .name = "rb:green:user", ++ .gpio = RB922_GPIO_LED_USR, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button rb922gs_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = RB922_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RB922_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct at803x_platform_data rb922gs_at803x_data = { ++ .disable_smarteee = 1, ++}; ++ ++static struct mdio_board_info rb922gs_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = RB922_PHY_ADDR, ++ .platform_data = &rb922gs_at803x_data, ++ }, ++}; ++ ++ ++ ++static void rb922gs_nand_select_chip(int chip_no) ++{ ++ switch (chip_no) { ++ case 0: ++ gpio_set_value(RB922_GPIO_NAND_NCE, 0); ++ break; ++ default: ++ gpio_set_value(RB922_GPIO_NAND_NCE, 1); ++ break; ++ } ++ ndelay(500); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++static struct nand_ecclayout rb922gs_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++#else ++ ++static int rb922gs_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 8; ++ oobregion->length = 3; ++ return 0; ++ case 1: ++ oobregion->offset = 13; ++ oobregion->length = 3; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static int rb922gs_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = 4; ++ return 0; ++ case 1: ++ oobregion->offset = 4; ++ oobregion->length = 1; ++ return 0; ++ case 2: ++ oobregion->offset = 6; ++ oobregion->length = 2; ++ return 0; ++ case 3: ++ oobregion->offset = 11; ++ oobregion->length = 2; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops rb922gs_nand_ecclayout_ops = { ++ .ecc = rb922gs_ooblayout_ecc, ++ .free = rb922gs_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static int rb922gs_nand_scan_fixup(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct nand_chip *chip = mtd->priv; ++#else ++ struct nand_chip *chip = mtd_to_nand(mtd); ++#endif /* < 4.6.0 */ ++ ++ if (mtd->writesize == 512) { ++ /* ++ * Use the OLD Yaffs-1 OOB layout, otherwise RouterBoot ++ * will not be able to find the kernel that we load. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ chip->ecc.layout = &rb922gs_nand_ecclayout; ++#else ++ mtd_set_ooblayout(mtd, &rb922gs_nand_ecclayout_ops); ++#endif ++ } ++ ++ chip->options = NAND_NO_SUBPAGE_WRITE; ++ ++ return 0; ++} ++ ++static void __init rb922gs_nand_init(void) ++{ ++ gpio_request_one(RB922_GPIO_NAND_NCE, GPIOF_OUT_INIT_HIGH, "NAND nCE"); ++ ++ ath79_nfc_set_scan_fixup(rb922gs_nand_scan_fixup); ++ ath79_nfc_set_parts(rb922gs_nand_partitions, ++ ARRAY_SIZE(rb922gs_nand_partitions)); ++ ath79_nfc_set_select_chip(rb922gs_nand_select_chip); ++ ath79_nfc_set_swap_dma(true); ++ ath79_register_nfc(); ++} ++ ++#define RB_BOARD_INFO(_name, _flags) \ ++ { \ ++ .name = (_name), \ ++ .flags = (_flags), \ ++ } ++ ++static const struct rb_board_info rb92x_boards[] __initconst = { ++ RB_BOARD_INFO("921GS-5HPacD r2", RB92X_FLAG_PCIE), ++ RB_BOARD_INFO("922UAGS-5HPacD", RB92X_FLAG_USB | RB92X_FLAG_USB_POWER | RB92X_FLAG_PCIE), ++}; ++ ++static u32 rb92x_get_flags(const struct rb_info *info) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(rb92x_boards); i++) { ++ const struct rb_board_info *bi; ++ ++ bi = &rb92x_boards[i]; ++ if (strcmp(info->board_name, bi->name) == 0) ++ return bi->flags; ++ } ++ ++ return 0; ++} ++ ++static void __init rb922gs_setup(void) ++{ ++ const struct rb_info *info; ++ char buf[64]; ++ u32 flags; ++ ++ info = rb_init_info((void *) KSEG1ADDR(0x1f000000), 0x10000); ++ if (!info) ++ return; ++ ++ scnprintf(buf, sizeof(buf), "MikroTik RouterBOARD %s", ++ (info->board_name) ? info->board_name : ""); ++ mips_set_machine_name(buf); ++ ++ rb922gs_init_partitions(info); ++ ath79_register_m25p80(&rb922gs_spi_flash_data); ++ ++ rb922gs_nand_init(); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(rb922gs_mdio0_info, ++ ARRAY_SIZE(rb922gs_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(RB922_PHY_ADDR); ++ if (strcmp(info->board_name, "921GS-5HPacD r2") == 0 || ++ strcmp(info->board_name, "922UAGS-5HPacD") == 0) ++ { ++ ath79_eth0_pll_data.pll_10 = 0xa0001313; ++ ath79_eth0_pll_data.pll_100 = 0xa0000101; ++ ath79_eth0_pll_data.pll_1000 = 0x8f000000; ++ } ++ else { ++ ath79_eth0_pll_data.pll_10 = 0x81001313; ++ ath79_eth0_pll_data.pll_100 = 0x81000101; ++ ath79_eth0_pll_data.pll_1000 = 0x8f000000; ++ } ++ ++ ath79_register_eth(0); ++ ++ flags = rb92x_get_flags(info); ++ ++ if (flags & RB92X_FLAG_USB) ++ ath79_register_usb(); ++ ++ if (flags & RB92X_FLAG_USB_POWER) ++ gpio_request_one(RB922_GPIO_USB_POWER, GPIOF_OUT_INIT_LOW | ++ GPIOF_EXPORT_DIR_FIXED, "USB power"); ++ ++ if (flags & RB92X_FLAG_PCIE) ++ ath79_register_pci(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb922gs_leds), rb922gs_leds); ++ ath79_register_gpio_keys_polled(-1, RB922_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(rb922gs_gpio_keys), ++ rb922gs_gpio_keys); ++ ++ /* NOTE: ++ * This only supports the RB911G-5HPacD board for now. For other boards ++ * more devices must be registered based on the hardware options which ++ * can be found in the hardware configuration of RouterBOOT. ++ */ ++} ++ ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_922GS, "922gs", rb922gs_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c +new file mode 100644 +index 0000000000..c4cf5f12a8 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c +@@ -0,0 +1,327 @@ ++/* ++ * MikroTik RouterBOARD 95X support ++ * ++ * Copyright (C) 2012 Stijn Tintel ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2013 Kamil Trzcinski ++ * ++ * 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. ++ */ ++ ++#define pr_fmt(fmt) "rb95x: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "routerboot.h" ++#include "dev-leds-gpio.h" ++ ++#define RB95X_GPIO_NAND_NCE 14 ++ ++static struct mtd_partition rb95x_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, ++ { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, ++ { ++ .name = "ubi", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static struct gpio_led rb951ui_leds_gpio[] __initdata = { ++ { ++ .name = "rb:green:wlan", ++ .gpio = 11, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:act", ++ .gpio = 3, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port1", ++ .gpio = 13, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port2", ++ .gpio = 12, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port3", ++ .gpio = 4, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port4", ++ .gpio = 21, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port5", ++ .gpio = 16, ++ .active_low = 1, ++ } ++}; ++ ++static struct ar8327_pad_cfg rb95x_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data rb95x_ar8327_data = { ++ .pad0_cfg = &rb95x_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ } ++}; ++ ++static struct mdio_board_info rb95x_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &rb95x_ar8327_data, ++ }, ++}; ++ ++void __init rb95x_wlan_init(void) ++{ ++ char *art_buf; ++ u8 wlan_mac[ETH_ALEN]; ++ ++ art_buf = rb_get_wlan_data(); ++ if (art_buf == NULL) ++ return; ++ ++ ath79_init_mac(wlan_mac, ath79_mac_base, 11); ++ ath79_register_wmac(art_buf + 0x1000, wlan_mac); ++ ++ kfree(art_buf); ++} ++ ++static void rb95x_nand_select_chip(int chip_no) ++{ ++ switch (chip_no) { ++ case 0: ++ gpio_set_value(RB95X_GPIO_NAND_NCE, 0); ++ break; ++ default: ++ gpio_set_value(RB95X_GPIO_NAND_NCE, 1); ++ break; ++ } ++ ndelay(500); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++static struct nand_ecclayout rb95x_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++#else ++ ++static int rb95x_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 8; ++ oobregion->length = 3; ++ return 0; ++ case 1: ++ oobregion->offset = 13; ++ oobregion->length = 3; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static int rb95x_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = 4; ++ return 0; ++ case 1: ++ oobregion->offset = 4; ++ oobregion->length = 1; ++ return 0; ++ case 2: ++ oobregion->offset = 6; ++ oobregion->length = 2; ++ return 0; ++ case 3: ++ oobregion->offset = 11; ++ oobregion->length = 2; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops rb95x_nand_ecclayout_ops = { ++ .ecc = rb95x_ooblayout_ecc, ++ .free = rb95x_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static int rb95x_nand_scan_fixup(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct nand_chip *chip = mtd->priv; ++#else ++ struct nand_chip *chip = mtd_to_nand(mtd); ++#endif /* < 4.6.0 */ ++ ++ if (mtd->writesize == 512) { ++ /* ++ * Use the OLD Yaffs-1 OOB layout, otherwise RouterBoot ++ * will not be able to find the kernel that we load. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ chip->ecc.layout = &rb95x_nand_ecclayout; ++#else ++ mtd_set_ooblayout(mtd, &rb95x_nand_ecclayout_ops); ++#endif ++ } ++ ++ chip->options = NAND_NO_SUBPAGE_WRITE; ++ ++ return 0; ++} ++ ++void __init rb95x_nand_init(void) ++{ ++ gpio_request_one(RB95X_GPIO_NAND_NCE, GPIOF_OUT_INIT_HIGH, "NAND nCE"); ++ ++ ath79_nfc_set_scan_fixup(rb95x_nand_scan_fixup); ++ ath79_nfc_set_parts(rb95x_nand_partitions, ++ ARRAY_SIZE(rb95x_nand_partitions)); ++ ath79_nfc_set_select_chip(rb95x_nand_select_chip); ++ ath79_nfc_set_swap_dma(true); ++ ath79_register_nfc(); ++} ++ ++static int __init rb95x_setup(void) ++{ ++ const struct rb_info *info; ++ ++ info = rb_init_info((void *)(KSEG1ADDR(AR71XX_SPI_BASE)), 0x10000); ++ if (!info) ++ return -EINVAL; ++ ++ rb95x_nand_init(); ++ ++ return 0; ++} ++ ++static void __init rb951g_setup(void) ++{ ++ if (rb95x_setup()) ++ return; ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_RXD_DELAY | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(rb95x_mdio0_info, ++ ARRAY_SIZE(rb95x_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_pll_data.pll_1000 = 0x6f000000; ++ ++ ath79_register_eth(0); ++ ++ rb95x_wlan_init(); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_951G, "951G", "MikroTik RouterBOARD 951G-2HnD", ++ rb951g_setup); ++ ++static void __init rb951ui_setup(void) ++{ ++ if (rb95x_setup()) ++ return; ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ gpio_request_one(20, GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ gpio_request_one(2, GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "POE power"); ++ ++ rb95x_wlan_init(); ++ ath79_register_usb(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb951ui_leds_gpio), ++ rb951ui_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RB_951U, "951HnD", "MikroTik RouterBOARD 951Ui-2HnD", ++ rb951ui_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c +new file mode 100644 +index 0000000000..cb05c9142c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c +@@ -0,0 +1,1262 @@ ++/* ++ * MikroTik SPI-NOR RouterBOARDs support ++ * ++ * - MikroTik RouterBOARD mAP 2nD ++ * - MikroTik RouterBOARD mAP L-2nD ++ * - MikroTik RouterBOARD 911-2Hn (911 Lite2) ++ * - MikroTik RouterBOARD 911-5Hn (911 Lite5) ++ * - MikroTik RouterBOARD 931-2nD (hAP mini) ++ * - MikroTik RouterBOARD 941L-2nD ++ * - MikroTik RouterBOARD 951Ui-2nD ++ * - MikroTik RouterBOARD 952Ui-5ac2nD ++ * - MikroTik RouterBOARD 962UiGS-5HacT2HnT ++ * - MikroTik RouterBOARD 750UP r2 ++ * - MikroTik RouterBOARD 750P-PBr2 ++ * - MikroTik RouterBOARD 750 r2 ++ * - MikroTik RouterBOARD LHG 5nD ++ * - MikroTik RouterBOARD wAP2nD ++ * - MikroTik RouterBOARD wAP G-5HacT2HnDwAP (wAP AC) ++ * - MikroTik RouterBOARD wAP R-2nD ++ * ++ * Preliminary support for the following hardware ++ * - MikroTik RouterBOARD cAP2nD ++ * Furthermore, the cAP lite (cAPL2nD) appears to feature the exact same ++ * hardware as the mAP L-2nD. It is unknown if they share the same board ++ * identifier. ++ * ++ * Copyright (C) 2017-2018 Thibaut VARENE ++ * Copyright (C) 2016 David Hutchison ++ * Copyright (C) 2017 Ryan Mounce ++ * ++ * 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 ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-spi.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "routerboot.h" ++ ++#define RBSPI_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define RBSPI_KEYS_DEBOUNCE_INTERVAL (3 * RBSPI_KEYS_POLL_INTERVAL) ++ ++#define RBSPI_HAS_USB BIT(0) ++#define RBSPI_HAS_WLAN0 BIT(1) ++#define RBSPI_HAS_WLAN1 BIT(2) ++#define RBSPI_HAS_WAN4 BIT(3) /* has WAN port on PHY4 */ ++#define RBSPI_HAS_SSR BIT(4) /* has an SSR on SPI bus 0 */ ++#define RBSPI_HAS_POE BIT(5) ++#define RBSPI_HAS_MDIO1 BIT(6) ++#define RBSPI_HAS_PCI BIT(7) ++ ++#define RB_ROUTERBOOT_OFFSET 0x0000 ++#define RB_BIOS_SIZE 0x1000 ++#define RB_SOFT_CFG_SIZE 0x1000 ++ ++/* Flash partitions indexes */ ++enum { ++ RBSPI_PART_RBOOT, ++ RBSPI_PART_HCONF, ++ RBSPI_PART_BIOS, ++ RBSPI_PART_RBOOT2, ++ RBSPI_PART_SCONF, ++ RBSPI_PART_FIRMW, ++ RBSPI_PARTS ++}; ++ ++static struct mtd_partition rbspi_spi_partitions[RBSPI_PARTS]; ++ ++/* ++ * Setup the SPI flash partition table based on initial parsing. ++ * The kernel can be at any aligned position and have any size. ++ */ ++static void __init rbspi_init_partitions(const struct rb_info *info) ++{ ++ struct mtd_partition *parts = rbspi_spi_partitions; ++ memset(parts, 0x0, sizeof(*parts)); ++ ++ parts[RBSPI_PART_RBOOT].name = "routerboot"; ++ parts[RBSPI_PART_RBOOT].offset = RB_ROUTERBOOT_OFFSET; ++ parts[RBSPI_PART_RBOOT].size = info->hard_cfg_offs; ++ parts[RBSPI_PART_RBOOT].mask_flags = MTD_WRITEABLE; ++ ++ parts[RBSPI_PART_HCONF].name = "hard_config"; ++ parts[RBSPI_PART_HCONF].offset = info->hard_cfg_offs; ++ parts[RBSPI_PART_HCONF].size = info->hard_cfg_size; ++ parts[RBSPI_PART_HCONF].mask_flags = MTD_WRITEABLE; ++ ++ parts[RBSPI_PART_BIOS].name = "bios"; ++ parts[RBSPI_PART_BIOS].offset = info->hard_cfg_offs ++ + info->hard_cfg_size; ++ parts[RBSPI_PART_BIOS].size = RB_BIOS_SIZE; ++ parts[RBSPI_PART_BIOS].mask_flags = MTD_WRITEABLE; ++ ++ parts[RBSPI_PART_RBOOT2].name = "routerboot2"; ++ parts[RBSPI_PART_RBOOT2].offset = parts[RBSPI_PART_BIOS].offset ++ + RB_BIOS_SIZE; ++ parts[RBSPI_PART_RBOOT2].size = info->soft_cfg_offs ++ - parts[RBSPI_PART_RBOOT2].offset; ++ parts[RBSPI_PART_RBOOT2].mask_flags = MTD_WRITEABLE; ++ ++ parts[RBSPI_PART_SCONF].name = "soft_config"; ++ parts[RBSPI_PART_SCONF].offset = info->soft_cfg_offs; ++ parts[RBSPI_PART_SCONF].size = RB_SOFT_CFG_SIZE; ++ ++ parts[RBSPI_PART_FIRMW].name = "firmware"; ++ parts[RBSPI_PART_FIRMW].offset = parts[RBSPI_PART_SCONF].offset ++ + parts[RBSPI_PART_SCONF].size; ++ parts[RBSPI_PART_FIRMW].size = MTDPART_SIZ_FULL; ++} ++ ++static struct flash_platform_data rbspi_spi_flash_data = { ++ .parts = rbspi_spi_partitions, ++ .nr_parts = ARRAY_SIZE(rbspi_spi_partitions), ++}; ++ ++/* ++ * Several boards only have a single reset button, use a common ++ * structure for that. ++ */ ++static struct gpio_keys_button rbspi_gpio_keys_reset[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = RBSPI_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = -ENOENT, /* filled dynamically */ ++ .active_low = 1, ++ }, ++}; ++ ++/* RB mAP L-2nD gpios */ ++#define RBMAPL_GPIO_LED_POWER 17 ++#define RBMAPL_GPIO_LED_USER 14 ++#define RBMAPL_GPIO_LED_ETH 4 ++#define RBMAPL_GPIO_LED_WLAN 11 ++#define RBMAPL_GPIO_BTN_RESET 16 ++ ++static struct gpio_led rbmapl_leds[] __initdata = { ++ { ++ .name = "rb:green:power", ++ .gpio = RBMAPL_GPIO_LED_POWER, ++ .active_low = 0, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, { ++ .name = "rb:green:user", ++ .gpio = RBMAPL_GPIO_LED_USER, ++ .active_low = 0, ++ }, { ++ .name = "rb:green:eth", ++ .gpio = RBMAPL_GPIO_LED_ETH, ++ .active_low = 0, ++ }, { ++ .name = "rb:green:wlan", ++ .gpio = RBMAPL_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++}; ++ ++/* RB 941L-2nD gpios */ ++#define RBHAPL_GPIO_LED_USER 14 ++#define RBHAPL_GPIO_BTN_RESET 16 ++ ++static struct gpio_led rbhapl_leds[] __initdata = { ++ { ++ .name = "rb:green:user", ++ .gpio = RBHAPL_GPIO_LED_USER, ++ .active_low = 1, ++ }, ++}; ++ ++/* common RB SSRs */ ++#define RBSPI_SSR_GPIO_BASE 40 ++#define RBSPI_SSR_GPIO(bit) (RBSPI_SSR_GPIO_BASE + (bit)) ++ ++/* RB 951Ui-2nD gpios */ ++#define RB952_SSR_BIT_LED_LAN1 0 ++#define RB952_SSR_BIT_LED_LAN2 1 ++#define RB952_SSR_BIT_LED_LAN3 2 ++#define RB952_SSR_BIT_LED_LAN4 3 ++#define RB952_SSR_BIT_LED_LAN5 4 ++#define RB952_SSR_BIT_USB_POWER 5 ++#define RB952_SSR_BIT_LED_WLAN 6 ++#define RB952_GPIO_SSR_CS 11 ++#define RB952_GPIO_LED_USER 4 ++#define RB952_GPIO_POE_POWER 14 ++#define RB952_GPIO_POE_STATUS 12 ++#define RB952_GPIO_BTN_RESET 16 ++#define RB952_GPIO_USB_PWROFF RBSPI_SSR_GPIO(RB952_SSR_BIT_USB_POWER) ++#define RB952_GPIO_LED_LAN1 RBSPI_SSR_GPIO(RB952_SSR_BIT_LED_LAN1) ++#define RB952_GPIO_LED_LAN2 RBSPI_SSR_GPIO(RB952_SSR_BIT_LED_LAN2) ++#define RB952_GPIO_LED_LAN3 RBSPI_SSR_GPIO(RB952_SSR_BIT_LED_LAN3) ++#define RB952_GPIO_LED_LAN4 RBSPI_SSR_GPIO(RB952_SSR_BIT_LED_LAN4) ++#define RB952_GPIO_LED_LAN5 RBSPI_SSR_GPIO(RB952_SSR_BIT_LED_LAN5) ++#define RB952_GPIO_LED_WLAN RBSPI_SSR_GPIO(RB952_SSR_BIT_LED_WLAN) ++ ++static struct gpio_led rb952_leds[] __initdata = { ++ { ++ .name = "rb:green:user", ++ .gpio = RB952_GPIO_LED_USER, ++ .active_low = 0, ++ }, { ++ .name = "rb:blue:wlan", ++ .gpio = RB952_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port1", ++ .gpio = RB952_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port2", ++ .gpio = RB952_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port3", ++ .gpio = RB952_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port4", ++ .gpio = RB952_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:port5", ++ .gpio = RB952_GPIO_LED_LAN5, ++ .active_low = 1, ++ }, ++}; ++ ++ ++/* RB 962UiGS-5HacT2HnT gpios */ ++#define RB962_WIFI_LED_1 1 ++#define RB962_WIFI_LED_2 2 ++#define RB962_GPIO_POE_STATUS 2 ++#define RB962_GPIO_POE_POWER 3 ++#define RB962_GPIO_LED_USER 12 ++#define RB962_GPIO_USB_PWROFF 13 ++#define RB962_GPIO_BTN_RESET 20 ++ ++static struct gpio_led rb962_leds_gpio[] __initdata = { ++ { ++ .name = "rb:green:user", ++ .gpio = RB962_GPIO_LED_USER, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info rb962_leds_ar8327[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "rb:green:port1"), ++ AR8327_LED_INFO(PHY1_0, HW, "rb:green:port2"), ++ AR8327_LED_INFO(PHY2_0, HW, "rb:green:port3"), ++ AR8327_LED_INFO(PHY3_0, HW, "rb:green:port4"), ++ AR8327_LED_INFO(PHY4_0, HW, "rb:green:port5"), ++}; ++ ++static struct ar8327_pad_cfg rb962_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++ .mac06_exchange_dis = true, ++}; ++ ++static struct ar8327_pad_cfg rb962_ar8327_pad6_cfg = { ++ /* Use SGMII interface for GMAC6 of the AR8337 switch */ ++ .mode = AR8327_PAD_MAC_SGMII, ++ .rxclk_delay_en = true, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL0, ++}; ++ ++static struct ar8327_led_cfg rb962_ar8327_led_cfg = { ++ .led_ctrl0 = 0xc737c737, ++ .led_ctrl1 = 0x00000000, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x0030c300, ++ .open_drain = false, ++}; ++ ++static struct ar8327_platform_data rb962_ar8327_data = { ++ .pad0_cfg = &rb962_ar8327_pad0_cfg, ++ .pad6_cfg = &rb962_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &rb962_ar8327_led_cfg, ++ .num_leds = ARRAY_SIZE(rb962_leds_ar8327), ++ .leds = rb962_leds_ar8327, ++}; ++ ++static struct mdio_board_info rb962_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &rb962_ar8327_data, ++ }, ++}; ++ ++/* RB wAP-2nD gpios */ ++#define RBWAP_GPIO_LED_USER 14 ++#define RBWAP_GPIO_LED_WLAN 11 ++#define RBWAP_GPIO_BTN_RESET 16 ++ ++static struct gpio_led rbwap_leds[] __initdata = { ++ { ++ .name = "rb:green:user", ++ .gpio = RBWAP_GPIO_LED_USER, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:wlan", ++ .gpio = RBWAP_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++/* RB cAP-2nD gpios */ ++#define RBCAP_GPIO_LED_1 14 ++#define RBCAP_GPIO_LED_2 12 ++#define RBCAP_GPIO_LED_3 11 ++#define RBCAP_GPIO_LED_4 4 ++#define RBCAP_GPIO_LED_ALL 13 ++ ++static struct gpio_led rbcap_leds[] __initdata = { ++ { ++ .name = "rb:green:rssi1", ++ .gpio = RBCAP_GPIO_LED_1, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:rssi2", ++ .gpio = RBCAP_GPIO_LED_2, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:rssi3", ++ .gpio = RBCAP_GPIO_LED_3, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:rssi4", ++ .gpio = RBCAP_GPIO_LED_4, ++ .active_low = 1, ++ }, ++}; ++ ++/* RB mAP-2nD gpios */ ++#define RBMAP_SSR_BIT_LED_LAN1 0 ++#define RBMAP_SSR_BIT_LED_LAN2 1 ++#define RBMAP_SSR_BIT_LED_POEO 2 ++#define RBMAP_SSR_BIT_LED_USER 3 ++#define RBMAP_SSR_BIT_LED_WLAN 4 ++#define RBMAP_SSR_BIT_USB_POWER 5 ++#define RBMAP_SSR_BIT_LED_APCAP 6 ++#define RBMAP_GPIO_BTN_RESET 16 ++#define RBMAP_GPIO_SSR_CS 11 ++#define RBMAP_GPIO_LED_POWER 4 ++#define RBMAP_GPIO_POE_POWER 14 ++#define RBMAP_GPIO_POE_STATUS 12 ++#define RBMAP_GPIO_USB_PWROFF RBSPI_SSR_GPIO(RBMAP_SSR_BIT_USB_POWER) ++#define RBMAP_GPIO_LED_LAN1 RBSPI_SSR_GPIO(RBMAP_SSR_BIT_LED_LAN1) ++#define RBMAP_GPIO_LED_LAN2 RBSPI_SSR_GPIO(RBMAP_SSR_BIT_LED_LAN2) ++#define RBMAP_GPIO_LED_POEO RBSPI_SSR_GPIO(RBMAP_SSR_BIT_LED_POEO) ++#define RBMAP_GPIO_LED_USER RBSPI_SSR_GPIO(RBMAP_SSR_BIT_LED_USER) ++#define RBMAP_GPIO_LED_WLAN RBSPI_SSR_GPIO(RBMAP_SSR_BIT_LED_WLAN) ++#define RBMAP_GPIO_LED_APCAP RBSPI_SSR_GPIO(RBMAP_SSR_BIT_LED_APCAP) ++ ++static struct gpio_led rbmap_leds[] __initdata = { ++ { ++ .name = "rb:green:power", ++ .gpio = RBMAP_GPIO_LED_POWER, ++ .active_low = 1, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, { ++ .name = "rb:green:eth1", ++ .gpio = RBMAP_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:eth2", ++ .gpio = RBMAP_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "rb:red:poe_out", ++ .gpio = RBMAP_GPIO_LED_POEO, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:user", ++ .gpio = RBMAP_GPIO_LED_USER, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:wlan", ++ .gpio = RBMAP_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:ap_cap", ++ .gpio = RBMAP_GPIO_LED_APCAP, ++ .active_low = 1, ++ }, ++}; ++ ++/* RB LHG 5nD gpios */ ++#define RBLHG_GPIO_LED_0 13 ++#define RBLHG_GPIO_LED_1 12 ++#define RBLHG_GPIO_LED_2 4 ++#define RBLHG_GPIO_LED_3 21 ++#define RBLHG_GPIO_LED_4 18 ++#define RBLHG_GPIO_LED_ETH 14 ++#define RBLHG_GPIO_LED_POWER 11 ++#define RBLHG_GPIO_LED_USER 20 ++#define RBLHG_GPIO_BTN_RESET 15 ++ ++static struct gpio_led rblhg_leds[] __initdata = { ++ { ++ .name = "rb:green:rssi0", ++ .gpio = RBLHG_GPIO_LED_0, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:rssi1", ++ .gpio = RBLHG_GPIO_LED_1, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:rssi2", ++ .gpio = RBLHG_GPIO_LED_2, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:rssi3", ++ .gpio = RBLHG_GPIO_LED_3, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:rssi4", ++ .gpio = RBLHG_GPIO_LED_4, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:eth", ++ .gpio = RBLHG_GPIO_LED_ETH, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:user", ++ .gpio = RBLHG_GPIO_LED_USER, ++ .active_low = 1, ++ }, { ++ .name = "rb:blue:power", ++ .gpio = RBLHG_GPIO_LED_POWER, ++ .active_low = 0, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, ++}; ++ ++/* RB w APG-5HacT2HnD (wAP AC) gpios*/ ++#define RBWAPGSC_WIFI_LED_1 1 ++#define RBWAPGSC_WIFI_LED_2 8 ++#define RBWAPGSC_WIFI_LED_3 9 ++#define RBWAPGSC_GPIO_LED_POWER 16 ++#define RBWAPGSC_GPIO_BTN_RESET 1 ++#define RBWAPGSC_GPIO_MDIO_MDC 12 ++#define RBWAPGSC_GPIO_MDIO_DATA 11 ++#define RBWAPGSC_MDIO_PHYADDR 0 ++ ++static struct gpio_led rbwapgsc_leds[] __initdata = { ++ { ++ .name = "rb:green:power", ++ .gpio = RBWAPGSC_GPIO_LED_POWER, ++ .active_low = 1, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, ++}; ++ ++static struct mdio_gpio_platform_data rbwapgsc_mdio_data = { ++ .mdc = RBWAPGSC_GPIO_MDIO_MDC, ++ .mdio = RBWAPGSC_GPIO_MDIO_DATA, ++ .phy_mask = ~BIT(RBWAPGSC_MDIO_PHYADDR), ++}; ++ ++static struct platform_device rbwapgsc_phy_device = { ++ .name = "mdio-gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &rbwapgsc_mdio_data ++ }, ++}; ++ ++static struct at803x_platform_data rbwapgsc_at803x_data = { ++ .override_sgmii_aneg = 1, ++}; ++ ++static struct mdio_board_info rbwapgsc_mdio_info[] = { ++ { ++ .bus_id = "gpio-1", ++ .mdio_addr = RBWAPGSC_MDIO_PHYADDR, ++ .platform_data = &rbwapgsc_at803x_data, ++ }, ++}; ++ ++/* RB911L GPIOs */ ++#define RB911L_GPIO_BTN_RESET 15 ++#define RB911L_GPIO_LED_1 13 ++#define RB911L_GPIO_LED_2 12 ++#define RB911L_GPIO_LED_3 4 ++#define RB911L_GPIO_LED_4 21 ++#define RB911L_GPIO_LED_5 18 ++#define RB911L_GPIO_LED_ETH 20 ++#define RB911L_GPIO_LED_POWER 11 ++#define RB911L_GPIO_LED_USER 3 ++#define RB911L_GPIO_PIN_HOLE 14 /* for reference, active low */ ++ ++static struct gpio_led rb911l_leds[] __initdata = { ++ { ++ .name = "rb:green:eth", ++ .gpio = RB911L_GPIO_LED_ETH, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:led1", ++ .gpio = RB911L_GPIO_LED_1, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:led2", ++ .gpio = RB911L_GPIO_LED_2, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:led3", ++ .gpio = RB911L_GPIO_LED_3, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:led4", ++ .gpio = RB911L_GPIO_LED_4, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:led5", ++ .gpio = RB911L_GPIO_LED_5, ++ .active_low = 1, ++ }, { ++ .name = "rb:green:power", ++ .gpio = RB911L_GPIO_LED_POWER, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ .active_low = 1, ++ .open_drain = 1, ++ }, { ++ .name = "rb:green:user", ++ .gpio = RB911L_GPIO_LED_USER, ++ .active_low = 1, ++ .open_drain = 1, ++ }, ++}; ++ ++/* RB 931-2nD gpios */ ++#define RB931_GPIO_BTN_RESET 0 ++#define RB931_GPIO_BTN_MODE 9 ++#define RB931_GPIO_LED_USER 1 ++ ++static struct gpio_keys_button rb931_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = RBSPI_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RB931_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "Mode button", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = RBSPI_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RB931_GPIO_BTN_MODE, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led rb931_leds[] __initdata = { ++ { ++ .name = "rb:green:user", ++ .gpio = RB931_GPIO_LED_USER, ++ .active_low = 1, ++ }, ++}; ++ ++/* RB wAP R-2nD (wAP R) gpios*/ ++#define RBWAPR_GPIO_LED_USER 14 ++#define RBWAPR_GPIO_LED1 12 ++#define RBWAPR_GPIO_LED2 13 ++#define RBWAPR_GPIO_LED3 3 ++#define RBWAPR_GPIO_PCIE_PWROFF 15 ++#define RBWAPR_GPIO_CONTROL 10 ++#define RBWAPR_GPIO_BTN_RESET 16 ++ ++static struct gpio_led rbwapr_leds[] __initdata = { ++ { ++ .name = "rb:green:user", ++ .gpio = RBWAPR_GPIO_LED_USER, ++ .active_low = 0, ++ },{ ++ .name = "rb:green:led1", ++ .gpio = RBWAPR_GPIO_LED1, ++ .active_low = 1, ++ },{ ++ .name = "rb:green:led2", ++ .gpio = RBWAPR_GPIO_LED2, ++ .active_low = 1, ++ },{ ++ .name = "rb:green:led3", ++ .gpio = RBWAPR_GPIO_LED3, ++ .active_low = 0, ++ }, ++}; ++ ++ ++static struct gen_74x164_chip_platform_data rbspi_ssr_data = { ++ .base = RBSPI_SSR_GPIO_BASE, ++ .num_registers = 1, ++}; ++ ++/* the spi-ath79 driver can only natively handle CS0. Other CS are bit-banged */ ++static int rbspi_spi_cs_gpios[] = { ++ -ENOENT, /* CS0 is always -ENOENT: natively handled */ ++ -ENOENT, /* CS1 can be updated by the code as necessary */ ++}; ++ ++static struct ath79_spi_platform_data rbspi_ath79_spi_data = { ++ .bus_num = 0, ++ .cs_gpios = rbspi_spi_cs_gpios, ++}; ++ ++/* ++ * Global spi_board_info: devices that don't have an SSR only have the SPI NOR ++ * flash on bus0 CS0, while devices that have an SSR add it on the same bus CS1 ++ */ ++static struct spi_board_info rbspi_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ .platform_data = &rbspi_spi_flash_data, ++ }, { ++ .bus_num = 0, ++ .chip_select = 1, ++ .max_speed_hz = 25000000, ++ .modalias = "74x164", ++ .platform_data = &rbspi_ssr_data, ++ } ++}; ++ ++void __init rbspi_wlan_init(int wmac_offset) ++{ ++ char *art_buf; ++ u8 wlan_mac[ETH_ALEN]; ++ ++ art_buf = rb_get_wlan_data(); ++ if (!art_buf) ++ return; ++ ++ ath79_init_mac(wlan_mac, ath79_mac_base, wmac_offset); ++ ath79_register_wmac(art_buf + 0x1000, wlan_mac); ++ ++ kfree(art_buf); ++} ++ ++#define RBSPI_MACH_BUFLEN 64 ++/* ++ * Common platform init routine for all SPI NOR devices. ++ */ ++static __init const struct rb_info *rbspi_platform_setup(void) ++{ ++ const struct rb_info *info; ++ char buf[RBSPI_MACH_BUFLEN] = "MikroTik "; ++ char *str; ++ int len = RBSPI_MACH_BUFLEN - strlen(buf) - 1; ++ ++ info = rb_init_info((void *)(KSEG1ADDR(AR71XX_SPI_BASE)), 0x20000); ++ if (!info) ++ return NULL; ++ ++ if (info->board_name) { ++ str = "RouterBOARD "; ++ if (strncmp(info->board_name, str, strlen(str))) { ++ strncat(buf, str, len); ++ len -= strlen(str); ++ } ++ strncat(buf, info->board_name, len); ++ } ++ else ++ strncat(buf, "UNKNOWN", len); ++ ++ mips_set_machine_name(buf); ++ ++ /* fix partitions based on flash parsing */ ++ rbspi_init_partitions(info); ++ ++ return info; ++} ++ ++/* ++ * Common peripherals init routine for all SPI NOR devices. ++ * Sets SPI and USB. ++ */ ++static void __init rbspi_peripherals_setup(u32 flags) ++{ ++ unsigned spi_n; ++ ++ if (flags & RBSPI_HAS_SSR) ++ spi_n = ARRAY_SIZE(rbspi_spi_info); ++ else ++ spi_n = 1; /* only one device on bus0 */ ++ ++ rbspi_ath79_spi_data.num_chipselect = spi_n; ++ rbspi_ath79_spi_data.cs_gpios = rbspi_spi_cs_gpios; ++ ath79_register_spi(&rbspi_ath79_spi_data, rbspi_spi_info, spi_n); ++ ++ if (flags & RBSPI_HAS_USB) ++ ath79_register_usb(); ++ ++ if (flags & RBSPI_HAS_PCI) ++ ath79_register_pci(); ++} ++ ++/* ++ * Common network init routine for all SPI NOR devices. ++ * Sets LAN/WAN/WLAN. ++ */ ++static void __init rbspi_network_setup(u32 flags, int gmac1_offset, ++ int wmac0_offset, int wmac1_offset) ++{ ++ /* for QCA953x that will init mdio1_device/data */ ++ ath79_register_mdio(0, 0x0); ++ if (flags & RBSPI_HAS_MDIO1) ++ ath79_register_mdio(1, 0x0); ++ ++ if (flags & RBSPI_HAS_WAN4) { ++ ath79_setup_ar934x_eth_cfg(0); ++ ++ /* set switch to oper mode 1, PHY4 connected to CPU */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ++ /* init GMAC0 connected to PHY4 at 100M */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_register_eth(0); ++ } else { ++ /* set the SoC to SW_ONLY_MODE, which connects all PHYs ++ * to the internal switch. ++ * We hijack ath79_setup_ar934x_eth_cfg() to set the switch in ++ * the QCA953x, this works because this configuration bit is ++ * the same as the AR934x. There's no equivalent function for ++ * QCA953x for now. */ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ } ++ ++ /* init GMAC1 */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, gmac1_offset); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ if (flags & RBSPI_HAS_WLAN0) ++ rbspi_wlan_init(wmac0_offset); ++ ++ if (flags & RBSPI_HAS_WLAN1) ++ rbspi_wlan_init(wmac1_offset); ++} ++ ++static __init void rbspi_register_reset_button(int gpio) ++{ ++ rbspi_gpio_keys_reset[0].gpio = gpio; ++ ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(rbspi_gpio_keys_reset), ++ rbspi_gpio_keys_reset); ++} ++ ++/* ++ * Init the mAP lite hardware (QCA953x). ++ * The mAP L-2nD (mAP lite) has a single ethernet port, connected to PHY0. ++ * Trying to use GMAC0 in direct mode was unsucessful, so we're ++ * using SW_ONLY_MODE, which connects PHY0 to MAC1 on the internal ++ * switch, which is connected to GMAC1 on the SoC. GMAC0 is unused. ++ */ ++static void __init rbmapl_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WLAN0; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* GMAC1 is HW MAC, WLAN0 MAC is HW MAC + 1 */ ++ rbspi_network_setup(flags, 0, 1, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbmapl_leds), rbmapl_leds); ++ ++ /* mAP lite has a single reset button as gpio 16 */ ++ rbspi_register_reset_button(RBMAPL_GPIO_BTN_RESET); ++ ++ /* clear internal multiplexing */ ++ ath79_gpio_output_select(RBMAPL_GPIO_LED_ETH, AR934X_GPIO_OUT_GPIO); ++ ath79_gpio_output_select(RBMAPL_GPIO_LED_POWER, AR934X_GPIO_OUT_GPIO); ++} ++ ++/* ++ * Init the hAP lite hardware (QCA953x). ++ * The 941-2nD (hAP lite) has 4 ethernet ports, with port 2-4 ++ * being assigned to LAN on the casing, and port 1 being assigned ++ * to "internet" (WAN) on the casing. Port 1 is connected to PHY3. ++ * Since WAN is neither PHY0 nor PHY4, we cannot use GMAC0 with this device. ++ */ ++static void __init rbhapl_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WLAN0; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* GMAC1 is HW MAC, WLAN0 MAC is HW MAC + 4 */ ++ rbspi_network_setup(flags, 0, 4, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbhapl_leds), rbhapl_leds); ++ ++ /* hAP lite has a single reset button as gpio 16 */ ++ rbspi_register_reset_button(RBHAPL_GPIO_BTN_RESET); ++} ++ ++/* ++ * The hAP, hAP ac lite, hEX lite and hEX PoE lite share the same platform ++ */ ++static void __init rbspi_952_750r2_setup(u32 flags) ++{ ++ if (flags & RBSPI_HAS_SSR) ++ rbspi_spi_cs_gpios[1] = RB952_GPIO_SSR_CS; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* ++ * GMAC1 is HW MAC + 1, WLAN0 MAC IS HW MAC + 5 (hAP), ++ * WLAN1 MAC IS HW MAC + 6 (hAP ac lite) ++ */ ++ rbspi_network_setup(flags, 1, 5, 6); ++ ++ if (flags & RBSPI_HAS_USB) ++ gpio_request_one(RB952_GPIO_USB_PWROFF, GPIOF_ACTIVE_LOW | ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power off"); ++ ++ if (flags & RBSPI_HAS_POE) ++ gpio_request_one(RB952_GPIO_POE_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "POE power"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb952_leds), rb952_leds); ++ ++ /* These devices have a single reset button as gpio 16 */ ++ rbspi_register_reset_button(RB952_GPIO_BTN_RESET); ++} ++ ++/* ++ * Init the hAP (ac lite) hardware (QCA953x). ++ * The 951Ui-2nD (hAP) has 5 ethernet ports, with ports 2-5 being assigned ++ * to LAN on the casing, and port 1 being assigned to "internet" (WAN). ++ * Port 1 is connected to PHY4 (the ports are labelled in reverse physical ++ * number), so the SoC can be set to connect GMAC0 to PHY4 and GMAC1 to the ++ * internal switch for the LAN ports. ++ * The device also has USB, PoE output and an SSR used for LED multiplexing. ++ * The 952Ui-5ac2nD (hAP ac lite) is nearly identical to the hAP, it adds a ++ * QCA9887 5GHz radio via PCI and moves 2.4GHz from WLAN0 to WLAN1. ++ */ ++static void __init rb952_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WAN4 | RBSPI_HAS_USB | ++ RBSPI_HAS_SSR | RBSPI_HAS_POE; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ /* differentiate the hAP from the hAP ac lite */ ++ if (strstr(mips_get_machine_name(), "952Ui-5ac2nD")) ++ flags |= RBSPI_HAS_WLAN1 | RBSPI_HAS_PCI; ++ else ++ flags |= RBSPI_HAS_WLAN0; ++ ++ rbspi_952_750r2_setup(flags); ++} ++ ++/* ++ * Init the hEX (PoE) lite hardware (QCA953x). ++ * The 750UP r2 (hEX PoE lite) is nearly identical to the hAP, only without ++ * WLAN. The 750 r2 (hEX lite) is nearly identical to the 750UP r2, only ++ * without USB and POE. The 750P Pbr2 (Powerbox) is nearly identical to hEX PoE ++ * lite, only without USB. It shares the same bootloader board identifier. ++ */ ++static void __init rb750upr2_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WAN4 | RBSPI_HAS_SSR; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ /* differentiate the hEX lite from the hEX PoE lite */ ++ if (strstr(mips_get_machine_name(), "750UP r2")) ++ flags |= RBSPI_HAS_USB | RBSPI_HAS_POE; ++ ++ /* differentiate the Powerbox from the hEX lite */ ++ else if (strstr(mips_get_machine_name(), "750P r2")) ++ flags |= RBSPI_HAS_POE; ++ ++ rbspi_952_750r2_setup(flags); ++} ++ ++/* ++ * Init the hAP ac / 962UiGS-5HacT2HnT hardware (QCA9558). ++ * The hAP ac has 5 ethernet ports provided by an AR8337 switch. Port 1 is ++ * assigned to WAN, ports 2-5 are assigned to LAN. Port 0 is connected to the ++ * SoC, ports 1-5 of the switch are connected to physical ports 1-5 in order. ++ * The SFP cage is not assigned by default on RouterOS. Extra work is required ++ * to support this interface as it is directly connected to the SoC (eth1). ++ * Wireless is provided by a 2.4GHz radio on the SoC (WLAN1) and a 5GHz radio ++ * attached via PCI (QCA9880). Red and green WLAN LEDs are populated however ++ * they are not attached to GPIOs, extra work is required to support these. ++ * PoE and USB output power control is supported. ++ */ ++static void __init rb962_setup(void) ++{ ++ u32 flags = RBSPI_HAS_USB | RBSPI_HAS_POE | RBSPI_HAS_PCI; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* Do not call rbspi_network_setup as we have a discrete switch chip */ ++ ath79_eth0_pll_data.pll_1000 = 0xae000000; ++ ath79_eth0_pll_data.pll_100 = 0xa0000101; ++ ath79_eth0_pll_data.pll_10 = 0xa0001313; ++ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(rb962_mdio0_info, ++ ARRAY_SIZE(rb962_mdio0_info)); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_register_eth(0); ++ ++ /* WLAN1 MAC is HW MAC + 7 */ ++ rbspi_wlan_init(7); ++ ++ if (flags & RBSPI_HAS_USB) ++ gpio_request_one(RB962_GPIO_USB_PWROFF, GPIOF_ACTIVE_LOW | ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power off"); ++ ++ /* PoE output GPIO is inverted, set GPIOF_ACTIVE_LOW for consistency */ ++ if (flags & RBSPI_HAS_POE) ++ gpio_request_one(RB962_GPIO_POE_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_ACTIVE_LOW | ++ GPIOF_EXPORT_DIR_FIXED, ++ "POE power"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb962_leds_gpio), ++ rb962_leds_gpio); ++ ++ /* This device has a single reset button as gpio 20 */ ++ rbspi_register_reset_button(RB962_GPIO_BTN_RESET); ++} ++ ++/* ++ * Init the LHG hardware (AR9344). ++ * The LHG 5nD has a single ethernet port connected to PHY0. ++ * Wireless is provided via 5GHz WLAN1. ++ */ ++static void __init rblhg_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WLAN1 | RBSPI_HAS_MDIO1; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* GMAC1 is HW MAC, WLAN1 MAC is HW MAC + 1 */ ++ rbspi_network_setup(flags, 0, 0, 1); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rblhg_leds), rblhg_leds); ++ ++ rbspi_register_reset_button(RBLHG_GPIO_BTN_RESET); ++} ++ ++/* ++ * Init the wAP hardware. ++ * The wAP 2nD has a single ethernet port. ++ */ ++static void __init rbwap_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WLAN0; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* GMAC1 is HW MAC, WLAN0 MAC is HW MAC + 1 */ ++ rbspi_network_setup(flags, 0, 1, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbwap_leds), rbwap_leds); ++ ++ /* wAP has a single reset button as GPIO 16 */ ++ rbspi_register_reset_button(RBWAP_GPIO_BTN_RESET); ++} ++ ++/* ++ * Init the cAP hardware (EXPERIMENTAL). ++ * The cAP 2nD has a single ethernet port, and a global LED switch. ++ */ ++static void __init rbcap_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WLAN0; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* GMAC1 is HW MAC, WLAN0 MAC is HW MAC + 1 */ ++ rbspi_network_setup(flags, 0, 1, 0); ++ ++ gpio_request_one(RBCAP_GPIO_LED_ALL, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LEDs enable"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbcap_leds), rbcap_leds); ++} ++ ++/* ++ * Init the mAP hardware. ++ * The mAP 2nD has two ethernet ports, PoE output, SSR for LED ++ * multiplexing and USB port. ++ */ ++static void __init rbmap_setup(void) ++{ ++ u32 flags = RBSPI_HAS_USB | RBSPI_HAS_WLAN0 | ++ RBSPI_HAS_SSR | RBSPI_HAS_POE; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_spi_cs_gpios[1] = RBMAP_GPIO_SSR_CS; ++ rbspi_peripherals_setup(flags); ++ ++ /* GMAC1 is HW MAC, WLAN0 MAC is HW MAC + 2 */ ++ rbspi_network_setup(flags, 0, 2, 0); ++ ++ if (flags & RBSPI_HAS_POE) ++ gpio_request_one(RBMAP_GPIO_POE_POWER, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "POE power"); ++ ++ if (flags & RBSPI_HAS_USB) ++ gpio_request_one(RBMAP_GPIO_USB_PWROFF, ++ GPIOF_OUT_INIT_HIGH | GPIOF_ACTIVE_LOW | ++ GPIOF_EXPORT_DIR_FIXED, ++ "USB power off"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbmap_leds), rbmap_leds); ++ ++ /* mAP 2nD has a single reset button as gpio 16 */ ++ rbspi_register_reset_button(RBMAP_GPIO_BTN_RESET); ++} ++ ++/* ++ * Init the wAPGSC (RB wAPG-5HacT2HnD // wAP AC) hardware. ++ * The wAPGSC has one Ethernet port via AR8033 with PoE input, dual radio (SoC ++ * 2.4 GHz and external QCA9880) and a ZT2046Q temperature and voltage sensor ++ * (currently not supported). ++ */ ++static void __init rbwapgsc_setup(void) ++{ ++ u32 flags = RBSPI_HAS_PCI; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ platform_device_register(&rbwapgsc_phy_device); ++ ++ mdiobus_register_board_info(rbwapgsc_mdio_info, ++ ARRAY_SIZE(rbwapgsc_mdio_info)); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth1_data.mii_bus_dev = &rbwapgsc_phy_device.dev; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.phy_mask = BIT(RBWAPGSC_MDIO_PHYADDR); ++ ath79_eth1_data.enable_sgmii_fixup = 1; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ath79_eth1_pll_data.pll_100 = 0x80000101; ++ ath79_eth1_pll_data.pll_10 = 0x80001313; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_register_eth(1); ++ ++ rbspi_wlan_init(2); ++ ++ rbspi_register_reset_button(RBWAPGSC_GPIO_BTN_RESET); ++ ++ ath79_gpio_function_enable(QCA955X_GPIO_FUNC_JTAG_DISABLE| ++ QCA955X_GPIO_REG_OUT_FUNC4| ++ QCA955X_GPIO_REG_OUT_FUNC3); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbwapgsc_leds), ++ rbwapgsc_leds); ++} ++ ++/* ++ * Setup the 911L hardware (AR9344). ++ */ ++static void __init rb911l_setup(void) ++{ ++ const struct rb_info *info; ++ ++ info = rbspi_platform_setup(); ++ if (!info) ++ return; ++ ++ if (!rb_has_hw_option(info, RB_HW_OPT_NO_NAND)) { ++ /* ++ * Old hardware revisions might be equipped with a NAND flash ++ * chip instead of the 16MiB SPI NOR device. Those boards are ++ * not supported at the moment, so throw a warning and skip ++ * the peripheral setup to avoid messing up the data in the ++ * flash chip. ++ */ ++ WARN(1, "The NAND flash on this board is not supported.\n"); ++ } else { ++ rbspi_peripherals_setup(0); ++ } ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++ ++ rbspi_wlan_init(1); ++ ++ rbspi_register_reset_button(RB911L_GPIO_BTN_RESET); ++ ++ /* Make the eth LED controllable by software. */ ++ ath79_gpio_output_select(RB911L_GPIO_LED_ETH, AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb911l_leds), rb911l_leds); ++} ++ ++/* ++ * Init the hAP mini hardware (QCA953x). ++ * The 931-2nD (hAP mini) has 3 ethernet ports, with port 2-3 ++ * being assigned to LAN on the casing, and port 1 being assigned ++ * to "internet" (WAN) on the casing. Port 1 is connected to PHY2. ++ * Since WAN is neither PHY0 nor PHY4, we cannot use GMAC0 with this device. ++ */ ++static void __init rb931_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WLAN0; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* GMAC1 is HW MAC, WLAN0 MAC is HW MAC + 3 */ ++ rbspi_network_setup(flags, 0, 3, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb931_leds), rb931_leds); ++ ++ /* hAP mini has two buttons */ ++ ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(rb931_gpio_keys), ++ rb931_gpio_keys); ++} ++ ++/* ++ * Init the wAP R hardware. ++ * The wAP R-2nD has a single ethernet port and a mini PCIe slot. ++ * The OEM source shows it has usb (used over PCIe for LTE devices), ++ * and the 'control' GPIO is assumed to be an output pin not tied to an LED. ++ */ ++static void __init rbwapr_setup(void) ++{ ++ u32 flags = RBSPI_HAS_WLAN0 | RBSPI_HAS_USB | RBSPI_HAS_PCI; ++ ++ if (!rbspi_platform_setup()) ++ return; ++ ++ rbspi_peripherals_setup(flags); ++ ++ /* GMAC1 is HW MAC, WLAN0 MAC is HW MAC + 1 */ ++ rbspi_network_setup(flags, 0, 1, 0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbwapr_leds), rbwapr_leds); ++ ++ gpio_request_one(RBWAPR_GPIO_PCIE_PWROFF, GPIOF_OUT_INIT_HIGH | ++ GPIOF_ACTIVE_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "PCIE power off"); ++ ++ gpio_request_one(RBWAPR_GPIO_CONTROL, GPIOF_OUT_INIT_LOW | ++ GPIOF_ACTIVE_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "control"); ++ ++ rbspi_register_reset_button(RBWAPR_GPIO_BTN_RESET); ++} ++ ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_MAPL, "map-hb", rbmapl_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_941, "H951L", rbhapl_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_911L, "911L", rb911l_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_952, "952-hb", rb952_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_962, "962", rb962_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_750UPR2, "750-hb", rb750upr2_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_LHG5, "lhg", rblhg_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_WAP, "wap-hb", rbwap_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_WAPR, "wap-lte", rbwapr_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_CAP, "cap-hb", rbcap_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_MAP, "map2-hb", rbmap_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_WAPAC, "wapg-sc", rbwapgsc_setup); ++MIPS_MACHINE_NONAME(ATH79_MACH_RB_931, "931", rb931_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rbsxtlite.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rbsxtlite.c +new file mode 100644 +index 0000000000..7eb0e54151 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rbsxtlite.c +@@ -0,0 +1,302 @@ ++/* ++ * MikroTik RouterBOARD SXT Lite support ++ * ++ * Copyright (C) 2012 Stijn Tintel ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2013 Vyacheslav Adamanov ++ * ++ * 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. ++ */ ++ ++#define pr_fmt(fmt) "sxtlite: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-wmac.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "routerboot.h" ++#include ++ ++#define SXTLITE_GPIO_NAND_NCE 14 ++#define SXTLITE_GPIO_LED_USER 3 ++#define SXTLITE_GPIO_LED_1 13 ++#define SXTLITE_GPIO_LED_2 12 ++#define SXTLITE_GPIO_LED_3 4 ++#define SXTLITE_GPIO_LED_4 21 ++#define SXTLITE_GPIO_LED_5 18 ++#define SXTLITE_GPIO_LED_POWER 11 ++ ++#define SXTLITE_GPIO_BUZZER 19 ++ ++#define SXTLITE_GPIO_BTN_RESET 15 ++ ++#define SXTLITE_KEYS_POLL_INTERVAL 20 ++#define SXTLITE_KEYS_DEBOUNCE_INTERVAL (3 * SXTLITE_KEYS_POLL_INTERVAL) ++ ++static struct mtd_partition rbsxtlite_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, ++ { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, ++ { ++ .name = "ubi", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static struct gpio_led rbsxtlite_leds_gpio[] __initdata = { ++ { ++ .name = "rb:green:user", ++ .gpio = SXTLITE_GPIO_LED_USER, ++ .active_low = 1, ++ }, ++ { ++ .name = "rb:green:led1", ++ .gpio = SXTLITE_GPIO_LED_1, ++ .active_low = 1, ++ }, ++ { ++ .name = "rb:green:led2", ++ .gpio = SXTLITE_GPIO_LED_2, ++ .active_low = 1, ++ }, ++ { ++ .name = "rb:green:led3", ++ .gpio = SXTLITE_GPIO_LED_3, ++ .active_low = 1, ++ }, ++ { ++ .name = "rb:green:led4", ++ .gpio = SXTLITE_GPIO_LED_4, ++ .active_low = 1, ++ }, ++ { ++ .name = "rb:green:led5", ++ .gpio = SXTLITE_GPIO_LED_5, ++ .active_low = 1, ++ }, ++ { ++ .name = "rb:green:power", ++ .gpio = SXTLITE_GPIO_LED_POWER, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, ++}; ++ ++static struct gpio_keys_button rbsxtlite_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = SXTLITE_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = SXTLITE_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static int __init rbsxtlite_rbinfo_init(void) ++{ ++ const struct rb_info *info; ++ ++ info = rb_init_info((void *)(KSEG1ADDR(AR71XX_SPI_BASE)), 0x10000); ++ if (!info) ++ return -EINVAL; ++ return 0; ++ ++} ++ ++void __init rbsxtlite_wlan_init(void) ++{ ++ char *art_buf; ++ u8 wlan_mac[ETH_ALEN]; ++ ++ art_buf = rb_get_wlan_data(); ++ if (art_buf == NULL) ++ return; ++ ++ ath79_init_mac(wlan_mac, ath79_mac_base, 1); ++ ath79_register_wmac(art_buf + 0x1000, wlan_mac); ++ ++ kfree(art_buf); ++} ++ ++static void rbsxtlite_nand_select_chip(int chip_no) ++{ ++ switch (chip_no) { ++ case 0: ++ gpio_set_value(SXTLITE_GPIO_NAND_NCE, 0); ++ break; ++ default: ++ gpio_set_value(SXTLITE_GPIO_NAND_NCE, 1); ++ break; ++ } ++ ndelay(500); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++static struct nand_ecclayout rbsxtlite_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++#else ++ ++static int rbsxtlite_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 8; ++ oobregion->length = 3; ++ return 0; ++ case 1: ++ oobregion->offset = 13; ++ oobregion->length = 3; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static int rbsxtlite_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = 4; ++ return 0; ++ case 1: ++ oobregion->offset = 4; ++ oobregion->length = 1; ++ return 0; ++ case 2: ++ oobregion->offset = 6; ++ oobregion->length = 2; ++ return 0; ++ case 3: ++ oobregion->offset = 11; ++ oobregion->length = 2; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops rbsxtlite_nand_ecclayout_ops = { ++ .ecc = rbsxtlite_ooblayout_ecc, ++ .free = rbsxtlite_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static int rbsxtlite_nand_scan_fixup(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct nand_chip *chip = mtd->priv; ++#endif ++ ++ if (mtd->writesize == 512) { ++ /* ++ * Use the OLD Yaffs-1 OOB layout, otherwise RouterBoot ++ * will not be able to find the kernel that we load. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ chip->ecc.layout = &rbsxtlite_nand_ecclayout; ++#else ++ mtd_set_ooblayout(mtd, &rbsxtlite_nand_ecclayout_ops); ++#endif ++ } ++ ++ return 0; ++} ++ ++void __init rbsxtlite_gpio_init(void) ++{ ++ gpio_request_one(SXTLITE_GPIO_NAND_NCE, GPIOF_OUT_INIT_HIGH, "NAND nCE"); ++} ++ ++void __init rbsxtlite_nand_init(void) ++{ ++ ath79_nfc_set_scan_fixup(rbsxtlite_nand_scan_fixup); ++ ath79_nfc_set_parts(rbsxtlite_nand_partitions, ++ ARRAY_SIZE(rbsxtlite_nand_partitions)); ++ ath79_nfc_set_select_chip(rbsxtlite_nand_select_chip); ++ ath79_nfc_set_swap_dma(true); ++ ath79_register_nfc(); ++} ++ ++ ++static void __init rbsxtlite_setup(void) ++{ ++ if(rbsxtlite_rbinfo_init()) ++ return; ++ rbsxtlite_nand_init(); ++ rbsxtlite_wlan_init(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbsxtlite_leds_gpio), ++ rbsxtlite_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, SXTLITE_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(rbsxtlite_gpio_keys), ++ rbsxtlite_gpio_keys); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* GMAC0 is left unused */ ++ ++ /* GMAC1 is connected to MAC0 on the internal switch */ ++ /* The ethernet port connects to PHY P0, which connects to MAC1 ++ on the internal switch */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ ++} ++ ++ ++MIPS_MACHINE(ATH79_MACH_RB_SXTLITE2ND, "sxt2n", "MikroTik RouterBOARD SXT Lite2", ++ rbsxtlite_setup); ++ ++MIPS_MACHINE(ATH79_MACH_RB_SXTLITE5ND, "sxt5n", "MikroTik RouterBOARD SXT Lite5", ++ rbsxtlite_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-re450.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-re450.c +new file mode 100644 +index 0000000000..991aa1c9a9 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-re450.c +@@ -0,0 +1,239 @@ ++/* ++ * TP-LINK RE355/RE450 board support ++ * ++ * Copyright (c) 2013 Gabor Juhos ++ * Copyright (c) 2016 Tal Keren ++ * Copyright (c) 2018 Henryk Heisig ++ * ++ * Based on the Qualcomm Atheros AP135/AP136 reference board support code ++ * Copyright (c) 2012 Qualcomm Atheros ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define RE450_GPIO_LED_SYSTEM 12 ++#define RE450_GPIO_LED_WLAN2G 13 ++#define RE450_GPIO_LED_WLAN5G 14 ++#define RE450_GPIO_LED_LAN_DATA 17 ++#define RE450_GPIO_LED_JUMPSTART 21 ++#define RE450_GPIO_LED_JUMPSTART_RED 22 ++#define RE450_GPIO_LED_LAN_LINK 23 ++ ++#define RE450_GPIO_BTN_RESET 18 ++#define RE450_GPIO_BTN_LED 19 ++#define RE450_GPIO_BTN_JUMPSTART 20 ++ ++#define RE450_GPIO_SMI_MDIO 1 ++#define RE450_GPIO_SMI_MDC 3 ++ ++#define RE450_LAN_PHYADDR 4 ++ ++#define RE450_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define RE450_KEYS_DEBOUNCE_INTERVAL (3 * RE450_KEYS_POLL_INTERVAL) ++ ++#define RE450_WMAC_CALDATA_OFFSET 0x1000 ++ ++static const char *tl_re450_part_probes[] = { ++ "cmdlinepart", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_re450_flash_data = { ++ .part_probes = tl_re450_part_probes, ++}; ++ ++static struct gpio_led re355_leds_gpio[] __initdata = { ++ { ++ .name = "re355:blue:power", ++ .gpio = RE450_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "re355:blue:wlan2g", ++ .gpio = RE450_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "re355:blue:wlan5g", ++ .gpio = RE450_GPIO_LED_WLAN5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "re355:blue:wps", ++ .gpio = RE450_GPIO_LED_JUMPSTART, ++ }, ++ { ++ .name = "re355:red:wps", ++ .gpio = RE450_GPIO_LED_JUMPSTART_RED, ++ }, ++ { ++ .name = "re355:green:lan_data", ++ .gpio = RE450_GPIO_LED_LAN_DATA, ++ .active_low = 1, ++ }, ++ { ++ .name = "re355:green:lan_link", ++ .gpio = RE450_GPIO_LED_LAN_LINK, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led re450_leds_gpio[] __initdata = { ++ { ++ .name = "re450:blue:power", ++ .gpio = RE450_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "re450:blue:wlan2g", ++ .gpio = RE450_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "re450:blue:wlan5g", ++ .gpio = RE450_GPIO_LED_WLAN5G, ++ .active_low = 1, ++ }, ++ { ++ .name = "re450:blue:wps", ++ .gpio = RE450_GPIO_LED_JUMPSTART, ++ }, ++ { ++ .name = "re450:red:wps", ++ .gpio = RE450_GPIO_LED_JUMPSTART_RED, ++ }, ++ { ++ .name = "re450:green:lan_data", ++ .gpio = RE450_GPIO_LED_LAN_DATA, ++ .active_low = 1, ++ }, ++ { ++ .name = "re450:green:lan_link", ++ .gpio = RE450_GPIO_LED_LAN_LINK, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button re450_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = RE450_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RE450_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = RE450_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RE450_GPIO_BTN_JUMPSTART, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Control LED button", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = RE450_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RE450_GPIO_BTN_LED, ++ .active_low = 1, ++ }, ++}; ++ ++static struct mdio_gpio_platform_data re450_mdio = { ++ .mdc = RE450_GPIO_SMI_MDC, ++ .mdio = RE450_GPIO_SMI_MDIO, ++ .phy_mask = ~BIT(RE450_LAN_PHYADDR), ++}; ++ ++static struct platform_device re450_phy_device = { ++ .name = "mdio-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &re450_mdio, ++ }, ++}; ++ ++static void __init rex5x_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f610008); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&tl_re450_flash_data); ++ ath79_register_gpio_keys_polled(-1, RE450_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(re450_gpio_keys), ++ re450_gpio_keys); ++ ++ ath79_init_mac(tmpmac, mac, -1); ++ ath79_register_wmac(art + RE450_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_register_pci(); ++ ++ /* MDIO Interface */ ++ platform_device_register(&re450_phy_device); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* GMAC0 is connected to the RGMII interface to an Atheros AR8035-A */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.mii_bus_dev = &re450_phy_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(RE450_LAN_PHYADDR); ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_eth0_pll_data.pll_100 = 0xa0000101; ++ ath79_eth0_pll_data.pll_10 = 0x80001313; ++ ath79_register_eth(0); ++} ++ ++static void __init re355_setup(void) ++{ ++ rex5x_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(re355_leds_gpio), ++ re355_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RE355, "RE355", "TP-LINK RE355", ++ re355_setup) ++ ++static void __init re450_setup(void) ++{ ++ rex5x_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(re450_leds_gpio), ++ re450_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RE450, "RE450", "TP-LINK RE450", ++ re450_setup) +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rme-eg200.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rme-eg200.c +new file mode 100644 +index 0000000000..332b0780d0 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rme-eg200.c +@@ -0,0 +1,99 @@ ++/* ++ * eTactica EG-200 board, based on 8devices Carambola2 module ++ * ++ * Copyright (C) 2015 Karl Palsson ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define RME_EG200_GPIO_LED_WLAN 0 ++#define RME_EG200_GPIO_LED_ETH0 13 ++#define RME_EG200_GPIO_LED_ETACTICA 15 ++#define RME_EG200_GPIO_LED_MODBUS 16 ++ ++#define RME_EG200_GPIO_BTN_RESTORE 11 ++ ++#define RME_EG200_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define RME_EG200_KEYS_DEBOUNCE_INTERVAL (3 * RME_EG200_KEYS_POLL_INTERVAL) ++ ++#define RME_EG200_MAC0_OFFSET 0x0000 ++#define RME_EG200_CALDATA_OFFSET 0x1000 ++#define RME_EG200_WMAC_MAC_OFFSET 0x1002 ++ ++static struct gpio_led rme_eg200_leds_gpio[] __initdata = { ++ { ++ .name = "eg200:red:wlan", ++ .gpio = RME_EG200_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "eg200:red:eth0", ++ .gpio = RME_EG200_GPIO_LED_ETH0, ++ .active_low = 1, ++ }, { ++ .name = "eg200:red:etactica", ++ .gpio = RME_EG200_GPIO_LED_ETACTICA, ++ .active_low = 0, ++ }, { ++ .name = "eg200:red:modbus", ++ .gpio = RME_EG200_GPIO_LED_MODBUS, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button rme_eg200_keys[] __initdata = { ++ { ++ .desc = "restore button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = RME_EG200_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RME_EG200_GPIO_BTN_RESTORE, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init rme_eg200_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_wmac(art + RME_EG200_CALDATA_OFFSET, ++ art + RME_EG200_WMAC_MAC_OFFSET); ++ ++ ath79_setup_ar933x_phy4_switch(true, true); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + RME_EG200_MAC0_OFFSET, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rme_eg200_leds_gpio), ++ rme_eg200_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, RME_EG200_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(rme_eg200_keys), ++ rme_eg200_keys); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RME_EG200, "RME-EG200", "eTactica EG-200", ++ rme_eg200_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rut9xx.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rut9xx.c +new file mode 100644 +index 0000000000..43a2a78c67 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rut9xx.c +@@ -0,0 +1,191 @@ ++/* ++ * Teltonika RUT900 series boards support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define RUT9XX_GPIO_LED_LAN1 14 ++#define RUT9XX_GPIO_LED_LAN2 13 ++#define RUT9XX_GPIO_LED_LAN3 22 ++#define RUT9XX_GPIO_LED_WAN 1 ++ ++#define RUT9XX_PCA9539_GPIO_BASE 32 ++#define RUT9XX_PCA9539_GPIO_SIGNAL1 (0 + RUT9XX_PCA9539_GPIO_BASE) ++#define RUT9XX_PCA9539_GPIO_SIGNAL2 (1 + RUT9XX_PCA9539_GPIO_BASE) ++#define RUT9XX_PCA9539_GPIO_SIGNAL3 (2 + RUT9XX_PCA9539_GPIO_BASE) ++#define RUT9XX_PCA9539_GPIO_SIGNAL4 (3 + RUT9XX_PCA9539_GPIO_BASE) ++#define RUT9XX_PCA9539_GPIO_SIGNAL5 (4 + RUT9XX_PCA9539_GPIO_BASE) ++#define RUT9XX_PCA9539_GPIO_STATUS_R (5 + RUT9XX_PCA9539_GPIO_BASE) ++#define RUT9XX_PCA9539_GPIO_STATUS_G (6 + RUT9XX_PCA9539_GPIO_BASE) ++ ++#define RUT9XX_GPIO_BTN_RESET 15 ++ ++#define RUT9XX_GPIO_I2C_SCK 16 ++#define RUT9XX_GPIO_I2C_SDA 17 ++ ++#define RUT9XX_GPIO_EXT_LNA0 2 ++ ++#define RUT9XX_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define RUT9XX_KEYS_POLL_INTERVAL 20 ++#define RUT9XX_KEYS_DEBOUNCE_INTERVAL (3 * RUT9XX_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led rut900_leds_gpio[] __initdata = { ++ { ++ .name = "rut900:green:lan1", ++ .gpio = RUT9XX_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "rut900:green:lan2", ++ .gpio = RUT9XX_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "rut900:green:lan3", ++ .gpio = RUT9XX_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "rut900:green:signal1", ++ .gpio = RUT9XX_PCA9539_GPIO_SIGNAL1, ++ .active_low = 0, ++ }, { ++ .name = "rut900:green:signal2", ++ .gpio = RUT9XX_PCA9539_GPIO_SIGNAL2, ++ .active_low = 0, ++ }, { ++ .name = "rut900:green:signal3", ++ .gpio = RUT9XX_PCA9539_GPIO_SIGNAL3, ++ .active_low = 0, ++ }, { ++ .name = "rut900:green:signal4", ++ .gpio = RUT9XX_PCA9539_GPIO_SIGNAL4, ++ .active_low = 0, ++ }, { ++ .name = "rut900:green:signal5", ++ .gpio = RUT9XX_PCA9539_GPIO_SIGNAL5, ++ .active_low = 0, ++ }, { ++ .name = "rut900:green:status", ++ .gpio = RUT9XX_PCA9539_GPIO_STATUS_G, ++ .active_low = 0, ++ }, { ++ .name = "rut900:green:wan", ++ .gpio = RUT9XX_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "rut900:red:status", ++ .gpio = RUT9XX_PCA9539_GPIO_STATUS_R, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button rut900_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = RUT9XX_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RUT9XX_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct i2c_gpio_platform_data rut900_i2c_gpio_data = { ++ .sda_pin = RUT9XX_GPIO_I2C_SDA, ++ .scl_pin = RUT9XX_GPIO_I2C_SCK, ++ .udelay = 10, ++}; ++ ++static struct platform_device rut900_i2c_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &rut900_i2c_gpio_data, ++ }, ++}; ++ ++static struct pca953x_platform_data rut9xx_pca9539_data = { ++ .gpio_base = RUT9XX_PCA9539_GPIO_BASE, ++ .irq_base = -1, ++}; ++ ++static struct i2c_board_info rut900_i2c_devs[] __initdata = { ++ { ++ I2C_BOARD_INFO("pca9539", 0x74), ++ .platform_data = &rut9xx_pca9539_data, ++ }, ++}; ++ ++static void __init rut900_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f030000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f020000); ++ u8 wlan_mac[ETH_ALEN]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = 0xf1; ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ platform_device_register(&rut900_i2c_device); ++ i2c_register_board_info(0, rut900_i2c_devs, ++ ARRAY_SIZE(rut900_i2c_devs)); ++ ++ /* Disable JTAG (enables GPIO0-3) */ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rut900_leds_gpio), ++ rut900_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, RUT9XX_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(rut900_gpio_keys), ++ rut900_gpio_keys); ++ ++ ath79_wmac_set_ext_lna_gpio(0, RUT9XX_GPIO_EXT_LNA0); ++ ++ ath79_init_mac(wlan_mac, mac, 2); ++ ath79_register_wmac(art + RUT9XX_WMAC_CALDATA_OFFSET, wlan_mac); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RUT9XX, "RUT900", "Teltonika RUT900", rut900_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rw2458n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rw2458n.c +new file mode 100644 +index 0000000000..bb7c2475bd +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rw2458n.c +@@ -0,0 +1,91 @@ ++/* ++ * Redwave RW2458N support ++ * ++ * Copyright (C) 2011-2013 Cezary Jackiewicz ++ * ++ * 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 "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define RW2458N_GPIO_LED_D3 1 ++#define RW2458N_GPIO_LED_D4 0 ++#define RW2458N_GPIO_LED_D5 11 ++#define RW2458N_GPIO_LED_D6 7 ++#define RW2458N_GPIO_BTN_RESET 12 ++ ++#define RW2458N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define RW2458N_KEYS_DEBOUNCE_INTERVAL (3 * RW2458N_KEYS_POLL_INTERVAL) ++ ++static struct gpio_keys_button rw2458n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = RW2458N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = RW2458N_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++#define RW2458N_WAN_PHYMASK BIT(4) ++ ++static struct gpio_led rw2458n_leds_gpio[] __initdata = { ++ { ++ .name = "rw2458n:green:d3", ++ .gpio = RW2458N_GPIO_LED_D3, ++ .active_low = 1, ++ }, { ++ .name = "rw2458n:green:d4", ++ .gpio = RW2458N_GPIO_LED_D4, ++ .active_low = 1, ++ }, { ++ .name = "rw2458n:green:d5", ++ .gpio = RW2458N_GPIO_LED_D5, ++ .active_low = 1, ++ }, { ++ .name = "rw2458n:green:d6", ++ .gpio = RW2458N_GPIO_LED_D6, ++ .active_low = 1, ++ } ++}; ++ ++static void __init rw2458n_setup(void) ++{ ++ u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac2 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(0, ~RW2458N_WAN_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(rw2458n_leds_gpio), ++ rw2458n_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, RW2458N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(rw2458n_gpio_keys), ++ rw2458n_gpio_keys); ++ ath79_register_usb(); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_RW2458N, "RW2458N", "Redwave RW2458N", ++ rw2458n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-sc1750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-sc1750.c +new file mode 100644 +index 0000000000..3a7d654b85 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-sc1750.c +@@ -0,0 +1,145 @@ ++/* ++ * Abicom International Scorpion SC1750 support. ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * Copyright (c) 2017 Conor O'Gorman ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define SC1750_GPIO_LED_POWER 11 ++#define SC1750_GPIO_LED_ERR1 12 ++#define SC1750_GPIO_LED_WLAN 13 ++#define SC1750_GPIO_LED_ERR2 14 ++#define SC1750_GPIO_LED_OK3 15 ++#define SC1750_GPIO_LED_ERR3 16 ++#define SC1750_GPIO_BTN_RESET 4 ++ ++#define SC1750_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define SC1750_KEYS_DEBOUNCE_INTERVAL (3 * SC1750_KEYS_POLL_INTERVAL) ++ ++#define SC1750_MAC0_OFFSET 0 ++#define SC1750_MAC1_OFFSET 6 ++#define SC1750_WMAC_CALDATA_OFFSET 0x1000 ++#define SC1750_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led sc1750_leds_gpio[] __initdata = { ++ { ++ .name = "sc1750:green:power", ++ .gpio = SC1750_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "sc1750:red:power", ++ .gpio = SC1750_GPIO_LED_ERR1, ++ .active_low = 1, ++ }, ++ { ++ .name = "sc1750:green:wlan", ++ .gpio = SC1750_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "sc1750:red:wlan", ++ .gpio = SC1750_GPIO_LED_ERR2, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button sc1750_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = SC1750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = SC1750_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static struct at803x_platform_data at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 0, ++ .enable_rgmii_tx_delay = 0, ++}; ++ ++static struct mdio_board_info sc1750_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 1, ++ .platform_data = &at803x_data, ++ }, ++}; ++ ++static void __init sc1750_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(sc1750_leds_gpio), ++ sc1750_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, SC1750_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(sc1750_gpio_keys), ++ sc1750_gpio_keys); ++ ++ ath79_register_usb(); ++ ath79_register_nfc(); ++ ++ ath79_register_wmac(art + SC1750_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_mdio(0, 0); ++ mdiobus_register_board_info(sc1750_mdio0_info, ++ ARRAY_SIZE(sc1750_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + SC1750_MAC0_OFFSET, 0); ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000101; ++ ath79_eth0_pll_data.pll_100 = 0xa4000101; ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = 0xF; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_SC1750, "SC1750", "Abicom SC1750", sc1750_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-sc300m.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-sc300m.c +new file mode 100644 +index 0000000000..6dd81ecd5a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-sc300m.c +@@ -0,0 +1,132 @@ ++/* ++ * Abicom International Scorpion SC300M Module support. ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * Copyright (c) 2017 Conor O'Gorman ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define SC300M_GPIO_LED_WLAN 0 ++#define SC300M_GPIO_LED_POWER 1 ++ ++#define SC300M_GPIO_BTN_RESET 17 ++ ++#define SC300M_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define SC300M_KEYS_DEBOUNCE_INTERVAL (3 * SC300M_KEYS_POLL_INTERVAL) ++ ++#define SC300M_MAC0_OFFSET 0 ++#define SC300M_MAC1_OFFSET 6 ++#define SC300M_WMAC_CALDATA_OFFSET 0x1000 ++#define SC300M_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led sc300m_leds_gpio[] __initdata = { ++ { ++ .name = "sc300m:blue:wlan", ++ .gpio = SC300M_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "sc300m:blue:power", ++ .gpio = SC300M_GPIO_LED_POWER, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button sc300m_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = SC300M_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = SC300M_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct at803x_platform_data at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 0, ++ .enable_rgmii_tx_delay = 0, ++}; ++ ++static struct mdio_board_info sc300m_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 1, ++ .platform_data = &at803x_data, ++ }, ++}; ++ ++static void __init sc300m_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(sc300m_leds_gpio), ++ sc300m_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, SC300M_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(sc300m_gpio_keys), ++ sc300m_gpio_keys); ++ ++ ath79_register_usb(); ++ ath79_register_nfc(); ++ ++ ath79_register_wmac(art + SC300M_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_mdio(0, 0); ++ mdiobus_register_board_info(sc300m_mdio0_info, ++ ARRAY_SIZE(sc300m_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + SC300M_MAC0_OFFSET, 0); ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000101; ++ ath79_eth0_pll_data.pll_100 = 0xa4000101; ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = 0xF; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_SC300M, "SC300M", "Abicom SC300M", sc300m_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-sc450.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-sc450.c +new file mode 100644 +index 0000000000..dee183e790 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-sc450.c +@@ -0,0 +1,149 @@ ++/* ++ * Abicom International Scorpion SC450 support. ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * Copyright (c) 2017 Conor O'Gorman ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define SC450_GPIO_LED_POWER 13 ++#define SC450_GPIO_LED_ERR1 14 ++#define SC450_GPIO_LED_ERR2 15 ++#define SC450_GPIO_LED_WLAN 16 ++#define SC450_GPIO_BTN_RESET 17 ++#define SC450_GPIO_WP 18 ++#define SC450_GPIO_POE 19 ++#define SC450_GPIO_RX_LOS 20 ++#define SC450_GPIO_MOD_GND 21 ++#define SC450_GPIO_MOD_SCL 22 ++#define SC450_GPIO_MOD_SDA 23 ++ ++#define SC450_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define SC450_KEYS_DEBOUNCE_INTERVAL (3 * SC450_KEYS_POLL_INTERVAL) ++ ++#define SC450_MAC0_OFFSET 0 ++#define SC450_MAC1_OFFSET 6 ++#define SC450_WMAC_CALDATA_OFFSET 0x1000 ++#define SC450_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led sc450_leds_gpio[] __initdata = { ++ { ++ .name = "sc450:green:power", ++ .gpio = SC450_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "sc450:red:power", ++ .gpio = SC450_GPIO_LED_ERR1, ++ .active_low = 1, ++ }, ++ { ++ .name = "sc450:green:wlan", ++ .gpio = SC450_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "sc450:red:wlan", ++ .gpio = SC450_GPIO_LED_ERR2, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button sc450_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = SC450_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = SC450_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct at803x_platform_data at803x_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 0, ++ .enable_rgmii_tx_delay = 0, ++}; ++ ++static struct mdio_board_info sc450_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 1, ++ .platform_data = &at803x_data, ++ }, ++}; ++ ++static void __init sc450_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(sc450_leds_gpio), ++ sc450_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, SC450_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(sc450_gpio_keys), ++ sc450_gpio_keys); ++ ++ ath79_register_usb(); ++ ath79_register_nfc(); ++ ++ ath79_register_wmac(art + SC450_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_mdio(0, 0); ++ mdiobus_register_board_info(sc450_mdio0_info, ++ ARRAY_SIZE(sc450_mdio0_info)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + SC450_MAC0_OFFSET, 0); ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000101; ++ ath79_eth0_pll_data.pll_100 = 0xa4000101; ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = 0xF; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_SC450, "SC450", "Abicom SC450", sc450_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-smart-300.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-smart-300.c +new file mode 100644 +index 0000000000..2520e960d3 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-smart-300.c +@@ -0,0 +1,135 @@ ++/* ++ * NC-LINK SMART-300 board support ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2014 Imre Kaloz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define SMART_300_GPIO_LED_WLAN 13 ++#define SMART_300_GPIO_LED_WAN 18 ++#define SMART_300_GPIO_LED_LAN4 19 ++#define SMART_300_GPIO_LED_LAN3 12 ++#define SMART_300_GPIO_LED_LAN2 21 ++#define SMART_300_GPIO_LED_LAN1 20 ++#define SMART_300_GPIO_LED_SYSTEM 15 ++#define SMART_300_GPIO_LED_POWER 14 ++ ++#define SMART_300_GPIO_BTN_RESET 17 ++#define SMART_300_GPIO_SW_RFKILL 16 ++ ++#define SMART_300_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define SMART_300_KEYS_DEBOUNCE_INTERVAL (3 * SMART_300_KEYS_POLL_INTERVAL) ++ ++#define SMART_300_GPIO_MASK 0x007fffff ++ ++static const char *smart_300_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data smart_300_flash_data = { ++ .part_probes = smart_300_part_probes, ++}; ++ ++static struct gpio_led smart_300_leds_gpio[] __initdata = { ++ { ++ .name = "nc-link:green:lan1", ++ .gpio = SMART_300_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "nc-link:green:lan2", ++ .gpio = SMART_300_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "nc-link:green:lan3", ++ .gpio = SMART_300_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "nc-link:green:lan4", ++ .gpio = SMART_300_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "nc-link:green:system", ++ .gpio = SMART_300_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "nc-link:green:wan", ++ .gpio = SMART_300_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "nc-link:green:wlan", ++ .gpio = SMART_300_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button smart_300_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = SMART_300_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = SMART_300_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init smart_300_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(smart_300_leds_gpio), ++ smart_300_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, SMART_300_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(smart_300_gpio_keys), ++ smart_300_gpio_keys); ++ ++ ath79_register_m25p80(&smart_300_flash_data); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++ ++ gpio_request(SMART_300_GPIO_LED_POWER, "power"); ++ gpio_direction_output(SMART_300_GPIO_LED_POWER, GPIOF_OUT_INIT_LOW); ++} ++ ++MIPS_MACHINE(ATH79_MACH_SMART_300, "SMART-300", "NC-LINK SMART-300", ++ smart_300_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-som9331.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-som9331.c +new file mode 100644 +index 0000000000..eef5bcedc2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-som9331.c +@@ -0,0 +1,125 @@ ++/* ++ * OpenEmbed SOM9331 board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * ++ * 5/27/2016 - Modified by Allan Nick Pedrana ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define SOM9331_GPIO_LED_WLAN 27 ++#define SOM9331_GPIO_LED_SYSTEM 0 ++#define SOM9331_GPIO_LED_2 13 ++#define SOM9331_GPIO_LED_3 14 ++#define SOM9331_GPIO_LED_5 16 ++#define SOM9331_GPIO_LED_WAN SOM9331_GPIO_LED_2 ++#define SOM9331_GPIO_LED_LAN1 SOM9331_GPIO_LED_3 ++#define SOM9331_GPIO_LED_LAN2 SOM9331_GPIO_LED_5 ++#define SOM9331_GPIO_BTN_RESET 11 ++ ++#define SOM9331_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define SOM9331_KEYS_DEBOUNCE_INTERVAL (3 * SOM9331_KEYS_POLL_INTERVAL) ++ ++static const char *som9331_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data som9331_flash_data = { ++ .part_probes = som9331_part_probes, ++}; ++ ++static struct gpio_led som9331_leds_gpio[] __initdata = { ++ { ++ .name = "som9331:red:wlan", ++ .gpio = SOM9331_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "som9331:orange:wan", ++ .gpio = SOM9331_GPIO_LED_WAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "som9331:orange:lan1", ++ .gpio = SOM9331_GPIO_LED_LAN1, ++ .active_low = 0, ++ }, ++ { ++ .name = "som9331:orange:lan2", ++ .gpio = SOM9331_GPIO_LED_LAN2, ++ .active_low = 0, ++ }, ++ { ++ .name = "som9331:blue:system", ++ .gpio = SOM9331_GPIO_LED_SYSTEM, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button som9331_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = SOM9331_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = SOM9331_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static void __init som9331_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_setup_ar933x_phy4_switch(true, true); ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_m25p80(&som9331_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(som9331_leds_gpio), ++ som9331_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, SOM9331_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(som9331_gpio_keys), ++ som9331_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_SOM9331, "SOM9331", "OpenEmbed SOM9331", som9331_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-sr3200.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-sr3200.c +new file mode 100644 +index 0000000000..72d46c0c47 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-sr3200.c +@@ -0,0 +1,187 @@ ++/* ++ * Support for YunCore SR3200 and XD3200 boards ++ * ++ * Copyright (C) 2016 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define SR3200_XD3200_GPIO_LED_SYSTEM 1 ++#define SR3200_XD3200_GPIO_LED_WLAN2G 19 ++ ++#define SR3200_XD3200_GPIO_BTN_RESET 2 ++ ++#define SR3200_XD3200_KEYS_POLL_INTERVAL 20 ++#define SR3200_XD3200_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * SR3200_XD3200_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led xd3200_leds_gpio[] __initdata = { ++ { ++ .name = "xd3200:green:system", ++ .gpio = SR3200_XD3200_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "xd3200:blue:wlan2g", ++ .gpio = SR3200_XD3200_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led sr3200_leds_gpio[] __initdata = { ++ { ++ .name = "sr3200:green:system", ++ .gpio = SR3200_XD3200_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "sr3200:green:wlan2g", ++ .gpio = SR3200_XD3200_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button sr3200_xd3200_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = SR3200_XD3200_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = SR3200_XD3200_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info sr3200_leds_qca833x[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "sr3200:green:lan1"), ++ AR8327_LED_INFO(PHY1_0, HW, "sr3200:green:lan2"), ++ AR8327_LED_INFO(PHY2_0, HW, "sr3200:green:lan3"), ++ AR8327_LED_INFO(PHY3_0, HW, "sr3200:green:lan4"), ++ AR8327_LED_INFO(PHY4_0, HW, "sr3200:green:wan"), ++}; ++ ++static const struct ar8327_led_info xd3200_leds_qca833x[] = { ++ AR8327_LED_INFO(PHY1_0, HW, "xd3200:green:lan"), ++ AR8327_LED_INFO(PHY2_0, HW, "xd3200:green:wan"), ++}; ++ ++/* Blink rate: 1 Gbps -> 8 hz, 100 Mbs -> 4 Hz, 10 Mbps -> 2 Hz */ ++static struct ar8327_led_cfg sr3200_xd3200_qca833x_led_cfg = { ++ .led_ctrl0 = 0xcf37cf37, ++ .led_ctrl1 = 0xcf37cf37, ++ .led_ctrl2 = 0xcf37cf37, ++ .led_ctrl3 = 0x0, ++ .open_drain = true, ++}; ++ ++static struct ar8327_pad_cfg sr3200_xd3200_qca833x_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data sr3200_xd3200_qca833x_data = { ++ .pad0_cfg = &sr3200_xd3200_qca833x_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &sr3200_xd3200_qca833x_led_cfg, ++}; ++ ++static struct mdio_board_info sr3200_xd3200_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &sr3200_xd3200_qca833x_data, ++ }, ++}; ++ ++static void __init sr3200_xd3200_common_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(sr3200_xd3200_mdio0_info, ++ ARRAY_SIZE(sr3200_xd3200_mdio0_info)); ++ ++ /* GMAC0 is connected to QCA8334/QCA8337N switch */ ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(mac + 0x1000, NULL); ++ ++ ap91_pci_init(mac + 0x5000, NULL); ++ ++ ath79_gpio_direction_select(SR3200_XD3200_GPIO_LED_SYSTEM, true); ++ ath79_gpio_direction_select(SR3200_XD3200_GPIO_LED_WLAN2G, true); ++ ++ /* Mute LEDs on boot */ ++ gpio_set_value(SR3200_XD3200_GPIO_LED_SYSTEM, 1); ++ gpio_set_value(SR3200_XD3200_GPIO_LED_WLAN2G, 1); ++ ++ ath79_gpio_output_select(SR3200_XD3200_GPIO_LED_SYSTEM, 0); ++ ath79_gpio_output_select(SR3200_XD3200_GPIO_LED_WLAN2G, 0); ++ ++ ath79_register_gpio_keys_polled(-1, SR3200_XD3200_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(sr3200_xd3200_gpio_keys), ++ sr3200_xd3200_gpio_keys); ++} ++ ++static void __init sr3200_setup(void) ++{ ++ sr3200_xd3200_qca833x_data.leds = sr3200_leds_qca833x; ++ sr3200_xd3200_qca833x_data.num_leds = ARRAY_SIZE(sr3200_leds_qca833x); ++ ++ sr3200_xd3200_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(sr3200_leds_gpio), ++ sr3200_leds_gpio); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_SR3200, "SR3200", "YunCore SR3200", sr3200_setup); ++ ++static void __init xd3200_setup(void) ++{ ++ sr3200_xd3200_qca833x_data.leds = xd3200_leds_qca833x; ++ sr3200_xd3200_qca833x_data.num_leds = ARRAY_SIZE(xd3200_leds_qca833x); ++ ++ sr3200_xd3200_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(xd3200_leds_gpio), ++ xd3200_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_XD3200, "XD3200", "YunCore XD3200", xd3200_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-t830.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-t830.c +new file mode 100644 +index 0000000000..ffdb2ca533 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-t830.c +@@ -0,0 +1,127 @@ ++/* ++ * YunCore T830 board support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define T830_GPIO_LED_LAN1 16 ++#define T830_GPIO_LED_LAN2 15 ++#define T830_GPIO_LED_LAN3 14 ++#define T830_GPIO_LED_LAN4 11 ++#define T830_GPIO_LED_USB 13 ++#define T830_GPIO_LED_WAN 4 ++#define T830_GPIO_LED_WLAN 12 ++ ++#define T830_GPIO_BTN_RESET 17 ++ ++#define T830_KEYS_POLL_INTERVAL 20 /* msec */ ++#define T830_KEYS_DEBOUNCE_INTERVAL (3 * T830_KEYS_POLL_INTERVAL) ++ ++#define T830_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led t830_gpio_leds[] __initdata = { ++ { ++ .name = "t830:green:lan1", ++ .gpio = T830_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "t830:green:lan2", ++ .gpio = T830_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "t830:green:lan3", ++ .gpio = T830_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "t830:green:lan4", ++ .gpio = T830_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "t830:green:usb", ++ .gpio = T830_GPIO_LED_USB, ++ .active_low = 1, ++ .default_state = LEDS_GPIO_DEFSTATE_KEEP, ++ }, { ++ .name = "t830:green:wan", ++ .gpio = T830_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "t830:green:wlan", ++ .gpio = T830_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button t830_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = T830_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = T830_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init t830_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac + 6, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, ++ AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(t830_gpio_leds), ++ t830_gpio_leds); ++ ++ ath79_register_gpio_keys_polled(-1, T830_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(t830_gpio_keys), ++ t830_gpio_keys); ++ ++ ath79_register_usb(); ++ ath79_register_wmac(art, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_T830, "T830", "YunCore T830", t830_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tellstick-znet-lite.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tellstick-znet-lite.c +new file mode 100644 +index 0000000000..0950d9a99d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tellstick-znet-lite.c +@@ -0,0 +1,129 @@ ++/* ++ * Telldus TellStick ZNet Lite board support ++ * ++ * Copyright (C) 2016 Micke Prag ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TELLSTICK_GPIO_LED_SYSTEM 27 ++#define TELLSTICK_GPIO_LED_BLUE 0 ++#define TELLSTICK_GPIO_LED_RED 14 ++#define TELLSTICK_GPIO_LED_GREEN 15 ++#define TELLSTICK_GPIO_LED_LAN_GREEN 16 ++#define TELLSTICK_GPIO_LED_LAN_ORANGE 17 ++ ++#define TELLSTICK_GPIO_BTN_RESET 11 ++ ++#define TELLSTICK_GPIO_RF433_RESET 13 ++ ++#define TELLSTICK_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TELLSTICK_KEYS_DEBOUNCE_INTERVAL (3 * TELLSTICK_KEYS_POLL_INTERVAL) ++ ++static const char *tellstick_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tellstick_flash_data = { ++ .part_probes = tellstick_part_probes, ++}; ++ ++static struct gpio_led tellstick_leds_gpio[] __initdata = { ++ { ++ .name = "tellstick:white:system", ++ .gpio = TELLSTICK_GPIO_LED_SYSTEM, ++ .active_low = 0, ++ }, ++ { ++ .name = "tellstick:blue:status", ++ .gpio = TELLSTICK_GPIO_LED_BLUE, ++ .active_low = 0, ++ }, ++ { ++ .name = "tellstick:red:status", ++ .gpio = TELLSTICK_GPIO_LED_RED, ++ .active_low = 0, ++ }, ++ { ++ .name = "tellstick:green:status", ++ .gpio = TELLSTICK_GPIO_LED_GREEN, ++ .active_low = 0, ++ }, ++ { ++ .name = "tellstick:green:lan", ++ .gpio = TELLSTICK_GPIO_LED_LAN_GREEN, ++ .active_low = 0, ++ }, ++ { ++ .name = "tellstick:orange:lan", ++ .gpio = TELLSTICK_GPIO_LED_LAN_ORANGE, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tellstick_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TELLSTICK_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TELLSTICK_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static void __init tellstick_znet_lite_setup(void) ++{ ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[ETH_ALEN]; ++ memcpy(&mac, (u8 *) KSEG1ADDR(0x1f01fc00), sizeof(mac)); ++ ++ ath79_gpio_function_disable( ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN ++ ); ++ ++ ath79_register_m25p80(&tellstick_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tellstick_leds_gpio), ++ tellstick_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TELLSTICK_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tellstick_gpio_keys), ++ tellstick_gpio_keys); ++ ++ gpio_request_one(TELLSTICK_GPIO_RF433_RESET, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "rf433 reset"); ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, (u8 *)mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ++ // wlan0 mac needs to be different then eth0 ++ mac[3] += 1; ++ ath79_register_wmac(ee, (u8 *)mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TELLSTICK_ZNET_LITE, "TELLSTICK-ZNET-LITE", "Telldus TellStick ZNet Lite", ++ tellstick_znet_lite_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-632brp.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-632brp.c +new file mode 100644 +index 0000000000..855664e562 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-632brp.c +@@ -0,0 +1,111 @@ ++/* ++ * TrendNET TEW-632BRP board support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define TEW_632BRP_GPIO_LED_STATUS 1 ++#define TEW_632BRP_GPIO_LED_WPS 3 ++#define TEW_632BRP_GPIO_LED_WLAN 6 ++#define TEW_632BRP_GPIO_BTN_WPS 12 ++#define TEW_632BRP_GPIO_BTN_RESET 21 ++ ++#define TEW_632BRP_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TEW_632BRP_KEYS_DEBOUNCE_INTERVAL (3 * TEW_632BRP_KEYS_POLL_INTERVAL) ++ ++#define TEW_632BRP_CONFIG_ADDR 0x1f020000 ++#define TEW_632BRP_CONFIG_SIZE 0x10000 ++ ++static struct gpio_led tew_632brp_leds_gpio[] __initdata = { ++ { ++ .name = "tew-632brp:green:status", ++ .gpio = TEW_632BRP_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "tew-632brp:blue:wps", ++ .gpio = TEW_632BRP_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "tew-632brp:green:wlan", ++ .gpio = TEW_632BRP_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tew_632brp_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TEW_632BRP_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW_632BRP_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TEW_632BRP_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW_632BRP_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++#define TEW_632BRP_LAN_PHYMASK BIT(0) ++#define TEW_632BRP_WAN_PHYMASK BIT(4) ++#define TEW_632BRP_MDIO_MASK (~(TEW_632BRP_LAN_PHYMASK | \ ++ TEW_632BRP_WAN_PHYMASK)) ++ ++static void __init tew_632brp_setup(void) ++{ ++ const char *config = (char *) KSEG1ADDR(TEW_632BRP_CONFIG_ADDR); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[6]; ++ u8 *wlan_mac = NULL; ++ ++ if (ath79_nvram_parse_mac_addr(config, TEW_632BRP_CONFIG_SIZE, ++ "lan_mac=", mac) == 0) { ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ wlan_mac = mac; ++ } ++ ++ ath79_register_mdio(0, TEW_632BRP_MDIO_MASK); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.phy_mask = TEW_632BRP_LAN_PHYMASK; ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = TEW_632BRP_WAN_PHYMASK; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tew_632brp_leds_gpio), ++ tew_632brp_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TEW_632BRP_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tew_632brp_gpio_keys), ++ tew_632brp_gpio_keys); ++ ++ ath79_register_wmac(eeprom, wlan_mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TEW_632BRP, "TEW-632BRP", "TRENDnet TEW-632BRP", ++ tew_632brp_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-673gru.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-673gru.c +new file mode 100644 +index 0000000000..80a5443c70 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-673gru.c +@@ -0,0 +1,198 @@ ++/* ++ * TRENDnet TEW-673GRU board support ++ * ++ * Copyright (C) 2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define TEW673GRU_GPIO_LCD_SCK 0 ++#define TEW673GRU_GPIO_LCD_MOSI 1 ++#define TEW673GRU_GPIO_LCD_MISO 2 ++#define TEW673GRU_GPIO_LCD_CS 6 ++ ++#define TEW673GRU_GPIO_LED_WPS 9 ++ ++#define TEW673GRU_GPIO_BTN_RESET 3 ++#define TEW673GRU_GPIO_BTN_WPS 8 ++ ++#define TEW673GRU_GPIO_RTL8366_SDA 5 ++#define TEW673GRU_GPIO_RTL8366_SCK 7 ++ ++#define TEW673GRU_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TEW673GRU_KEYS_DEBOUNCE_INTERVAL (3 * TEW673GRU_KEYS_POLL_INTERVAL) ++ ++#define TEW673GRU_CAL0_OFFSET 0x1000 ++#define TEW673GRU_CAL1_OFFSET 0x5000 ++#define TEW673GRU_MAC0_OFFSET 0xffa0 ++#define TEW673GRU_MAC1_OFFSET 0xffb4 ++ ++#define TEW673GRU_CAL_LOCATION_0 0x1f660000 ++#define TEW673GRU_CAL_LOCATION_1 0x1f7f0000 ++ ++static struct gpio_led tew673gru_leds_gpio[] __initdata = { ++ { ++ .name = "trendnet:blue:wps", ++ .gpio = TEW673GRU_GPIO_LED_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tew673gru_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TEW673GRU_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW673GRU_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TEW673GRU_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW673GRU_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct rtl8366_initval tew673gru_rtl8366s_initvals[] = { ++ { .reg = 0x06, .val = 0x0108 }, ++}; ++ ++static struct rtl8366_platform_data tew673gru_rtl8366s_data = { ++ .gpio_sda = TEW673GRU_GPIO_RTL8366_SDA, ++ .gpio_sck = TEW673GRU_GPIO_RTL8366_SCK, ++ .num_initvals = ARRAY_SIZE(tew673gru_rtl8366s_initvals), ++ .initvals = tew673gru_rtl8366s_initvals, ++}; ++ ++static struct platform_device tew673gru_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &tew673gru_rtl8366s_data, ++ } ++}; ++ ++static struct spi_board_info tew673gru_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 400000, ++ .modalias = "spidev", ++ .mode = SPI_MODE_2, ++ .controller_data = (void *) TEW673GRU_GPIO_LCD_CS, ++ }, ++}; ++ ++static struct spi_gpio_platform_data tew673gru_spi_data = { ++ .sck = TEW673GRU_GPIO_LCD_SCK, ++ .miso = TEW673GRU_GPIO_LCD_MISO, ++ .mosi = TEW673GRU_GPIO_LCD_MOSI, ++ .num_chipselect = 1, ++}; ++ ++static struct platform_device tew673gru_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &tew673gru_spi_data, ++ }, ++}; ++ ++static bool __init tew673gru_is_caldata_valid(u8 *p) ++{ ++ u16 *magic0, *magic1; ++ ++ magic0 = (u16 *)(p + TEW673GRU_CAL0_OFFSET); ++ magic1 = (u16 *)(p + TEW673GRU_CAL1_OFFSET); ++ ++ return (*magic0 == 0xa55a && *magic1 == 0xa55a); ++} ++ ++static void __init tew673gru_wlan_init(void) ++{ ++ u8 mac1[ETH_ALEN], mac2[ETH_ALEN]; ++ u8 *caldata; ++ ++ caldata = (u8 *) KSEG1ADDR(TEW673GRU_CAL_LOCATION_0); ++ if (!tew673gru_is_caldata_valid(caldata)) { ++ caldata = (u8 *)KSEG1ADDR(TEW673GRU_CAL_LOCATION_1); ++ if (!tew673gru_is_caldata_valid(caldata)) { ++ pr_err("no calibration data found\n"); ++ return; ++ } ++ } ++ ++ ath79_parse_ascii_mac(caldata + TEW673GRU_MAC0_OFFSET, mac1); ++ ath79_parse_ascii_mac(caldata + TEW673GRU_MAC1_OFFSET, mac2); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 2); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 3); ++ ++ ap9x_pci_setup_wmac_led_pin(0, 5); ++ ap9x_pci_setup_wmac_led_pin(1, 5); ++ ++ ap94_pci_init(caldata + TEW673GRU_CAL0_OFFSET, mac1, ++ caldata + TEW673GRU_CAL1_OFFSET, mac2); ++} ++ ++static void __init tew673gru_setup(void) ++{ ++ tew673gru_wlan_init(); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_eth0_data.mii_bus_dev = &tew673gru_rtl8366s_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_pll_data.pll_1000 = 0x11110000; ++ ++ ath79_eth1_data.mii_bus_dev = &tew673gru_rtl8366s_device.dev; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ath79_eth1_pll_data.pll_1000 = 0x11110000; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tew673gru_leds_gpio), ++ tew673gru_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TEW673GRU_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tew673gru_gpio_keys), ++ tew673gru_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ platform_device_register(&tew673gru_rtl8366s_device); ++ ++ spi_register_board_info(tew673gru_spi_info, ++ ARRAY_SIZE(tew673gru_spi_info)); ++ platform_device_register(&tew673gru_spi_device); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TEW_673GRU, "TEW-673GRU", "TRENDnet TEW-673GRU", ++ tew673gru_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-712br.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-712br.c +new file mode 100644 +index 0000000000..304b994887 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-712br.c +@@ -0,0 +1,153 @@ ++/* ++ * TRENDnet TEW-712BR board support ++ * ++ * Copyright (C) 2012 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. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TEW_712BR_GPIO_BTN_WPS 11 ++#define TEW_712BR_GPIO_BTN_RESET 12 ++ ++#define TEW_712BR_GPIO_LED_LAN1 13 ++#define TEW_712BR_GPIO_LED_LAN2 14 ++#define TEW_712BR_GPIO_LED_LAN3 15 ++#define TEW_712BR_GPIO_LED_LAN4 16 ++#define TEW_712BR_GPIO_LED_POWER_GREEN 20 ++#define TEW_712BR_GPIO_LED_POWER_ORANGE 27 ++#define TEW_712BR_GPIO_LED_WAN_GREEN 17 ++#define TEW_712BR_GPIO_LED_WAN_ORANGE 23 ++#define TEW_712BR_GPIO_LED_WLAN 0 ++#define TEW_712BR_GPIO_LED_WPS 26 ++ ++#define TEW_712BR_GPIO_WAN_LED_ENABLE 1 ++ ++#define TEW_712BR_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TEW_712BR_KEYS_DEBOUNCE_INTERVAL (3 * TEW_712BR_KEYS_POLL_INTERVAL) ++ ++#define TEW_712BR_ART_ADDRESS 0x1f010000 ++#define TEW_712BR_CALDATA_OFFSET 0x1000 ++ ++#define TEW_712BR_MAC_PART_ADDRESS 0x1f020000 ++#define TEW_712BR_LAN_MAC_OFFSET 0x04 ++#define TEW_712BR_WAN_MAC_OFFSET 0x16 ++ ++static struct gpio_led tew_712br_leds_gpio[] __initdata = { ++ { ++ .name = "trendnet:green:lan1", ++ .gpio = TEW_712BR_GPIO_LED_LAN1, ++ .active_low = 0, ++ }, { ++ .name = "trendnet:green:lan2", ++ .gpio = TEW_712BR_GPIO_LED_LAN2, ++ .active_low = 0, ++ }, { ++ .name = "trendnet:green:lan3", ++ .gpio = TEW_712BR_GPIO_LED_LAN3, ++ .active_low = 0, ++ }, { ++ .name = "trendnet:green:lan4", ++ .gpio = TEW_712BR_GPIO_LED_LAN4, ++ .active_low = 0, ++ }, { ++ .name = "trendnet:blue:wps", ++ .gpio = TEW_712BR_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "trendnet:green:power", ++ .gpio = TEW_712BR_GPIO_LED_POWER_GREEN, ++ .active_low = 0, ++ }, { ++ .name = "trendnet:orange:power", ++ .gpio = TEW_712BR_GPIO_LED_POWER_ORANGE, ++ .active_low = 0, ++ }, { ++ .name = "trendnet:green:wan", ++ .gpio = TEW_712BR_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "trendnet:orange:wan", ++ .gpio = TEW_712BR_GPIO_LED_WAN_ORANGE, ++ .active_low = 0, ++ }, { ++ .name = "trendnet:green:wlan", ++ .gpio = TEW_712BR_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tew_712br_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TEW_712BR_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW_712BR_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TEW_712BR_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW_712BR_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init tew_712br_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(TEW_712BR_ART_ADDRESS); ++ u8 *mac = (u8 *) KSEG1ADDR(TEW_712BR_MAC_PART_ADDRESS); ++ u8 lan_mac[ETH_ALEN]; ++ u8 wan_mac[ETH_ALEN]; ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ gpio_request_one(TEW_712BR_GPIO_WAN_LED_ENABLE, ++ GPIOF_OUT_INIT_LOW, "WAN LED enable"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tew_712br_leds_gpio), ++ tew_712br_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TEW_712BR_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tew_712br_gpio_keys), ++ tew_712br_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_parse_ascii_mac(mac + TEW_712BR_LAN_MAC_OFFSET, lan_mac); ++ ath79_parse_ascii_mac(mac + TEW_712BR_WAN_MAC_OFFSET, wan_mac); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, wan_mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, lan_mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art + TEW_712BR_CALDATA_OFFSET, wan_mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TEW_712BR, "TEW-712BR", ++ "TRENDnet TEW-712BR", tew_712br_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-732br.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-732br.c +new file mode 100644 +index 0000000000..1f26f6f4b0 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-732br.c +@@ -0,0 +1,127 @@ ++/* ++ * TRENDnet TEW-732BR board support ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TEW_732BR_GPIO_BTN_WPS 16 ++#define TEW_732BR_GPIO_BTN_RESET 17 ++ ++#define TEW_732BR_GPIO_LED_POWER_GREEN 4 ++#define TEW_732BR_GPIO_LED_POWER_AMBER 14 ++#define TEW_732BR_GPIO_LED_PLANET_GREEN 12 ++#define TEW_732BR_GPIO_LED_PLANET_AMBER 22 ++ ++#define TEW_732BR_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TEW_732BR_KEYS_DEBOUNCE_INTERVAL (3 * TEW_732BR_KEYS_POLL_INTERVAL) ++ ++#define TEW_732BR_ART_ADDRESS 0x1fff0000 ++#define TEW_732BR_CALDATA_OFFSET 0x1000 ++#define TEW_732BR_LAN_MAC_OFFSET 0xffa0 ++#define TEW_732BR_WAN_MAC_OFFSET 0xffb4 ++ ++static struct gpio_led tew_732br_leds_gpio[] __initdata = { ++ { ++ .name = "trendnet:green:power", ++ .gpio = TEW_732BR_GPIO_LED_POWER_GREEN, ++ .active_low = 0, ++ }, ++ { ++ .name = "trendnet:amber:power", ++ .gpio = TEW_732BR_GPIO_LED_POWER_AMBER, ++ .active_low = 0, ++ }, ++ { ++ .name = "trendnet:green:wan", ++ .gpio = TEW_732BR_GPIO_LED_PLANET_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "trendnet:amber:wan", ++ .gpio = TEW_732BR_GPIO_LED_PLANET_AMBER, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tew_732br_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TEW_732BR_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW_732BR_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TEW_732BR_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW_732BR_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init tew_732br_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(TEW_732BR_ART_ADDRESS); ++ u8 lan_mac[ETH_ALEN]; ++ u8 wan_mac[ETH_ALEN]; ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tew_732br_leds_gpio), ++ tew_732br_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TEW_732BR_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tew_732br_gpio_keys), ++ tew_732br_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_parse_ascii_mac(art + TEW_732BR_LAN_MAC_OFFSET, lan_mac); ++ ath79_parse_ascii_mac(art + TEW_732BR_WAN_MAC_OFFSET, wan_mac); ++ ++ ath79_register_wmac(art + TEW_732BR_CALDATA_OFFSET, lan_mac); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ /* LAN: GMAC1 is connected to the internal switch */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, lan_mac, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ++ ath79_register_eth(1); ++ ++ /* WAN: GMAC0 is connected to the PHY4 of the internal switch */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, wan_mac, 0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TEW_732BR, "TEW-732BR", "TRENDnet TEW-732BR", ++ tew_732br_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-823dru.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-823dru.c +new file mode 100644 +index 0000000000..e631828a65 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tew-823dru.c +@@ -0,0 +1,181 @@ ++/* ++ * TRENDnet TEW-823DRU board support ++ * ++ * Copyright (C) 2015 Cezary Jackiewicz ++ * Copyright (C) 2014 Gabor Juhos ++ * Copyright (C) 2014 Imre Kaloz ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TEW_823DRU_GPIO_LED_POWER_ORANGE 14 ++#define TEW_823DRU_GPIO_LED_POWER_GREEN 19 ++#define TEW_823DRU_GPIO_LED_PLANET_GREEN 22 ++#define TEW_823DRU_GPIO_LED_PLANET_ORANGE 23 ++ ++#define TEW_823DRU_GPIO_BTN_WPS 16 ++#define TEW_823DRU_GPIO_BTN_RESET 17 ++ ++#define TEW_823DRU_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TEW_823DRU_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * TEW_823DRU_KEYS_POLL_INTERVAL) ++ ++#define TEW_823DRU_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define TEW_823DRU_LAN_MAC_OFFSET 0x04 ++#define TEW_823DRU_WAN_MAC_OFFSET 0x18 ++ ++static struct gpio_led tew_823dru_leds_gpio[] __initdata = { ++ { ++ .name = "trendnet:green:power", ++ .gpio = TEW_823DRU_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "trendnet:orange:power", ++ .gpio = TEW_823DRU_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ }, ++ { ++ .name = "trendnet:green:planet", ++ .gpio = TEW_823DRU_GPIO_LED_PLANET_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "trendnet:orange:planet", ++ .gpio = TEW_823DRU_GPIO_LED_PLANET_ORANGE, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tew_823dru_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TEW_823DRU_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW_823DRU_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TEW_823DRU_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TEW_823DRU_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++/* GMAC0 of the AR8327 switch is connected to the QCA9558 SoC via SGMII */ ++static struct ar8327_pad_cfg tew_823dru_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++/* GMAC6 of the AR8327 switch is connected to the QCA9558 SoC via RGMII */ ++static struct ar8327_pad_cfg tew_823dru_ar8327_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data tew_823dru_ar8327_data = { ++ .pad0_cfg = &tew_823dru_ar8327_pad0_cfg, ++ .pad6_cfg = &tew_823dru_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info tew_823dru_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &tew_823dru_ar8327_data, ++ }, ++}; ++ ++static void __init tew_823dru_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1ffe0000); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 lan_mac[ETH_ALEN]; ++ u8 wan_mac[ETH_ALEN]; ++ ++ ath79_parse_ascii_mac(mac + TEW_823DRU_LAN_MAC_OFFSET, lan_mac); ++ ath79_parse_ascii_mac(mac + TEW_823DRU_WAN_MAC_OFFSET, wan_mac); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tew_823dru_leds_gpio), ++ tew_823dru_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TEW_823DRU_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tew_823dru_gpio_keys), ++ tew_823dru_gpio_keys); ++ ++ ath79_register_wmac(art + TEW_823DRU_WMAC_CALDATA_OFFSET, lan_mac); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, lan_mac, 0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, wan_mac, 0); ++ ++ ++ mdiobus_register_board_info(tew_823dru_mdio0_info, ++ ARRAY_SIZE(tew_823dru_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TEW_823DRU, "TEW-823DRU", "TRENDnet TEW-823DRU", ++ tew_823dru_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr11u.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr11u.c +new file mode 100644 +index 0000000000..74ccf639e0 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr11u.c +@@ -0,0 +1,183 @@ ++/* ++ * TP-LINK TL-MR11U/TL-MR3040 board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_MR11U_GPIO_LED_3G 27 ++#define TL_MR11U_GPIO_LED_WLAN 26 ++#define TL_MR11U_GPIO_LED_LAN 17 ++ ++#define TL_MR11U_GPIO_BTN_WPS 20 ++#define TL_MR11U_GPIO_BTN_RESET 11 ++ ++#define TL_MR11U_GPIO_USB_POWER 8 ++#define TL_MR3040_GPIO_USB_POWER 18 ++ ++#define TL_MR3040_V2_GPIO_BTN_SW1 19 ++#define TL_MR3040_V2_GPIO_BTN_SW2 20 ++ ++#define TL_MR11U_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_MR11U_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR11U_KEYS_POLL_INTERVAL) ++ ++static const char *tl_mr11u_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_mr11u_flash_data = { ++ .part_probes = tl_mr11u_part_probes, ++}; ++ ++static struct gpio_led tl_mr11u_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:3g", ++ .gpio = TL_MR11U_GPIO_LED_3G, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_MR11U_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan", ++ .gpio = TL_MR11U_GPIO_LED_LAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_mr11u_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_MR11U_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR11U_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_MR11U_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR11U_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tl_mr3040_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_MR11U_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR11U_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++ { ++ .desc = "sw1", ++ .type = EV_SW, ++ .code = BTN_0, ++ .debounce_interval = TL_MR11U_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3040_V2_GPIO_BTN_SW1, ++ .active_low = 0, ++ }, ++ { ++ .desc = "sw2", ++ .type = EV_SW, ++ .code = BTN_1, ++ .debounce_interval = TL_MR11U_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3040_V2_GPIO_BTN_SW2, ++ .active_low = 0, ++ } ++}; ++ ++static void __init common_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* Disable hardware control LAN1 and LAN2 LEDs, enabling GPIO14 and GPIO15 */ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_m25p80(&tl_mr11u_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_mr11u_leds_gpio), ++ tl_mr11u_leds_gpio); ++ ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init tl_mr11u_setup(void) ++{ ++ common_setup(); ++ ++ ath79_register_gpio_keys_polled(-1, TL_MR11U_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_mr11u_gpio_keys), ++ tl_mr11u_gpio_keys); ++ gpio_request_one(TL_MR11U_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR11U, "TL-MR11U", "TP-LINK TL-MR11U", ++ tl_mr11u_setup); ++ ++static void __init tl_mr3040_setup(void) ++{ ++ common_setup(); ++ ++ ath79_register_gpio_keys_polled(-1, TL_MR11U_KEYS_POLL_INTERVAL, ++ 1, tl_mr11u_gpio_keys); ++ gpio_request_one(TL_MR3040_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR3040, "TL-MR3040", "TP-LINK TL-MR3040", ++ tl_mr3040_setup); ++ ++static void __init tl_mr3040_v2_setup(void) ++{ ++ common_setup(); ++ ++ ath79_register_gpio_keys_polled(-1, TL_MR11U_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_mr3040_v2_gpio_keys), ++ tl_mr3040_v2_gpio_keys); ++ gpio_request_one(TL_MR3040_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR3040_V2, "TL-MR3040-v2", "TP-LINK TL-MR3040 v2", ++ tl_mr3040_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr13u.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr13u.c +new file mode 100644 +index 0000000000..84b6937849 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr13u.c +@@ -0,0 +1,107 @@ ++/* ++ * TP-LINK TL-MR13U board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_MR13U_GPIO_LED_SYSTEM 27 ++ ++#define TL_MR13U_GPIO_BTN_RESET 11 ++#define TL_MR13U_GPIO_BTN_SW1 6 ++#define TL_MR13U_GPIO_BTN_SW2 7 ++ ++#define TL_MR13U_GPIO_USB_POWER 18 ++ ++#define TL_MR13U_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_MR13U_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR13U_KEYS_POLL_INTERVAL) ++ ++static const char *tl_mr13u_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_mr13u_flash_data = { ++ .part_probes = tl_mr13u_part_probes, ++}; ++ ++static struct gpio_led tl_mr13u_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:system", ++ .gpio = TL_MR13U_GPIO_LED_SYSTEM, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tl_mr13u_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_MR13U_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR13U_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++ { ++ .desc = "sw1", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = TL_MR13U_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR13U_GPIO_BTN_SW1, ++ .active_low = 0, ++ }, ++ { ++ .desc = "sw2", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = TL_MR13U_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR13U_GPIO_BTN_SW2, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init tl_mr13u_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_m25p80(&tl_mr13u_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_mr13u_leds_gpio), ++ tl_mr13u_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_MR13U_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_mr13u_gpio_keys), ++ tl_mr13u_gpio_keys); ++ ++ gpio_request_one(TL_MR13U_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR13U, "TL-MR13U", "TP-LINK TL-MR13U v1", ++ tl_mr13u_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3020.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3020.c +new file mode 100644 +index 0000000000..e3b4087eff +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3020.c +@@ -0,0 +1,126 @@ ++/* ++ * TP-LINK TL-MR3020 board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_MR3020_GPIO_LED_3G 27 ++#define TL_MR3020_GPIO_LED_WLAN 0 ++#define TL_MR3020_GPIO_LED_LAN 17 ++#define TL_MR3020_GPIO_LED_WPS 26 ++ ++#define TL_MR3020_GPIO_BTN_WPS 11 ++#define TL_MR3020_GPIO_BTN_SW1 18 ++#define TL_MR3020_GPIO_BTN_SW2 20 ++ ++#define TL_MR3020_GPIO_USB_POWER 8 ++ ++#define TL_MR3020_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_MR3020_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR3020_KEYS_POLL_INTERVAL) ++ ++static const char *tl_mr3020_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_mr3020_flash_data = { ++ .part_probes = tl_mr3020_part_probes, ++}; ++ ++static struct gpio_led tl_mr3020_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:3g", ++ .gpio = TL_MR3020_GPIO_LED_3G, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_MR3020_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "tp-link:green:lan", ++ .gpio = TL_MR3020_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wps", ++ .gpio = TL_MR3020_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_mr3020_gpio_keys[] __initdata = { ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_MR3020_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3020_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, ++ { ++ .desc = "sw1", ++ .type = EV_SW, ++ .code = BTN_0, ++ .debounce_interval = TL_MR3020_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3020_GPIO_BTN_SW1, ++ .active_low = 0, ++ }, ++ { ++ .desc = "sw2", ++ .type = EV_SW, ++ .code = BTN_1, ++ .debounce_interval = TL_MR3020_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3020_GPIO_BTN_SW2, ++ .active_low = 0, ++ } ++}; ++ ++static void __init tl_mr3020_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_m25p80(&tl_mr3020_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_mr3020_leds_gpio), ++ tl_mr3020_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_MR3020_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_mr3020_gpio_keys), ++ tl_mr3020_gpio_keys); ++ ++ gpio_request_one(TL_MR3020_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR3020, "TL-MR3020", "TP-LINK TL-MR3020", ++ tl_mr3020_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c +new file mode 100644 +index 0000000000..5924ac5048 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c +@@ -0,0 +1,147 @@ ++/* ++ * TP-LINK TL-MR3220/3420 board support ++ * ++ * Copyright (C) 2010-2012 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. ++ */ ++ ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define TL_MR3X20_GPIO_LED_QSS 0 ++#define TL_MR3X20_GPIO_LED_SYSTEM 1 ++#define TL_MR3X20_GPIO_LED_3G 8 ++ ++#define TL_MR3X20_GPIO_BTN_RESET 11 ++#define TL_MR3X20_GPIO_BTN_QSS 12 ++ ++#define TL_MR3X20_GPIO_USB_POWER 6 ++ ++#define TL_MR3X20_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_MR3X20_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR3X20_KEYS_POLL_INTERVAL) ++ ++static const char *tl_mr3x20_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_mr3x20_flash_data = { ++ .part_probes = tl_mr3x20_part_probes, ++}; ++ ++static struct gpio_led tl_mr3x20_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_MR3X20_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_MR3X20_GPIO_LED_QSS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:3g", ++ .gpio = TL_MR3X20_GPIO_LED_3G, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_mr3x20_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_MR3X20_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3X20_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_MR3X20_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3X20_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init tl_ap99_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&tl_mr3x20_flash_data); ++ ++ ath79_register_gpio_keys_polled(-1, TL_MR3X20_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_mr3x20_gpio_keys), ++ tl_mr3x20_gpio_keys); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ ap91_pci_init(ee, mac); ++} ++ ++static void __init tl_mr3x20_usb_setup(void) ++{ ++ /* enable power for the USB port */ ++ gpio_request_one(TL_MR3X20_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++} ++ ++static void __init tl_mr3220_setup(void) ++{ ++ tl_ap99_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_mr3x20_leds_gpio), ++ tl_mr3x20_leds_gpio); ++ ap9x_pci_setup_wmac_led_pin(0, 1); ++ tl_mr3x20_usb_setup(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR3220, "TL-MR3220", "TP-LINK TL-MR3220", ++ tl_mr3220_setup); ++ ++static void __init tl_mr3420_setup(void) ++{ ++ tl_ap99_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_mr3x20_leds_gpio), ++ tl_mr3x20_leds_gpio); ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++ tl_mr3x20_usb_setup(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR3420, "TL-MR3420", "TP-LINK TL-MR3420", ++ tl_mr3420_setup); ++ ++static void __init tl_wr841n_v7_setup(void) ++{ ++ tl_ap99_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_mr3x20_leds_gpio) - 1, ++ tl_mr3x20_leds_gpio); ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR841N_V7, "TL-WR841N-v7", ++ "TP-LINK TL-WR841N/ND v7", tl_wr841n_v7_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr6400.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr6400.c +new file mode 100644 +index 0000000000..be49c89cab +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr6400.c +@@ -0,0 +1,151 @@ ++/* ++ * TP-LINK TL-MR6400 board support ++ * ++ * Copyright (C) 2017 Filip Moc ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_MR6400_GPIO_LTE_POWER 4 ++#define TL_MR6400_GPIO_BTN_RESET 12 /* SW2 */ ++#define TL_MR6400_GPIO_BTN_RFKILL 14 /* SW3 */ ++#define TL_MR6400_GPIO_LED_WAN 0 /* D12 */ ++#define TL_MR6400_GPIO_LED_4G 1 /* D11 */ ++#define TL_MR6400_GPIO_LED_WPS 3 /* D5 */ ++#define TL_MR6400_GPIO_LED_WLAN 11 /* D3 */ ++#define TL_MR6400_GPIO_LED_POWER 13 /* D2 */ ++#define TL_MR6400_GPIO_LED_LAN 16 /* D4 */ ++ ++#define TL_MR6400_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_MR6400_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR6400_KEYS_POLL_INTERVAL) ++ ++#define TL_MR6400_WMAC_CALDATA_OFFSET 0x1000 ++ ++static const char *tl_mr6400_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_mr6400_flash_data = { ++ .part_probes = tl_mr6400_part_probes, ++ .type = "w25q64", ++}; ++ ++static struct gpio_led tl_mr6400_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:white:wan", ++ .gpio = TL_MR6400_GPIO_LED_WAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "tp-link:white:4g", ++ .gpio = TL_MR6400_GPIO_LED_4G, ++ .active_low = 0, ++ }, ++ { ++ .name = "tp-link:white:wps", ++ .gpio = TL_MR6400_GPIO_LED_WPS, ++ .active_low = 0, ++ }, ++ { ++ .name = "tp-link:white:wlan", ++ .gpio = TL_MR6400_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .name = "tp-link:white:power", ++ .gpio = TL_MR6400_GPIO_LED_POWER, ++ .active_low = 0, ++ }, ++ { ++ .name = "tp-link:white:lan", ++ .gpio = TL_MR6400_GPIO_LED_LAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tl_mr6400_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_MR6400_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR6400_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "rfkill", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_MR6400_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR6400_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init tl_mr6400_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&tl_mr6400_flash_data); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN1, LAN2, LAN3 */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask |= BIT(0); ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ath79_register_eth(1); ++ ++ /* LAN4 / WAN */ ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art + TL_MR6400_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_register_leds_gpio(-1, ++ ARRAY_SIZE(tl_mr6400_leds_gpio), ++ tl_mr6400_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ++ TL_MR6400_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_mr6400_gpio_keys), ++ tl_mr6400_gpio_keys); ++ ++ gpio_request_one(TL_MR6400_GPIO_LTE_POWER, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED | GPIOF_ACTIVE_LOW, ++ "LTE power"); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR6400, "TL-MR6400", "TP-LINK TL-MR6400", ++ tl_mr6400_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa701nd-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa701nd-v2.c +new file mode 100644 +index 0000000000..aab92b30d4 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa701nd-v2.c +@@ -0,0 +1,116 @@ ++/* ++ * TP-LINK TL-WA701ND v2 board support ++ * ++ * Copyright (C) 2015 Luigi Tarenga ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WA701NDV2_GPIO_LED_WLAN 0 ++#define TL_WA701NDV2_GPIO_LED_QSS 1 ++#define TL_WA701NDV2_GPIO_LED_LAN 17 ++#define TL_WA701NDV2_GPIO_LED_SYSTEM 27 ++ ++#define TL_WA701NDV2_GPIO_BTN_RESET 11 ++#define TL_WA701NDV2_GPIO_BTN_QSS 26 ++ ++#define TL_WA701NDV2_GPIO_USB_POWER 8 ++ ++#define TL_WA701NDV2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WA701NDV2_KEYS_DEBOUNCE_INTERVAL (3 * TL_WA701NDV2_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wa701ndv2_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wa701ndv2_flash_data = { ++ .part_probes = tl_wa701ndv2_part_probes, ++}; ++ ++static struct gpio_led tl_wa701ndv2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WA701NDV2_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WA701NDV2_GPIO_LED_QSS, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WA701NDV2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WA701NDV2_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_wa701ndv2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WA701NDV2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA701NDV2_GPIO_BTN_RESET, ++ .active_low = 0, ++ } , { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WA701NDV2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA701NDV2_GPIO_BTN_QSS, ++ .active_low = 0, ++ } ++ ++}; ++ ++static void __init tl_wa701ndv2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa701ndv2_leds_gpio), ++ tl_wa701ndv2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WA701NDV2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wa701ndv2_gpio_keys), ++ tl_wa701ndv2_gpio_keys); ++ ++ gpio_request_one(TL_WA701NDV2_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(&tl_wa701ndv2_flash_data); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ /* ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); */ ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA701ND_V2, "TL-WA701ND-v2", ++ "TP-LINK TL-WA701ND v2", tl_wa701ndv2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa7210n-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa7210n-v2.c +new file mode 100644 +index 0000000000..276353a6c3 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa7210n-v2.c +@@ -0,0 +1,125 @@ ++/* ++ * TP-LINK TL-WA7210N v2.1 board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2014 Nicolas Braud-Santoni ++ * Copyright (C) 2014 Alexander List ++ * Copyright (C) 2015 Hendrik Frenzel ++ * ++ * rebased on TL-WA7510Nv1 support, ++ * Copyright (C) 2012 Stefan Helmert ++ * ++ * 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 "dev-dsa.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#include "common.h" ++ ++#define TL_WA7210N_V2_GPIO_BTN_RESET 11 ++#define TL_WA7210N_V2_KEYS_POLL_INT 20 ++#define TL_WA7210N_V2_KEYS_DEBOUNCE_INT (3 * TL_WA7210N_V2_KEYS_POLL_INT) ++ ++#define TL_WA7210N_V2_GPIO_LED_LAN 17 ++#define TL_WA7210N_V2_GPIO_LED_SIG1 0 ++#define TL_WA7210N_V2_GPIO_LED_SIG2 1 ++#define TL_WA7210N_V2_GPIO_LED_SIG3 27 ++#define TL_WA7210N_V2_GPIO_LED_SIG4 26 ++ ++#define TL_WA7210N_V2_GPIO_LNA_EN 28 ++ ++static const char *tl_wa7210n_v2_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct gpio_keys_button tl_wa7210n_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WA7210N_V2_KEYS_DEBOUNCE_INT, ++ .gpio = TL_WA7210N_V2_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_led tl_wa7210n_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WA7210N_V2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:signal1", ++ .gpio = TL_WA7210N_V2_GPIO_LED_SIG1, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:signal2", ++ .gpio = TL_WA7210N_V2_GPIO_LED_SIG2, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:signal3", ++ .gpio = TL_WA7210N_V2_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:signal4", ++ .gpio = TL_WA7210N_V2_GPIO_LED_SIG4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct flash_platform_data tl_wa7210n_v2_flash_data = { ++ .part_probes = tl_wa7210n_v2_part_probes, ++}; ++ ++static void __init tl_wa7210n_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WA7210N_V2_KEYS_POLL_INT, ++ ARRAY_SIZE(tl_wa7210n_v2_gpio_keys), ++ tl_wa7210n_v2_gpio_keys); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa7210n_v2_leds_gpio), ++ tl_wa7210n_v2_leds_gpio); ++ ++ ath79_gpio_function_enable(TL_WA7210N_V2_GPIO_LNA_EN); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_register_wmac(ee, mac); ++ ++ ath79_register_m25p80(&tl_wa7210n_v2_flash_data); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA7210N_V2, "TL-WA7210N-v2", "TP-LINK TL-WA7210N v2", ++ tl_wa7210n_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa801nd-v3.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa801nd-v3.c +new file mode 100644 +index 0000000000..1637382192 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa801nd-v3.c +@@ -0,0 +1,137 @@ ++/* ++ * TP-LINK TL-WA801ND v3 adapted from TP-LINK TL-WR841N/ND v9 ++ * TP-LINK TL-WA801ND v4 ++ * ++ * Copyright (C) 2014 Matthias Schiffer ++ * Copyright (C) 2016 Tiziano Bacocco ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WA801NDV3_GPIO_LED_WLAN 12 ++#define TL_WA801NDV3_GPIO_LED_SYSTEM 13 ++#define TL_WA801NDV3_GPIO_LED_SECURITY_RED 11 ++#define TL_WA801NDV3_GPIO_LED_SECURITY_GREEN 15 ++#define TL_WA801NDV3_GPIO_LED_LAN 3 ++ ++#define TL_WA801NDV3_GPIO_BTN_RESET 2 ++#define TL_WA801NDV3_GPIO_BTN_WIFI 1 ++ ++#define TL_WA801NDV3_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WA801NDV3_KEYS_DEBOUNCE_INTERVAL (3 * TL_WA801NDV3_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wa801n_v3_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wa801n_v3_flash_data = { ++ .part_probes = tl_wa801n_v3_part_probes, ++}; ++ ++static struct gpio_led tl_wa801n_v3_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WA801NDV3_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WA801NDV3_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WA801NDV3_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:red:security", ++ .gpio = TL_WA801NDV3_GPIO_LED_SECURITY_RED, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:security", ++ .gpio = TL_WA801NDV3_GPIO_LED_SECURITY_GREEN, ++ .active_low = 0, ++ } ++ ++}; ++ ++static struct gpio_keys_button tl_wa801n_v3_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WA801NDV3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA801NDV3_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "WIFI button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WA801NDV3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA801NDV3_GPIO_BTN_WIFI, ++ .active_low = 1, ++ } ++}; ++ ++ ++static void __init tl_ap143_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&tl_wa801n_v3_flash_data); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ ath79_init_mac(tmpmac, mac, 0); ++ ath79_register_wmac(ee, tmpmac); ++} ++ ++static void __init tl_wa801n_v3_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa801n_v3_leds_gpio), ++ tl_wa801n_v3_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WA801NDV3_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wa801n_v3_gpio_keys), ++ tl_wa801n_v3_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA801ND_V3, "TL-WA801ND-v3", "TP-LINK TL-WA801ND v3", ++ tl_wa801n_v3_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa830re-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa830re-v2.c +new file mode 100644 +index 0000000000..1c74fed98e +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa830re-v2.c +@@ -0,0 +1,132 @@ ++/* ++ * TP-LINK TL-WA830RE v2 board support ++ * ++ * Copyright (C) 2014 Fredrik Jonson ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WA830REV2_GPIO_LED_WLAN 13 ++#define TL_WA830REV2_GPIO_LED_QSS 15 ++#define TL_WA830REV2_GPIO_LED_LAN 18 ++#define TL_WA830REV2_GPIO_LED_SYSTEM 14 ++ ++#define TL_WA830REV2_GPIO_BTN_RESET 17 ++#define TL_WA830REV2_GPIO_SW_RFKILL 16 /* WPS for MR3420 v2 */ ++ ++#define TL_WA830REV2_GPIO_USB_POWER 4 ++ ++#define TL_WA830REV2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WA830REV2_KEYS_DEBOUNCE_INTERVAL (3 * TL_WA830REV2_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wa830re_v2_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wa830re_v2_flash_data = { ++ .part_probes = tl_wa830re_v2_part_probes, ++}; ++ ++static struct gpio_led tl_wa830re_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WA830REV2_GPIO_LED_QSS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WA830REV2_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WA830REV2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WA830REV2_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wa830re_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WA830REV2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA830REV2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "RFKILL switch", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WA830REV2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA830REV2_GPIO_SW_RFKILL, ++ .active_low = 0, ++ } ++}; ++ ++static void __init tl_ap123_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* Disable JTAG, enabling GPIOs 0-3 */ ++ /* Configure OBS4 line, for GPIO 4*/ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, ++ AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ /* config gpio4 as normal gpio function */ ++ ath79_gpio_output_select(TL_WA830REV2_GPIO_USB_POWER, ++ AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_m25p80(&tl_wa830re_v2_flash_data); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init tl_wa830re_v2_setup(void) ++{ ++ tl_ap123_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa830re_v2_leds_gpio) - 1, ++ tl_wa830re_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WA830REV2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wa830re_v2_gpio_keys), ++ tl_wa830re_v2_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA830RE_V2, "TL-WA830RE-v2", "TP-LINK TL-WA830RE v2", ++ tl_wa830re_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v2.c +new file mode 100644 +index 0000000000..b4fb2a9f91 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v2.c +@@ -0,0 +1,104 @@ ++/* ++ * TP-LINK TL-WA901N/ND v2 board support ++ * ++ * Copyright (C) 2009-2012 Gabor Juhos ++ * Copyright (C) 2010 Pieter Hollants ++ * Copyright (C) 2011 Jonathan Bennett ++ * ++ * 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 "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WA901ND_V2_GPIO_LED_QSS 4 ++#define TL_WA901ND_V2_GPIO_LED_SYSTEM 2 ++#define TL_WA901ND_V2_GPIO_LED_WLAN 9 ++ ++#define TL_WA901ND_V2_GPIO_BTN_RESET 3 ++#define TL_WA901ND_V2_GPIO_BTN_QSS 7 ++ ++#define TL_WA901ND_V2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WA901ND_V2_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * TL_WA901ND_V2_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wa901nd_v2_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wa901nd_v2_flash_data = { ++ .part_probes = tl_wa901nd_v2_part_probes, ++}; ++ ++static struct gpio_led tl_wa901nd_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WA901ND_V2_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WA901ND_V2_GPIO_LED_QSS, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WA901ND_V2_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_wa901nd_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WA901ND_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA901ND_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WA901ND_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA901ND_V2_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init tl_wa901nd_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = 0x00001000; ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_eth0_data.reset_bit = AR71XX_RESET_GE0_MAC | ++ AR71XX_RESET_GE0_PHY; ++ ath79_register_eth(0); ++ ++ ath79_register_m25p80(&tl_wa901nd_v2_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa901nd_v2_leds_gpio), ++ tl_wa901nd_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WA901ND_V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wa901nd_v2_gpio_keys), ++ tl_wa901nd_v2_gpio_keys); ++ ++ ath79_register_wmac(eeprom, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA901ND_V2, "TL-WA901ND-v2", ++ "TP-LINK TL-WA901ND v2", tl_wa901nd_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v4.c +new file mode 100644 +index 0000000000..ffbcd6fe42 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v4.c +@@ -0,0 +1,115 @@ ++/* ++ * TP-LINK TL-WA901ND v4, v5 board ++ * ++ * Copyright (C) 2015 Matthias Schiffer ++ * Copyright (C) 2016 Tiziano Bacocco ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++#define TL_WA901ND_V4_GPIO_LED_QSS 3 ++#define TL_WA901ND_V4_GPIO_LED_LAN 7 ++#define TL_WA901ND_V4_GPIO_LED_WLAN 8 ++#define TL_WA901ND_V4_GPIO_LED_SYSTEM 18 ++ ++#define TL_WA901ND_V4_GPIO_BTN_RESET 1 ++ ++#define TL_WA901ND_V4_KEYS_POLL_INTERVAL 20 ++#define TL_WA901ND_V4_KEYS_DEBOUNCE_INTERVAL (3 * TL_WA901ND_V4_KEYS_POLL_INTERVAL) ++ ++ ++static struct gpio_led TL_WA901ND_V4_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WA901ND_V4_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WA901ND_V4_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WA901ND_V4_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WA901ND_V4_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button TL_WA901ND_V4_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WA901ND_V4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA901ND_V4_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++ ++static const char *tl_wa901nd_v4_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wa901nd_v4_flash_data = { ++ .part_probes = tl_wa901nd_v4_part_probes, ++}; ++ ++ ++static void __init TL_WA901ND_V4_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&tl_wa901nd_v4_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(TL_WA901ND_V4_leds_gpio), ++ TL_WA901ND_V4_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WA901ND_V4_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(TL_WA901ND_V4_gpio_keys), ++ TL_WA901ND_V4_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++ ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA901ND_V4, "TL-WA901ND-v4", "TP-LINK TL-WA901ND v4", ++ TL_WA901ND_V4_setup); ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA901ND_V5, "TL-WA901ND-v5", "TP-LINK TL-WA901ND v5", ++ TL_WA901ND_V4_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd.c +new file mode 100644 +index 0000000000..957b92cba6 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd.c +@@ -0,0 +1,127 @@ ++/* ++ * TP-LINK TL-WA901N/ND v1, TL-WA7510N v1 board support ++ * ++ * Copyright (C) 2009-2012 Gabor Juhos ++ * Copyright (C) 2010 Pieter Hollants ++ * Copyright (C) 2012 Stefan Helmert ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define TL_WA901ND_GPIO_LED_QSS 0 ++#define TL_WA901ND_GPIO_LED_SYSTEM 1 ++#define TL_WA901ND_GPIO_LED_LAN 13 ++ ++#define TL_WA901ND_GPIO_BTN_RESET 11 ++#define TL_WA901ND_GPIO_BTN_QSS 12 ++ ++#define TL_WA901ND_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WA901ND_KEYS_DEBOUNCE_INTERVAL (3 * TL_WA901ND_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wa901nd_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wa901nd_flash_data = { ++ .part_probes = tl_wa901nd_part_probes, ++}; ++ ++static struct gpio_led tl_wa901nd_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WA901ND_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WA901ND_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WA901ND_GPIO_LED_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_wa901nd_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WA901ND_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA901ND_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WA901ND_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA901ND_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init common_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ ++ /* ++ * ath79_eth0 would be the WAN port, but is not connected. ++ * ath79_eth1 connects to the internal switch chip, however ++ * we have a single LAN port only. ++ */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(&tl_wa901nd_flash_data); ++} ++ ++static void __init tl_wa901nd_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa901nd_leds_gpio), ++ tl_wa901nd_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WA901ND_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wa901nd_gpio_keys), ++ tl_wa901nd_gpio_keys); ++ ++ ap91_pci_init(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA901ND, "TL-WA901ND", "TP-LINK TL-WA901ND", ++ tl_wa901nd_setup); ++ ++static void __init tl_wa7510n_v1_setup(void) ++{ ++ common_setup(); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA7510N_V1, "TL-WA7510N", "TP-LINK TL-WA7510N v1", ++ tl_wa7510n_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wax50re.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wax50re.c +new file mode 100644 +index 0000000000..955628fecb +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wax50re.c +@@ -0,0 +1,445 @@ ++/* ++ * Support for TP-Link boards: ++ * - TL-WA750RE v1 ++ * - TL-WA801ND v2 ++ * - TL-WA850RE v1/v2 ++ * - TL-WA855RE v1 ++ * - TL-WA901ND v3 ++ * ++ * Copyright (C) 2013 Martijn Zilverschoon ++ * Copyright (C) 2013 Jiri Pirko ++ * Copyright (C) 2017 Piotr Dymacz ++ * Copyright (C) 2017 Federico Cappon ++ * Copyright (C) 2017 Nicolò Veronese ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WAX50RE_GPIO_LED_LAN 20 ++#define TL_WAX50RE_GPIO_LED_WLAN 13 ++#define TL_WAX50RE_GPIO_LED_RE 15 ++#define TL_WAX50RE_GPIO_LED_SIGNAL1 0 ++#define TL_WAX50RE_GPIO_LED_SIGNAL2 1 ++#define TL_WAX50RE_GPIO_LED_SIGNAL3 2 ++#define TL_WAX50RE_GPIO_LED_SIGNAL4 3 ++#define TL_WAX50RE_GPIO_LED_SIGNAL5 4 ++ ++#define TL_WA850RE_V2_GPIO_LED_LAN 14 ++#define TL_WA850RE_V2_GPIO_LED_RE 12 ++#define TL_WA850RE_V2_GPIO_LED_SIGNAL1 0 ++#define TL_WA850RE_V2_GPIO_LED_SIGNAL2 1 ++#define TL_WA850RE_V2_GPIO_LED_SIGNAL3 2 ++#define TL_WA850RE_V2_GPIO_LED_SIGNAL4 3 ++#define TL_WA850RE_V2_GPIO_LED_SIGNAL5 4 ++#define TL_WA850RE_V2_GPIO_LED_WLAN 13 ++ ++#define TL_WA850RE_V2_GPIO_ENABLE_LEDS 15 ++ ++#define TL_WA855REV1_GPIO_LED_RED 11 ++#define TL_WA855REV1_GPIO_LED_GREEN 12 ++ ++#define TL_WA860RE_GPIO_LED_WLAN_ORANGE 0 ++#define TL_WA860RE_GPIO_LED_WLAN_GREEN 2 ++#define TL_WA860RE_GPIO_LED_POWER_ORANGE 12 ++#define TL_WA860RE_GPIO_LED_POWER_GREEN 14 ++#define TL_WA860RE_GPIO_LED_LAN 20 ++ ++#define TL_WA801ND_V2_GPIO_LED_LAN 18 ++#define TL_WA801ND_V2_GPIO_LED_SYSTEM 14 ++ ++#define TL_WAX50RE_GPIO_BTN_RESET 17 ++#define TL_WAX50RE_GPIO_BTN_WPS 16 ++ ++#define TL_WA860RE_GPIO_BTN_RESET 17 ++#define TL_WA860RE_GPIO_BTN_WPS 16 ++#define TL_WA860RE_GPIO_BTN_ONOFF 11 ++ ++#define TL_WAX50RE_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WAX50RE_KEYS_DEBOUNCE_INTERVAL (3 * TL_WAX50RE_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wax50re_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wax50re_flash_data = { ++ .part_probes = tl_wax50re_part_probes, ++}; ++ ++static struct gpio_led tl_wa750re_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:orange:lan", ++ .gpio = TL_WAX50RE_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:wlan", ++ .gpio = TL_WAX50RE_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:re", ++ .gpio = TL_WAX50RE_GPIO_LED_RE, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:signal1", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:signal2", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:signal3", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:signal4", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:signal5", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL5, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led tl_wa850re_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:lan", ++ .gpio = TL_WAX50RE_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:wlan", ++ .gpio = TL_WAX50RE_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:re", ++ .gpio = TL_WAX50RE_GPIO_LED_RE, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal1", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal2", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal3", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal4", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal5", ++ .gpio = TL_WAX50RE_GPIO_LED_SIGNAL5, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led tl_wa850re_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:lan", ++ .gpio = TL_WA850RE_V2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:re", ++ .gpio = TL_WA850RE_V2_GPIO_LED_RE, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal1", ++ .gpio = TL_WA850RE_V2_GPIO_LED_SIGNAL1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal2", ++ .gpio = TL_WA850RE_V2_GPIO_LED_SIGNAL2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal3", ++ .gpio = TL_WA850RE_V2_GPIO_LED_SIGNAL3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal4", ++ .gpio = TL_WA850RE_V2_GPIO_LED_SIGNAL4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:signal5", ++ .gpio = TL_WA850RE_V2_GPIO_LED_SIGNAL5, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:blue:wlan", ++ .gpio = TL_WA850RE_V2_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led tl_wa855re_v1_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:power", ++ .gpio = TL_WA855REV1_GPIO_LED_GREEN, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:red:power", ++ .gpio = TL_WA855REV1_GPIO_LED_RED, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_led tl_wa860re_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WA860RE_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:power", ++ .gpio = TL_WA860RE_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:power", ++ .gpio = TL_WA860RE_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WA860RE_GPIO_LED_WLAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:wlan", ++ .gpio = TL_WA860RE_GPIO_LED_WLAN_ORANGE, ++ .active_low = 1, ++ }, ++}; ++ ++ ++static struct gpio_keys_button tl_wax50re_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WAX50RE_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WAX50RE_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "WPS", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WAX50RE_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WAX50RE_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wa860re_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WAX50RE_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA860RE_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "WPS", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WAX50RE_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA860RE_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, { ++ .desc = "ONOFF", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = TL_WAX50RE_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WA860RE_GPIO_BTN_ONOFF, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led tl_wa801nd_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WA801ND_V2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WAX50RE_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WAX50RE_GPIO_LED_RE, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WA801ND_V2_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init tl_ap123_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&tl_wax50re_flash_data); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init tl_ap143_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f3c0008); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -2); ++ ath79_register_eth(0); ++ ++ ath79_init_mac(tmpmac, mac, 0); ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init tl_wa750re_setup(void) ++{ ++ tl_ap123_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa750re_leds_gpio), ++ tl_wa750re_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WAX50RE_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wax50re_gpio_keys), ++ tl_wax50re_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA750RE, "TL-WA750RE", "TP-LINK TL-WA750RE", ++ tl_wa750re_setup); ++ ++static void __init tl_wa801nd_v2_setup(void) ++{ ++ tl_ap123_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa801nd_v2_leds_gpio), ++ tl_wa801nd_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WAX50RE_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wax50re_gpio_keys), ++ tl_wax50re_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA801ND_V2, "TL-WA801ND-v2", "TP-LINK TL-WA801ND v2", ++ tl_wa801nd_v2_setup); ++ ++static void __init tl_wa850re_setup(void) ++{ ++ tl_ap123_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa850re_leds_gpio), ++ tl_wa850re_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WAX50RE_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wax50re_gpio_keys), ++ tl_wax50re_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA850RE, "TL-WA850RE", "TP-LINK TL-WA850RE", ++ tl_wa850re_setup); ++ ++static void __init tl_wa850re_v2_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ /* For GPIO 0~4 */ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, ++ AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ /* Allow to enable/disable all LEDs from userspace */ ++ gpio_request_one(TL_WA850RE_V2_GPIO_ENABLE_LEDS, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LEDs enable"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa850re_v2_leds_gpio), ++ tl_wa850re_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WAX50RE_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wax50re_gpio_keys), ++ tl_wax50re_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA850RE_V2, "TL-WA850RE-V2", ++ "TP-LINK TL-WA850RE v2", tl_wa850re_v2_setup); ++ ++static void __init tl_wa855re_v1_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa855re_v1_leds_gpio), ++ tl_wa855re_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WAX50RE_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wax50re_gpio_keys), ++ tl_wax50re_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA855RE_V1, "TL-WA855RE-v1", "TP-LINK TL-WA855RE v1", ++ tl_wa855re_v1_setup); ++ ++static void __init tl_wa860re_setup(void) ++{ ++ tl_ap123_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa860re_leds_gpio), ++ tl_wa860re_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WAX50RE_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wa860re_gpio_keys), ++ tl_wa860re_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA860RE, "TL-WA860RE", "TP-LINK TL-WA860RE", ++ tl_wa860re_setup); ++ ++static void __init tl_wa901nd_v3_setup(void) ++{ ++ tl_ap123_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wa801nd_v2_leds_gpio), ++ tl_wa801nd_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WAX50RE_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wax50re_gpio_keys) - 1, ++ tl_wax50re_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA901ND_V3, "TL-WA901ND-v3", "TP-LINK TL-WA901ND v3", ++ tl_wa901nd_v3_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3320-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3320-v2.c +new file mode 100644 +index 0000000000..3e452f2a4a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3320-v2.c +@@ -0,0 +1,146 @@ ++/* ++ * TP-LINK TL-WDR3320 v2 board support ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2015 Weijie Gao ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WDR3320_GPIO_LED_WLAN5G 12 ++#define WDR3320_GPIO_LED_SYSTEM 14 ++#define WDR3320_GPIO_LED_QSS 15 ++#define WDR3320_GPIO_LED_WAN 4 ++#define WDR3320_GPIO_LED_LAN1 18 ++#define WDR3320_GPIO_LED_LAN2 20 ++#define WDR3320_GPIO_LED_LAN3 21 ++#define WDR3320_GPIO_LED_LAN4 22 ++ ++#define WDR3320_GPIO_BTN_RESET 16 ++ ++#define WDR3320_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WDR3320_KEYS_DEBOUNCE_INTERVAL (3 * WDR3320_KEYS_POLL_INTERVAL) ++ ++#define WDR3320_WMAC_CALDATA_OFFSET 0x1000 ++#define WDR3320_PCIE_CALDATA_OFFSET 0x5000 ++ ++static const char *wdr3320_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data wdr3320_flash_data = { ++ .part_probes = wdr3320_part_probes, ++}; ++ ++static struct gpio_led wdr3320_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:qss", ++ .gpio = WDR3320_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:system", ++ .gpio = WDR3320_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan5g", ++ .gpio = WDR3320_GPIO_LED_WLAN5G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wdr3320_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WDR3320_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WDR3320_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init wdr3320_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&wdr3320_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wdr3320_leds_gpio), ++ wdr3320_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WDR3320_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wdr3320_gpio_keys), ++ wdr3320_gpio_keys); ++ ++ ath79_init_mac(tmpmac, mac, 0); ++ ath79_register_wmac(art + WDR3320_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_init_mac(tmpmac, mac, -1); ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++ ap91_pci_init(art + WDR3320_PCIE_CALDATA_OFFSET, tmpmac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* LAN */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ++ /* GMAC0 is connected to the PHY4 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ ath79_register_eth(0); ++ ++ ath79_register_usb(); ++ ++ ath79_gpio_output_select(WDR3320_GPIO_LED_LAN1, ++ AR934X_GPIO_OUT_LED_LINK0); ++ ath79_gpio_output_select(WDR3320_GPIO_LED_LAN2, ++ AR934X_GPIO_OUT_LED_LINK1); ++ ath79_gpio_output_select(WDR3320_GPIO_LED_LAN3, ++ AR934X_GPIO_OUT_LED_LINK2); ++ ath79_gpio_output_select(WDR3320_GPIO_LED_LAN4, ++ AR934X_GPIO_OUT_LED_LINK3); ++ ath79_gpio_output_select(WDR3320_GPIO_LED_WAN, ++ AR934X_GPIO_OUT_LED_LINK4); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WDR3320_V2, "TL-WDR3320-v2", ++ "TP-LINK TL-WDR3320 v2", ++ wdr3320_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3500.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3500.c +new file mode 100644 +index 0000000000..452c20b777 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3500.c +@@ -0,0 +1,169 @@ ++/* ++ * TP-LINK TL-WDR3500 board support ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2013 Gui Iribarren ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WDR3500_GPIO_LED_USB 11 ++#define WDR3500_GPIO_LED_WLAN2G 13 ++#define WDR3500_GPIO_LED_SYSTEM 14 ++#define WDR3500_GPIO_LED_QSS 15 ++#define WDR3500_GPIO_LED_WAN 18 ++#define WDR3500_GPIO_LED_LAN1 19 ++#define WDR3500_GPIO_LED_LAN2 20 ++#define WDR3500_GPIO_LED_LAN3 21 ++#define WDR3500_GPIO_LED_LAN4 22 ++ ++#define WDR3500_GPIO_BTN_WPS 16 ++#define WDR3500_GPIO_BTN_RFKILL 17 ++ ++#define WDR3500_GPIO_USB_POWER 12 ++ ++#define WDR3500_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WDR3500_KEYS_DEBOUNCE_INTERVAL (3 * WDR3500_KEYS_POLL_INTERVAL) ++ ++#define WDR3500_MAC0_OFFSET 0 ++#define WDR3500_MAC1_OFFSET 6 ++#define WDR3500_WMAC_CALDATA_OFFSET 0x1000 ++#define WDR3500_PCIE_CALDATA_OFFSET 0x5000 ++ ++static const char *wdr3500_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data wdr3500_flash_data = { ++ .part_probes = wdr3500_part_probes, ++}; ++ ++static struct gpio_led wdr3500_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:qss", ++ .gpio = WDR3500_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:system", ++ .gpio = WDR3500_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb", ++ .gpio = WDR3500_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan2g", ++ .gpio = WDR3500_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wdr3500_gpio_keys[] __initdata = { ++ { ++ .desc = "QSS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WDR3500_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WDR3500_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL switch", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = WDR3500_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WDR3500_GPIO_BTN_RFKILL, ++ }, ++}; ++ ++ ++static void __init wdr3500_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&wdr3500_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wdr3500_leds_gpio), ++ wdr3500_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WDR3500_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wdr3500_gpio_keys), ++ wdr3500_gpio_keys); ++ ++ ath79_init_mac(tmpmac, mac, 0); ++ ath79_register_wmac(art + WDR3500_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_init_mac(tmpmac, mac, 1); ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++ ap91_pci_init(art + WDR3500_PCIE_CALDATA_OFFSET, tmpmac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* LAN */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 2); ++ ++ /* GMAC0 is connected to the PHY4 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ ath79_register_eth(0); ++ ++ gpio_request_one(WDR3500_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_gpio_output_select(WDR3500_GPIO_LED_LAN1, ++ AR934X_GPIO_OUT_LED_LINK3); ++ ath79_gpio_output_select(WDR3500_GPIO_LED_LAN2, ++ AR934X_GPIO_OUT_LED_LINK2); ++ ath79_gpio_output_select(WDR3500_GPIO_LED_LAN3, ++ AR934X_GPIO_OUT_LED_LINK1); ++ ath79_gpio_output_select(WDR3500_GPIO_LED_LAN4, ++ AR934X_GPIO_OUT_LED_LINK0); ++ ath79_gpio_output_select(WDR3500_GPIO_LED_WAN, ++ AR934X_GPIO_OUT_LED_LINK4); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WDR3500, "TL-WDR3500", ++ "TP-LINK TL-WDR3500", ++ wdr3500_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c +new file mode 100644 +index 0000000000..b9fea95bc2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c +@@ -0,0 +1,206 @@ ++/* ++ * TP-LINK TL-WDR4300 board support ++ * ++ * Copyright (C) 2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WDR4300_GPIO_LED_USB1 11 ++#define WDR4300_GPIO_LED_USB2 12 ++#define WDR4300_GPIO_LED_WLAN2G 13 ++#define WDR4300_GPIO_LED_SYSTEM 14 ++#define WDR4300_GPIO_LED_QSS 15 ++ ++#define WDR4300_GPIO_BTN_WPS 16 ++#define WDR4300_GPIO_BTN_RFKILL 17 ++ ++#define WDR4300_GPIO_EXTERNAL_LNA0 18 ++#define WDR4300_GPIO_EXTERNAL_LNA1 19 ++ ++#define WDR4300_GPIO_USB1_POWER 22 ++#define WDR4300_GPIO_USB2_POWER 21 ++ ++#define WDR4300_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WDR4300_KEYS_DEBOUNCE_INTERVAL (3 * WDR4300_KEYS_POLL_INTERVAL) ++ ++#define WDR4300_MAC0_OFFSET 0 ++#define WDR4300_MAC1_OFFSET 6 ++#define WDR4300_WMAC_CALDATA_OFFSET 0x1000 ++#define WDR4300_PCIE_CALDATA_OFFSET 0x5000 ++ ++static const char *wdr4300_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data wdr4300_flash_data = { ++ .part_probes = wdr4300_part_probes, ++}; ++ ++static struct gpio_led wdr4300_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:qss", ++ .gpio = WDR4300_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:system", ++ .gpio = WDR4300_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb1", ++ .gpio = WDR4300_GPIO_LED_USB1, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb2", ++ .gpio = WDR4300_GPIO_LED_USB2, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:wlan2g", ++ .gpio = WDR4300_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wdr4300_gpio_keys[] __initdata = { ++ { ++ .desc = "QSS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WDR4300_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WDR4300_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL switch", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = WDR4300_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WDR4300_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info wdr4300_leds_ar8327[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "tp-link:blue:wan"), ++ AR8327_LED_INFO(PHY1_0, HW, "tp-link:blue:lan1"), ++ AR8327_LED_INFO(PHY2_0, HW, "tp-link:blue:lan2"), ++ AR8327_LED_INFO(PHY3_0, HW, "tp-link:blue:lan3"), ++ AR8327_LED_INFO(PHY4_0, HW, "tp-link:blue:lan4"), ++}; ++ ++static struct ar8327_pad_cfg wdr4300_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg wdr4300_ar8327_led_cfg = { ++ .led_ctrl0 = 0xc737c737, ++ .led_ctrl1 = 0x00000000, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x0030c300, ++ .open_drain = false, ++}; ++ ++static struct ar8327_platform_data wdr4300_ar8327_data = { ++ .pad0_cfg = &wdr4300_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &wdr4300_ar8327_led_cfg, ++ .num_leds = ARRAY_SIZE(wdr4300_leds_ar8327), ++ .leds = wdr4300_leds_ar8327, ++}; ++ ++static struct mdio_board_info wdr4300_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &wdr4300_ar8327_data, ++ }, ++}; ++ ++static void __init wdr4300_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&wdr4300_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wdr4300_leds_gpio), ++ wdr4300_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WDR4300_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wdr4300_gpio_keys), ++ wdr4300_gpio_keys); ++ ++ ath79_wmac_set_ext_lna_gpio(0, WDR4300_GPIO_EXTERNAL_LNA0); ++ ath79_wmac_set_ext_lna_gpio(1, WDR4300_GPIO_EXTERNAL_LNA1); ++ ++ ath79_init_mac(tmpmac, mac, -1); ++ ath79_register_wmac(art + WDR4300_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_init_mac(tmpmac, mac, 0); ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++ ap91_pci_init(art + WDR4300_PCIE_CALDATA_OFFSET, tmpmac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ++ mdiobus_register_board_info(wdr4300_mdio0_info, ++ ARRAY_SIZE(wdr4300_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ /* GMAC0 is connected to an AR8327N switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++ ++ gpio_request_one(WDR4300_GPIO_USB1_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB1 power"); ++ gpio_request_one(WDR4300_GPIO_USB2_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB2 power"); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WDR4300, "TL-WDR4300", ++ "TP-LINK TL-WDR3600/4300/4310", ++ wdr4300_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr6500-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr6500-v2.c +new file mode 100644 +index 0000000000..1e72477646 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr6500-v2.c +@@ -0,0 +1,142 @@ ++/* ++ * TP-LINK TL-WDR6500 v2 ++ * ++ * Copyright (C) 2015 Weijie Gao ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define TL_WDR6500_V2_GPIO_LED_SYS 21 ++#define TL_WDR6500_V2_GPIO_LED_WAN 18 ++#define TL_WDR6500_V2_GPIO_LED_LAN1 17 ++#define TL_WDR6500_V2_GPIO_LED_LAN2 16 ++#define TL_WDR6500_V2_GPIO_LED_LAN3 15 ++#define TL_WDR6500_V2_GPIO_LED_LAN4 14 ++ ++#define TL_WDR6500_V2_GPIO_BTN_RESET 1 ++ ++#define TL_WDR6500_V2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WDR6500_V2_KEYS_DEBOUNCE_INTERVAL (3 * TL_WDR6500_V2_KEYS_POLL_INTERVAL) ++ ++#define TL_WDR6500_V2_WMAC_CALDATA_OFFSET 0x1000 ++#define TL_WDR6500_V2_PCIE_CALDATA_OFFSET 0x5000 ++ ++static const char *tl_wdr6500_v2_part_probes[] = { ++ "tp-link-64k", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wdr6500_v2_flash_data = { ++ .part_probes = tl_wdr6500_v2_part_probes, ++}; ++ ++static struct gpio_led tl_wdr6500_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WDR6500_V2_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WDR6500_V2_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WDR6500_V2_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WDR6500_V2_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WDR6500_V2_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:white:system", ++ .gpio = TL_WDR6500_V2_GPIO_LED_SYS, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wdr6500_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WDR6500_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WDR6500_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++ ++static void __init tl_ap151_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f00fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&tl_wdr6500_v2_flash_data); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* WAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ /* LAN */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ ath79_init_mac(tmpmac, mac, -1); ++ ath79_register_wmac(ee + TL_WDR6500_V2_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_register_pci(); ++ ++ ath79_register_usb(); ++} ++ ++static void __init tl_wdr6500_v2_setup(void) ++{ ++ tl_ap151_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wdr6500_v2_leds_gpio), ++ tl_wdr6500_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WDR6500_V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wdr6500_v2_gpio_keys), ++ tl_wdr6500_v2_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WDR6500_V2, "TL-WDR6500-v2", "TP-LINK TL-WDR6500 v2", ++ tl_wdr6500_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wpa8630.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wpa8630.c +new file mode 100644 +index 0000000000..a95a11c122 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wpa8630.c +@@ -0,0 +1,172 @@ ++/* ++ * TP-Link TL-WPA8630 board support ++ * ++ * Copyright (C) 2016 Henryk Heisig ++ * ++ * 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 "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++ ++#define TL_WPA8630_KEYS_POLL_INTERVAL 20 ++#define TL_WPA8630_KEYS_DEBOUNCE_INTERVAL (3 * TL_WPA8630_KEYS_POLL_INTERVAL) ++ ++#define TL_WPA8630_GPIO_LED_POWER 1 ++#define TL_WPA8630_GPIO_LED_LAN 5 ++#define TL_WPA8630_GPIO_LED_WLAN 19 ++#define TL_WPA8630_GPIO_LED_WLAN5 21 ++ ++#define TL_WPA8630_GPIO_BTN_RESET 2 ++#define TL_WPA8630_GPIO_BTN_RFKILL 8 ++#define TL_WPA8630_GPIO_BTN_LED 6 ++#define TL_WPA8630_GPIO_BTN_PAIR 7 ++ ++#define TL_WPA8630_MAC0_OFFSET 0x0000 ++#define TL_WPA8630_WMAC_CALDATA_OFFSET 0x1000 ++#define TL_WPA8630_PCI_CALDATA_OFFSET 0x5000 ++ ++static const char *tl_wpa8630_part_probes[] = { ++ "tp-link-64k", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wpa8630_flash_data = { ++ .part_probes = tl_wpa8630_part_probes, ++ .type = "s25fl064k", ++}; ++ ++static struct gpio_led tl_wpa8630_leds_gpio[] __initdata = { ++ { ++ .name = "tl-wpa8630:green:power", ++ .gpio = TL_WPA8630_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "tl-wpa8630:green:lan", ++ .gpio = TL_WPA8630_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tl-wpa8630:green:wlan", ++ .gpio = TL_WPA8630_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tl-wpa8630:green:wlan5", ++ .gpio = TL_WPA8630_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wpa8630_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WPA8630_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WPA8630_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WPA8630_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WPA8630_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++ { ++ .desc = "LED", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = TL_WPA8630_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WPA8630_GPIO_BTN_LED, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Pair", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = TL_WPA8630_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WPA8630_GPIO_BTN_PAIR, ++ .active_low = 1, ++ }, ++}; ++ ++/* GMAC0 of the QCA8337 switch is connected to the QCA9563 SoC via SGMII */ ++static struct ar8327_pad_cfg tl_wpa8630_qca8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data tl_wpa8630_qca8337_data = { ++ .pad0_cfg = &tl_wpa8630_qca8337_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info tl_wpa8630_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &tl_wpa8630_qca8337_data, ++ }, ++}; ++ ++static void __init tl_wpa8630_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f00fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&tl_wpa8630_flash_data); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + TL_WPA8630_MAC0_OFFSET, 0); ++ ++ platform_device_register(&ath79_mdio0_device); ++ ++ mdiobus_register_board_info(tl_wpa8630_mdio0_info, ++ ARRAY_SIZE(tl_wpa8630_mdio0_info)); ++ ++ /* GMAC0 is connected to an AR8337 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = ~BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art + TL_WPA8630_WMAC_CALDATA_OFFSET, mac); ++ ++ ap91_pci_init(art + TL_WPA8630_PCI_CALDATA_OFFSET, NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wpa8630_leds_gpio), ++ tl_wpa8630_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WPA8630_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wpa8630_gpio_keys), ++ tl_wpa8630_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WPA8630, "TL-WPA8630", "TP-LINK TL-WPA8630", ++ tl_wpa8630_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1041n-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1041n-v2.c +new file mode 100644 +index 0000000000..c98dd4ff00 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1041n-v2.c +@@ -0,0 +1,157 @@ ++/* ++ * TP-LINK TL-WR1041 v2 board support ++ * ++ * Copyright (C) 2010-2012 Gabor Juhos ++ * Copyright (C) 2011-2012 Anan Huang ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR1041NV2_GPIO_BTN_RESET 14 ++#define TL_WR1041NV2_GPIO_LED_WPS 13 ++#define TL_WR1041NV2_GPIO_LED_WLAN 11 ++ ++#define TL_WR1041NV2_GPIO_LED_SYSTEM 12 ++ ++#define TL_WR1041NV2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR1041NV2_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR1041NV2_KEYS_POLL_INTERVAL) ++ ++#define TL_WR1041NV2_PCIE_CALDATA_OFFSET 0x5000 ++ ++static const char *tl_wr1041nv2_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr1041nv2_flash_data = { ++ .part_probes = tl_wr1041nv2_part_probes, ++}; ++ ++static struct gpio_led tl_wr1041nv2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR1041NV2_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wps", ++ .gpio = TL_WR1041NV2_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR1041NV2_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_wr1041nv2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR1041NV2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR1041NV2_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static const struct ar8327_led_info tl_wr1041n_leds_ar8327[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "tp-link:green:wan"), ++ AR8327_LED_INFO(PHY1_0, HW, "tp-link:green:lan1"), ++ AR8327_LED_INFO(PHY2_0, HW, "tp-link:green:lan2"), ++ AR8327_LED_INFO(PHY3_0, HW, "tp-link:green:lan3"), ++ AR8327_LED_INFO(PHY4_0, HW, "tp-link:green:lan4"), ++}; ++ ++static struct ar8327_led_cfg wr1041n_v2_ar8327_led_cfg = { ++ .led_ctrl0 = 0xcf35cf35, /* LED0: blink at 10/100/1000M */ ++ .led_ctrl1 = 0xcf35cf35, /* LED1: blink at 10/100/1000M: anyway, no LED1 on tl-wr1041n */ ++ .led_ctrl2 = 0xcf35cf35, /* LED2: blink at 10/100/1000M: anyway, no LED2 on tl-wr1041n */ ++ .led_ctrl3 = 0x03ffff00, /* Pattern enabled for LED 0-2 of port 1-3 */ ++ .open_drain = true, ++}; ++ ++static struct ar8327_pad_cfg db120_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data db120_ar8327_data = { ++ .pad0_cfg = &db120_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &wr1041n_v2_ar8327_led_cfg, ++ .num_leds = ARRAY_SIZE(tl_wr1041n_leds_ar8327), ++ .leds = tl_wr1041n_leds_ar8327 ++}; ++ ++static struct mdio_board_info db120_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &db120_ar8327_data, ++ }, ++}; ++ ++static void __init tl_wr1041nv2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&tl_wr1041nv2_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr1041nv2_leds_gpio), ++ tl_wr1041nv2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_WR1041NV2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr1041nv2_gpio_keys), ++ tl_wr1041nv2_gpio_keys); ++ ath79_register_wmac(ee, mac); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ++ mdiobus_register_board_info(db120_mdio0_info, ++ ARRAY_SIZE(db120_mdio0_info)); ++ ++ /* GMAC0 is connected to an AR8327 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR1041N_V2, "TL-WR1041N-v2", ++ "TP-LINK TL-WR1041N v2", tl_wr1041nv2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v2.c +new file mode 100644 +index 0000000000..90b649957d +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v2.c +@@ -0,0 +1,215 @@ ++/* ++ * TP-LINK TL-WR1043ND v2 board support ++ * ++ * Copyright (c) 2013 Gabor Juhos ++ * ++ * Based on the Qualcomm Atheros AP135/AP136 reference board support code ++ * Copyright (c) 2012 Qualcomm Atheros ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR1043_V2_GPIO_LED_WLAN 12 ++#define TL_WR1043_V2_GPIO_LED_USB 15 ++#define TL_WR1043_V2_GPIO_LED_WPS 18 ++#define TL_WR1043_V2_GPIO_LED_SYSTEM 19 ++ ++#define TL_WR1043_V2_GPIO_BTN_RESET 16 ++#define TL_WR1043_V2_GPIO_BTN_RFKILL 17 ++ ++#define TL_WR1043_V2_GPIO_USB_POWER 21 ++ ++#define TL_WR1043_V2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR1043_V2_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR1043_V2_KEYS_POLL_INTERVAL) ++ ++#define TL_WR1043_V2_WMAC_CALDATA_OFFSET 0x1000 ++ ++static const char *wr1043nd_v2_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data wr1043nd_v2_flash_data = { ++ .part_probes = wr1043nd_v2_part_probes, ++}; ++ ++static struct gpio_led tl_wr1043_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:wps", ++ .gpio = TL_WR1043_V2_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR1043_V2_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR1043_V2_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb", ++ .gpio = TL_WR1043_V2_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr1043_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR1043_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR1043_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR1043_V2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR1043_V2_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info tl_wr1043_leds_ar8327[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "tp-link:green:lan4"), ++ AR8327_LED_INFO(PHY1_0, HW, "tp-link:green:lan3"), ++ AR8327_LED_INFO(PHY2_0, HW, "tp-link:green:lan2"), ++ AR8327_LED_INFO(PHY3_0, HW, "tp-link:green:lan1"), ++ AR8327_LED_INFO(PHY4_0, HW, "tp-link:green:wan"), ++}; ++ ++/* GMAC0 of the AR8327 switch is connected to the QCA9558 SoC via SGMII */ ++static struct ar8327_pad_cfg wr1043nd_v2_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++/* GMAC6 of the AR8327 switch is connected to the QCA9558 SoC via RGMII */ ++static struct ar8327_pad_cfg wr1043nd_v2_ar8327_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg wr1043nd_v2_ar8327_led_cfg = { ++ .led_ctrl0 = 0xcc35cc35, ++ .led_ctrl1 = 0xca35ca35, ++ .led_ctrl2 = 0xc935c935, ++ .led_ctrl3 = 0x03ffff00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data wr1043nd_v2_ar8327_data = { ++ .pad0_cfg = &wr1043nd_v2_ar8327_pad0_cfg, ++ .pad6_cfg = &wr1043nd_v2_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &wr1043nd_v2_ar8327_led_cfg, ++ .num_leds = ARRAY_SIZE(tl_wr1043_leds_ar8327), ++ .leds = tl_wr1043_leds_ar8327, ++}; ++ ++static struct mdio_board_info wr1043nd_v2_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &wr1043nd_v2_ar8327_data, ++ }, ++}; ++ ++static void __init tl_wr1043nd_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&wr1043nd_v2_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr1043_v2_leds_gpio), ++ tl_wr1043_v2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_WR1043_V2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr1043_v2_gpio_keys), ++ tl_wr1043_v2_gpio_keys); ++ ++ ath79_register_wmac(art + TL_WR1043_V2_WMAC_CALDATA_OFFSET, mac); ++ ++ mdiobus_register_board_info(wr1043nd_v2_mdio0_info, ++ ARRAY_SIZE(wr1043nd_v2_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ++ gpio_request_one(TL_WR1043_V2_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR1043ND_V2, "TL-WR1043ND-v2", ++ "TP-LINK TL-WR1043ND v2", tl_wr1043nd_v2_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v4.c +new file mode 100644 +index 0000000000..04ea49c753 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v4.c +@@ -0,0 +1,283 @@ ++/* ++ * TP-LINK WR1043 V4 support ++ * ++ * Copyright (C) 2015-2016 P. Wassi ++ * Copyright (C) 2016 Matthias Schiffer ++ * Copyright (C) 2016 Andreas Ziegler ++ * Copyright (C) 2016 Ludwig Thomeczek ++ * Copyright (C) 2017 Tim Thorpe ++ * ++ * Derived from: mach-dir-869-a1.c ++ * ++ * 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 ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "nvram.h" ++ ++#define TL_WR1043_V4_GPIO_BTN_RESET 2 ++#define TL_WR1043_V4_GPIO_BTN_RFKILL 5 ++ ++#define TL_WR1043_V4_GPIO_LED_WLAN 19 ++#define TL_WR1043_V4_GPIO_LED_USB 7 ++#define TL_WR1043_V4_GPIO_LED_WPS 1 ++#define TL_WR1043_V4_GPIO_LED_SYSTEM 6 ++ ++#define TL_WR1043_V4_GPIO_USB_POWER 8 ++ ++#define TL_WR1043_V4_GPIO_LED_INET 15 ++#define TL_WR1043_V4_GPIO_LED_WAN 16 ++#define TL_WR1043_V4_GPIO_LED_LAN1 9 ++#define TL_WR1043_V4_GPIO_LED_LAN2 14 ++#define TL_WR1043_V4_GPIO_LED_LAN3 21 ++#define TL_WR1043_V4_GPIO_LED_LAN4 20 ++ ++#define TL_WR1043_V4_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR1043_V4_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR1043_V4_KEYS_POLL_INTERVAL) ++ ++#define TL_WR1043_V4_MAC_LOCATION 0x1ff50008 ++ ++#define TL_WR1043_V4_EEPROM_ADDR 0x1fff0000 ++#define TL_WR1043_V4_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define TL_WR1043_V5_MAC_LOCATION 0x1ff00008 ++ ++static struct gpio_led tl_wr1043nd_v4_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:wps", ++ .gpio = TL_WR1043_V4_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR1043_V4_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR1043_V4_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:usb", ++ .gpio = TL_WR1043_V4_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR1043_V4_GPIO_LED_INET, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:orange:wan", ++ .gpio = TL_WR1043_V4_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr1043nd_v4_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR1043_V4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR1043_V4_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR1043_V4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR1043_V4_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg tl_wr1043nd_v4_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data tl_wr1043nd_v4_ar8327_data = { ++ .pad0_cfg = &tl_wr1043nd_v4_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info tl_wr1043nd_v4_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &tl_wr1043nd_v4_ar8327_data, ++ }, ++}; ++ ++static void __init tl_wr1043nd_v4_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(TL_WR1043_V4_MAC_LOCATION); ++ u8 *eeprom = (u8 *) KSEG1ADDR(TL_WR1043_V4_EEPROM_ADDR); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ mdiobus_register_board_info(tl_wr1043nd_v4_mdio0_info, ++ ARRAY_SIZE(tl_wr1043nd_v4_mdio0_info)); ++ ++ ath79_register_usb(); ++ ath79_register_mdio(0, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(eeprom + TL_WR1043_V4_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr1043nd_v4_leds_gpio), ++ tl_wr1043nd_v4_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR1043_V4_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr1043nd_v4_gpio_keys), ++ tl_wr1043nd_v4_gpio_keys); ++ ++ gpio_request_one(TL_WR1043_V4_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR1043ND_V4, "TL-WR1043ND-v4", ++ "TP-LINK TL-WR1043ND v4", tl_wr1043nd_v4_setup); ++ ++static struct gpio_led tl_wr1043n_v5_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:wps", ++ .gpio = TL_WR1043_V4_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR1043_V4_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR1043_V4_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR1043_V4_GPIO_LED_INET, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:orange:wan", ++ .gpio = TL_WR1043_V4_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, ++}; ++ ++/* The 1043Nv5 is identical to the 1043NDv4, ++ * only missing the usb and small firmware layout changes */ ++static void __init tl_wr1043nv5_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(TL_WR1043_V4_EEPROM_ADDR); ++ u8 *mac = (u8 *) KSEG1ADDR(TL_WR1043_V5_MAC_LOCATION); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr1043n_v5_leds_gpio), ++ tl_wr1043n_v5_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_WR1043_V4_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr1043nd_v4_gpio_keys), ++ tl_wr1043nd_v4_gpio_keys); ++ ++ platform_device_register(&ath79_mdio0_device); ++ ++ mdiobus_register_board_info(tl_wr1043nd_v4_mdio0_info, ++ ARRAY_SIZE(tl_wr1043nd_v4_mdio0_info)); ++ ++ ath79_register_wmac(art + TL_WR1043_V4_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ /* GMAC0 is connected to an AR8337 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR1043N_V5, "TL-WR1043N-v5", "TP-LINK TL-WR1043N v5", ++ tl_wr1043nv5_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd.c +new file mode 100644 +index 0000000000..4e4b85d736 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd.c +@@ -0,0 +1,141 @@ ++/* ++ * TP-LINK TL-WR1043N/ND board support ++ * ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR1043ND_GPIO_LED_USB 1 ++#define TL_WR1043ND_GPIO_LED_SYSTEM 2 ++#define TL_WR1043ND_GPIO_LED_QSS 5 ++#define TL_WR1043ND_GPIO_LED_WLAN 9 ++ ++#define TL_WR1043ND_GPIO_BTN_RESET 3 ++#define TL_WR1043ND_GPIO_BTN_QSS 7 ++ ++#define TL_WR1043ND_GPIO_RTL8366_SDA 18 ++#define TL_WR1043ND_GPIO_RTL8366_SCK 19 ++ ++#define TL_WR1043ND_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR1043ND_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR1043ND_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr1043nd_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr1043nd_flash_data = { ++ .part_probes = tl_wr1043nd_part_probes, ++}; ++ ++static struct gpio_led tl_wr1043nd_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:usb", ++ .gpio = TL_WR1043ND_GPIO_LED_USB, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR1043ND_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR1043ND_GPIO_LED_QSS, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR1043ND_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_wr1043nd_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR1043ND_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR1043ND_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR1043ND_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR1043ND_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static void tl_wr1043nd_rtl8366rb_hw_reset(struct rtl8366_smi *smi, bool active) ++{ ++ if (active) ++ ath79_device_reset_set(AR71XX_RESET_GE0_PHY); ++ else ++ ath79_device_reset_clear(AR71XX_RESET_GE0_PHY); ++} ++ ++static struct rtl8366_platform_data tl_wr1043nd_rtl8366rb_data = { ++ .gpio_sda = TL_WR1043ND_GPIO_RTL8366_SDA, ++ .gpio_sck = TL_WR1043ND_GPIO_RTL8366_SCK, ++ .hw_reset = tl_wr1043nd_rtl8366rb_hw_reset, ++}; ++ ++static struct platform_device tl_wr1043nd_rtl8366rb_device = { ++ .name = RTL8366RB_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &tl_wr1043nd_rtl8366rb_data, ++ } ++}; ++ ++static void __init tl_wr1043nd_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ tl_wr1043nd_rtl8366rb_hw_reset(NULL, true); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.mii_bus_dev = &tl_wr1043nd_rtl8366rb_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_pll_data.pll_1000 = 0x1a000000; ++ ++ ath79_register_eth(0); ++ ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(&tl_wr1043nd_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr1043nd_leds_gpio), ++ tl_wr1043nd_leds_gpio); ++ ++ platform_device_register(&tl_wr1043nd_rtl8366rb_device); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR1043ND_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr1043nd_gpio_keys), ++ tl_wr1043nd_gpio_keys); ++ ++ ath79_register_wmac(eeprom, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR1043ND, "TL-WR1043ND", "TP-LINK TL-WR1043ND", ++ tl_wr1043nd_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr2543n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr2543n.c +new file mode 100644 +index 0000000000..141914aa29 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr2543n.c +@@ -0,0 +1,150 @@ ++/* ++ * TP-LINK TL-WR2543N/ND board support ++ * ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define TL_WR2543N_GPIO_LED_WPS 0 ++#define TL_WR2543N_GPIO_LED_USB 8 ++ ++/* The WLAN LEDs use GPIOs on the discrete AR9380 wmac */ ++#define TL_WR2543N_GPIO_WMAC_LED_WLAN2G 0 ++#define TL_WR2543N_GPIO_WMAC_LED_WLAN5G 1 ++ ++#define TL_WR2543N_GPIO_BTN_RESET 11 ++#define TL_WR2543N_GPIO_BTN_WPS 12 ++ ++#define TL_WR2543N_GPIO_RTL8367_SDA 1 ++#define TL_WR2543N_GPIO_RTL8367_SCK 6 ++ ++#define TL_WR2543N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR2543N_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR2543N_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr2543n_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr2543n_flash_data = { ++ .part_probes = tl_wr2543n_part_probes, ++}; ++ ++static struct gpio_led tl_wr2543n_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:usb", ++ .gpio = TL_WR2543N_GPIO_LED_USB, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wps", ++ .gpio = TL_WR2543N_GPIO_LED_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led tl_wr2543n_wmac_leds_gpio[] = { ++ { ++ .name = "tp-link:green:wlan2g", ++ .gpio = TL_WR2543N_GPIO_WMAC_LED_WLAN2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan5g", ++ .gpio = TL_WR2543N_GPIO_WMAC_LED_WLAN5G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr2543n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR2543N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR2543N_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR2543N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR2543N_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct rtl8367_extif_config tl_wr2543n_rtl8367_extif0_cfg = { ++ .mode = RTL8367_EXTIF_MODE_RGMII, ++ .txdelay = 1, ++ .rxdelay = 0, ++ .ability = { ++ .force_mode = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ .link = 1, ++ .duplex = 1, ++ .speed = RTL8367_PORT_SPEED_1000, ++ }, ++}; ++ ++static struct rtl8367_platform_data tl_wr2543n_rtl8367_data = { ++ .gpio_sda = TL_WR2543N_GPIO_RTL8367_SDA, ++ .gpio_sck = TL_WR2543N_GPIO_RTL8367_SCK, ++ .extif0_cfg = &tl_wr2543n_rtl8367_extif0_cfg, ++}; ++ ++static struct platform_device tl_wr2543n_rtl8367_device = { ++ .name = RTL8367_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &tl_wr2543n_rtl8367_data, ++ } ++}; ++ ++static void __init tl_wr2543n_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&tl_wr2543n_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr2543n_leds_gpio), ++ tl_wr2543n_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_WR2543N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr2543n_gpio_keys), ++ tl_wr2543n_gpio_keys); ++ ath79_register_usb(); ++ ++ ap9x_pci_setup_wmac_leds(0, tl_wr2543n_wmac_leds_gpio, ++ ARRAY_SIZE(tl_wr2543n_wmac_leds_gpio)); ++ ap91_pci_init(eeprom, mac); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); ++ ath79_eth0_data.mii_bus_dev = &tl_wr2543n_rtl8367_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_pll_data.pll_1000 = 0x1a000000; ++ ++ ath79_register_eth(0); ++ ++ platform_device_register(&tl_wr2543n_rtl8367_device); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR2543N, "TL-WR2543N", "TP-LINK TL-WR2543N/ND", ++ tl_wr2543n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr703n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr703n.c +new file mode 100644 +index 0000000000..1d8d01cc63 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr703n.c +@@ -0,0 +1,118 @@ ++/* ++ * TP-LINK TL-WR703N/TL-MR10U board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR703N_GPIO_LED_SYSTEM 27 ++#define TL_WR703N_GPIO_BTN_RESET 11 ++ ++#define TL_WR703N_GPIO_USB_POWER 8 ++ ++#define TL_MR10U_GPIO_USB_POWER 18 ++ ++#define TL_WR703N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR703N_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR703N_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr703n_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr703n_flash_data = { ++ .part_probes = tl_wr703n_part_probes, ++}; ++ ++static struct gpio_led tl_wr703n_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:system", ++ .gpio = TL_WR703N_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr703n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR703N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR703N_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static void __init common_setup(unsigned usb_power_gpio, bool sec_ethernet) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_m25p80(&tl_wr703n_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr703n_leds_gpio), ++ tl_wr703n_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_WR703N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr703n_gpio_keys), ++ tl_wr703n_gpio_keys); ++ ++ gpio_request_one(usb_power_gpio, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ++ if (sec_ethernet) ++ { ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ath79_register_eth(1); ++ } ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init tl_mr10u_setup(void) ++{ ++ common_setup(TL_MR10U_GPIO_USB_POWER, false); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR10U, "TL-MR10U", "TP-LINK TL-MR10U", ++ tl_mr10u_setup); ++ ++static void __init tl_wr703n_setup(void) ++{ ++ common_setup(TL_WR703N_GPIO_USB_POWER, false); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR703N, "TL-WR703N", "TP-LINK TL-WR703N v1", ++ tl_wr703n_setup); ++ ++static void __init tl_wr710n_setup(void) ++{ ++ common_setup(TL_WR703N_GPIO_USB_POWER, true); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR710N, "TL-WR710N", "TP-LINK TL-WR710N v1", ++ tl_wr710n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr720n-v3.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr720n-v3.c +new file mode 100644 +index 0000000000..2bb3b44a71 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr720n-v3.c +@@ -0,0 +1,108 @@ ++/* ++ * TP-LINK TL-WR720N board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 Gabor Juhos ++ * Copyright (C) 2013 yousong ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR720N_GPIO_LED_SYSTEM 27 ++#define TL_WR720N_GPIO_BTN_RESET 11 ++#define TL_WR720N_GPIO_BTN_SW1 18 ++#define TL_WR720N_GPIO_BTN_SW2 20 ++ ++#define TL_WR720N_GPIO_USB_POWER 8 ++ ++#define TL_WR720N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR720N_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR720N_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr720n_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr720n_flash_data = { ++ .part_probes = tl_wr720n_part_probes, ++}; ++ ++static struct gpio_led tl_wr720n_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:system", ++ .gpio = TL_WR720N_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr720n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR720N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR720N_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, { ++ .desc = "sw1", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = TL_WR720N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR720N_GPIO_BTN_SW1, ++ .active_low = 0, ++ }, { ++ .desc = "sw2", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = TL_WR720N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR720N_GPIO_BTN_SW2, ++ .active_low = 0, ++ } ++}; ++ ++static void __init tl_wr720n_v3_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_m25p80(&tl_wr720n_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr720n_leds_gpio), ++ tl_wr720n_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_WR720N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr720n_gpio_keys), ++ tl_wr720n_gpio_keys); ++ ++ gpio_request_one(TL_WR720N_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 2); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR720N_V3, "TL-WR720N-v3", "TP-LINK TL-WR720N v3/v4", ++ tl_wr720n_v3_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd-v4.c +new file mode 100644 +index 0000000000..851b7624ff +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd-v4.c +@@ -0,0 +1,187 @@ ++/* ++ * TP-LINK TL-WR741ND v4/TL-MR3220 v2 board support ++ * ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR741NDV4_GPIO_BTN_RESET 11 ++#define TL_WR741NDV4_GPIO_BTN_WPS 26 ++ ++#define TL_WR741NDV4_GPIO_LED_WLAN 0 ++#define TL_WR741NDV4_GPIO_LED_QSS 1 ++#define TL_WR741NDV4_GPIO_LED_WAN 13 ++#define TL_WR741NDV4_GPIO_LED_LAN1 14 ++#define TL_WR741NDV4_GPIO_LED_LAN2 15 ++#define TL_WR741NDV4_GPIO_LED_LAN3 16 ++#define TL_WR741NDV4_GPIO_LED_LAN4 17 ++#define TL_WR741NDV4_GPIO_LED_SYSTEM 27 ++ ++#define TL_MR3220V2_GPIO_BTN_WPS 11 ++#define TL_MR3220V2_GPIO_BTN_WIFI 24 ++ ++#define TL_MR3220V2_GPIO_LED_3G 26 ++#define TL_MR3220V2_GPIO_USB_POWER 8 ++ ++#define TL_WR741NDV4_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR741NDV4_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR741NDV4_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr741ndv4_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr741ndv4_flash_data = { ++ .part_probes = tl_wr741ndv4_part_probes, ++}; ++ ++static struct gpio_led tl_wr741ndv4_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR741NDV4_GPIO_LED_LAN1, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR741NDV4_GPIO_LED_LAN2, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR741NDV4_GPIO_LED_LAN3, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR741NDV4_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR741NDV4_GPIO_LED_QSS, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR741NDV4_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR741NDV4_GPIO_LED_WAN, ++ .active_low = 0, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR741NDV4_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, { ++ /* the 3G LED is only present on the MR3220 v2 */ ++ .name = "tp-link:green:3g", ++ .gpio = TL_MR3220V2_GPIO_LED_3G, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr741ndv4_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR741NDV4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR741NDV4_GPIO_BTN_RESET, ++ .active_low = 0, ++ }, { ++ .desc = "WPS", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR741NDV4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR741NDV4_GPIO_BTN_WPS, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button tl_mr3220v2_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR741NDV4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3220V2_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, { ++ .desc = "WIFI button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR741NDV4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_MR3220V2_GPIO_BTN_WIFI, ++ .active_low = 0, ++ } ++}; ++ ++static void __init tl_ap121_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_setup_ar933x_phy4_switch(true, true); ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_m25p80(&tl_wr741ndv4_flash_data); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init tl_wr741ndv4_setup(void) ++{ ++ tl_ap121_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr741ndv4_leds_gpio) - 1, ++ tl_wr741ndv4_leds_gpio); ++ ath79_register_gpio_keys_polled(1, TL_WR741NDV4_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr741ndv4_gpio_keys), ++ tl_wr741ndv4_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR741ND_V4, "TL-WR741ND-v4", ++ "TP-LINK TL-WR741ND v4", tl_wr741ndv4_setup); ++ ++static void __init tl_mr3220v2_setup(void) ++{ ++ tl_ap121_setup(); ++ ++ gpio_request_one(TL_MR3220V2_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr741ndv4_leds_gpio), ++ tl_wr741ndv4_leds_gpio); ++ ath79_register_gpio_keys_polled(1, TL_WR741NDV4_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_mr3220v2_gpio_keys), ++ tl_mr3220v2_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR3220_V2, "TL-MR3220-v2", ++ "TP-LINK TL-MR3220 v2", tl_mr3220v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd.c +new file mode 100644 +index 0000000000..5931654bbd +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr741nd.c +@@ -0,0 +1,130 @@ ++/* ++ * TP-LINK TL-WR741ND board support ++ * ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define TL_WR741ND_GPIO_LED_QSS 0 ++#define TL_WR741ND_GPIO_LED_SYSTEM 1 ++#define TL_WR741ND_GPIO_LED_LAN1 13 ++#define TL_WR741ND_GPIO_LED_LAN2 14 ++#define TL_WR741ND_GPIO_LED_LAN3 15 ++#define TL_WR741ND_GPIO_LED_LAN4 16 ++#define TL_WR741ND_GPIO_LED_WAN 17 ++ ++#define TL_WR741ND_GPIO_BTN_RESET 11 ++#define TL_WR741ND_GPIO_BTN_QSS 12 ++ ++#define TL_WR741ND_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR741ND_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR741ND_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr741nd_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr741nd_flash_data = { ++ .part_probes = tl_wr741nd_part_probes, ++}; ++ ++static struct gpio_led tl_wr741nd_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR741ND_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR741ND_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR741ND_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR741ND_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR741ND_GPIO_LED_QSS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR741ND_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR741ND_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr741nd_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR741ND_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR741ND_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR741ND_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR741ND_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init tl_wr741nd_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&tl_wr741nd_flash_data); ++ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr741nd_leds_gpio), ++ tl_wr741nd_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR741ND_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr741nd_gpio_keys), ++ tl_wr741nd_gpio_keys); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ ap9x_pci_setup_wmac_led_pin(0, 1); ++ ap91_pci_init(ee, mac); ++} ++MIPS_MACHINE(ATH79_MACH_TL_WR741ND, "TL-WR741ND", "TP-LINK TL-WR741ND", ++ tl_wr741nd_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr802n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr802n.c +new file mode 100644 +index 0000000000..514529ca18 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr802n.c +@@ -0,0 +1,117 @@ ++/* ++ * TP-LINK TL-WR802N v1, v2 ++ * ++ * Copyright (C) 2015 Rick Pannen > ++ * Copyright (C) 2016 Thomas Roberts > ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR802N_GPIO_LED_SYSTEM 13 ++#define TL_WR802N_GPIO_BTN_RESET 12 ++ ++#define TL_WR802N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR802N_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR802N_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr802n_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr802n_flash_data = { ++ .part_probes = tl_wr802n_part_probes, ++}; ++ ++static struct gpio_led tl_wr802n_v1_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:system", ++ .gpio = TL_WR802N_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led tl_wr802n_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tl-wr802n-v2:green:system", ++ .gpio = TL_WR802N_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr802n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR802N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR802N_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init tl_ap143_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&tl_wr802n_flash_data); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ ath79_init_mac(tmpmac, mac, 0); ++ ath79_register_wmac(ee, tmpmac); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR802N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr802n_gpio_keys), ++ tl_wr802n_gpio_keys); ++} ++ ++static void __init tl_wr802n_v1_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr802n_v1_leds_gpio), ++ tl_wr802n_v1_leds_gpio); ++} ++ ++static void __init tl_wr802n_v2_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr802n_v2_leds_gpio), ++ tl_wr802n_v2_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR802N_V1, "TL-WR802N-v1", "TP-LINK TL-WR802N v1", ++ tl_wr802n_v1_setup); ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR802N_V2, "TL-WR802N-v2", "TP-LINK TL-WR802N v2", ++ tl_wr802n_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr810n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr810n.c +new file mode 100644 +index 0000000000..588bb9d861 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr810n.c +@@ -0,0 +1,149 @@ ++/* ++ * TP-LINK TL-WR810N board support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012 Gabor Juhos ++ * Copyright (c) 2016 Jens Steinhauser ++ * ++ * 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 "common.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR810N_GPIO_SWITCH_B1 0 ++#define TL_WR810N_GPIO_SWITCH_B0 1 ++#define TL_WR810N_GPIO_USB_POWER 11 ++#define TL_WR810N_GPIO_BTN_RESET 12 ++#define TL_WR810N_GPIO_LED_SYSTEM 13 ++ ++#define TL_WR810N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR810N_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR810N_KEYS_POLL_INTERVAL) ++ ++#define TL_WR810N_WMAC_CALDATA_OFFSET 0x1000 ++ ++static const char *tl_wr810n_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr810n_flash_data = { ++ .part_probes = tl_wr810n_part_probes, ++}; ++ ++static struct gpio_led tl_wr810n_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:system", ++ .gpio = TL_WR810N_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr810n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR810N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR810N_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "switch_b0", ++ .type = EV_SW, ++ .code = BTN_0, ++ .debounce_interval = TL_WR810N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR810N_GPIO_SWITCH_B0, ++ .active_low = 0, ++ }, ++ { ++ .desc = "switch_b1", ++ .type = EV_SW, ++ .code = BTN_1, ++ .debounce_interval = TL_WR810N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR810N_GPIO_SWITCH_B1, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init tl_ap143_setup(int lan_mac_offset) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&tl_wr810n_flash_data); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* WAN */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ /* LAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, lan_mac_offset); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + TL_WR810N_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_register_leds_gpio(-1, ++ ARRAY_SIZE(tl_wr810n_leds_gpio), ++ tl_wr810n_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, ++ TL_WR810N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr810n_gpio_keys), ++ tl_wr810n_gpio_keys); ++} ++ ++static void __init tl_wr810n_setup(void) ++{ ++ tl_ap143_setup(-1); ++ ++ gpio_request_one(TL_WR810N_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++} ++ ++static void __init tl_wr810n_v2_setup(void) ++{ ++ tl_ap143_setup(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR810N, "TL-WR810N", "TP-LINK TL-WR810N", ++ tl_wr810n_setup); ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR810N_V2, "TL-WR810N-v2", "TP-LINK TL-WR810N v2", ++ tl_wr810n_v2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c +new file mode 100644 +index 0000000000..73cfdd9cc6 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c +@@ -0,0 +1,286 @@ ++/* ++ * TP-LINK TL-WR841N/ND v8/TL-MR3420 v2 board support ++ * ++ * Copyright (C) 2012 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR841NV8_GPIO_LED_WLAN 13 ++#define TL_WR841NV8_GPIO_LED_QSS 15 ++#define TL_WR841NV8_GPIO_LED_WAN 18 ++#define TL_WR841NV8_GPIO_LED_LAN1 19 ++#define TL_WR841NV8_GPIO_LED_LAN2 20 ++#define TL_WR841NV8_GPIO_LED_LAN3 21 ++#define TL_WR841NV8_GPIO_LED_LAN4 12 ++#define TL_WR841NV8_GPIO_LED_SYSTEM 14 ++ ++#define TL_WR841NV8_GPIO_BTN_RESET 17 ++#define TL_WR841NV8_GPIO_SW_RFKILL 16 /* WPS for MR3420 v2 */ ++ ++#define TL_MR3420V2_GPIO_LED_3G 11 ++#define TL_MR3420V2_GPIO_USB_POWER 4 ++ ++#define TL_WR941NDV5_GPIO_LED_WLAN 13 ++#define TL_WR941NDV5_GPIO_LED_QSS 15 ++#define TL_WR941NDV5_GPIO_LED_WAN 18 ++#define TL_WR941NDV5_GPIO_LED_LAN1 19 ++#define TL_WR941NDV5_GPIO_LED_LAN2 20 ++#define TL_WR941NDV5_GPIO_LED_LAN3 2 ++#define TL_WR941NDV5_GPIO_LED_LAN4 3 ++#define TL_WR941NDV5_GPIO_LED_SYSTEM 14 ++ ++#define TL_WR841NV8_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR841NV8_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr841n_v8_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr841n_v8_flash_data = { ++ .part_probes = tl_wr841n_v8_part_probes, ++}; ++ ++static struct gpio_led tl_wr841n_v8_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR841NV8_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR841NV8_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR841NV8_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR841NV8_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR841NV8_GPIO_LED_QSS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR841NV8_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR841NV8_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR841NV8_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ /* the 3G LED is only present on the MR3420 v2 */ ++ .name = "tp-link:green:3g", ++ .gpio = TL_MR3420V2_GPIO_LED_3G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr841n_v8_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR841NV8_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "RFKILL switch", ++ .type = EV_SW, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR841NV8_GPIO_SW_RFKILL, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button tl_mr3420v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR841NV8_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "WPS", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR841NV8_GPIO_SW_RFKILL, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_led tl_wr941nd_v5_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR941NDV5_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR941NDV5_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR941NDV5_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR941NDV5_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR941NDV5_GPIO_LED_QSS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR941NDV5_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR941NDV5_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR941NDV5_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init tl_ap123_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* Disable JTAG, enabling GPIOs 0-3 */ ++ /* Configure OBS4 line, for GPIO 4*/ ++ ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE, ++ AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ++ /* config gpio4 as normal gpio function */ ++ ath79_gpio_output_select(TL_MR3420V2_GPIO_USB_POWER, ++ AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_m25p80(&tl_wr841n_v8_flash_data); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++static void __init tl_wr841n_v8_setup(void) ++{ ++ tl_ap123_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v8_leds_gpio) - 1, ++ tl_wr841n_v8_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV8_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr841n_v8_gpio_keys), ++ tl_wr841n_v8_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR841N_V8, "TL-WR841N-v8", "TP-LINK TL-WR841N/ND v8", ++ tl_wr841n_v8_setup); ++ ++ ++static void __init tl_wr842n_v2_setup(void) ++{ ++ tl_ap123_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v8_leds_gpio), ++ tl_wr841n_v8_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV8_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr841n_v8_gpio_keys), ++ tl_wr841n_v8_gpio_keys); ++ ++ gpio_request_one(TL_MR3420V2_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR842N_V2, "TL-WR842N-v2", "TP-LINK TL-WR842N/ND v2", ++ tl_wr842n_v2_setup); ++ ++static void __init tl_mr3420v2_setup(void) ++{ ++ tl_ap123_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v8_leds_gpio), ++ tl_wr841n_v8_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV8_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_mr3420v2_gpio_keys), ++ tl_mr3420v2_gpio_keys); ++ ++ /* enable power for the USB port */ ++ gpio_request_one(TL_MR3420V2_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_MR3420_V2, "TL-MR3420-v2", "TP-LINK TL-MR3420 v2", ++ tl_mr3420v2_setup); ++ ++ ++static void __init tl_wr941nd_v5_setup(void) ++{ ++ tl_ap123_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr941nd_v5_leds_gpio), ++ tl_wr941nd_v5_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV8_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr841n_v8_gpio_keys), ++ tl_wr841n_v8_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR941ND_V5, "TL-WR941ND-v5", "TP-LINK TL-WR941N/ND v5", ++ tl_wr941nd_v5_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v9.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v9.c +new file mode 100644 +index 0000000000..304d8ff6e9 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v9.c +@@ -0,0 +1,457 @@ ++/* ++ * TP-LINK TL-WR840N v2/v3 / TL-WR841N/ND v9/v11 / TL-WR842N/ND v3 ++ * ++ * Copyright (C) 2014 Matthias Schiffer ++ * Copyright (C) 2016 Cezary Jackiewicz ++ * Copyright (C) 2016 Stijn Segers ++ * Copyright (C) 2017 Vaclav Svoboda ++ * Copyright (C) 2017 Andrey Polischuk ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR840NV2_GPIO_LED_SYSTEM 15 ++#define TL_WR840NV2_GPIO_LED_WLAN 13 ++#define TL_WR840NV2_GPIO_LED_WPS 3 ++#define TL_WR840NV2_GPIO_LED_WAN 4 ++#define TL_WR840NV2_GPIO_LED_LAN 16 ++ ++#define TL_WR840NV2_GPIO_BTN_RESET 12 ++ ++#define TL_WR841NV9_GPIO_LED_WLAN 13 ++#define TL_WR841NV9_GPIO_LED_QSS 3 ++#define TL_WR841NV9_GPIO_LED_WAN 4 ++#define TL_WR841NV9_GPIO_LED_LAN1 16 ++#define TL_WR841NV9_GPIO_LED_LAN2 15 ++#define TL_WR841NV9_GPIO_LED_LAN3 14 ++#define TL_WR841NV9_GPIO_LED_LAN4 11 ++ ++#define TL_WR841NV9_GPIO_BTN_RESET 12 ++#define TL_WR841NV9_GPIO_BTN_WIFI 17 ++ ++#define TL_WR841NV11_GPIO_LED_SYSTEM 1 ++#define TL_WR841NV11_GPIO_LED_QSS 3 ++#define TL_WR841NV11_GPIO_LED_WAN 4 ++#define TL_WR841NV11_GPIO_LED_WAN_STATUS 2 ++#define TL_WR841NV11_GPIO_LED_WLAN 13 ++#define TL_WR841NV11_GPIO_LED_LAN1 16 ++#define TL_WR841NV11_GPIO_LED_LAN2 15 ++#define TL_WR841NV11_GPIO_LED_LAN3 14 ++#define TL_WR841NV11_GPIO_LED_LAN4 11 ++ ++#define TL_WR841NV11_GPIO_BTN_RESET 12 ++#define TL_WR841NV11_GPIO_BTN_WIFI 17 ++ ++#define TL_WR842NV3_GPIO_LED_SYSTEM 2 ++#define TL_WR842NV3_GPIO_LED_WLAN 3 ++#define TL_WR842NV3_GPIO_LED_WAN_RED 4 ++#define TL_WR842NV3_GPIO_LED_WAN_GREEN 11 ++#define TL_WR842NV3_GPIO_LED_LAN1 12 ++#define TL_WR842NV3_GPIO_LED_LAN2 13 ++#define TL_WR842NV3_GPIO_LED_LAN3 14 ++#define TL_WR842NV3_GPIO_LED_LAN4 15 ++#define TL_WR842NV3_GPIO_LED_3G 16 ++#define TL_WR842NV3_GPIO_LED_WPS 17 ++ ++#define TL_WR842NV3_GPIO_BTN_RESET 1 ++#define TL_WR842NV3_GPIO_BTN_WIFI 0 ++ ++#define TL_WR740NV6_GPIO_LED_SYSTEM 1 ++#define TL_WR740NV6_GPIO_LED_QSS 3 ++#define TL_WR740NV6_GPIO_LED_WAN_ORANGE 2 ++#define TL_WR740NV6_GPIO_LED_WAN_GREEN 4 ++#define TL_WR740NV6_GPIO_LED_LAN1 16 ++#define TL_WR740NV6_GPIO_LED_LAN2 15 ++#define TL_WR740NV6_GPIO_LED_LAN3 14 ++#define TL_WR740NV6_GPIO_LED_LAN4 11 ++#define TL_WR740NV6_GPIO_LED_WLAN 13 ++ ++#define TL_WR740NV6_GPIO_BTN_RESET 12 ++#define TL_WR740NV6_GPIO_BTN_WIFI 17 ++ ++#define TL_WR841NV9_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR841NV9_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR841NV9_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr841n_v9_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr841n_v9_flash_data = { ++ .part_probes = tl_wr841n_v9_part_probes, ++}; ++ ++static struct gpio_led tl_wr840n_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR840NV2_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan", ++ .gpio = TL_WR840NV2_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wps", ++ .gpio = TL_WR840NV2_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR840NV2_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR840NV2_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr840n_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR841NV9_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR840NV2_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led tl_wr841n_v9_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR841NV9_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR841NV9_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR841NV9_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR841NV9_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR841NV9_GPIO_LED_QSS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR841NV9_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR841NV9_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr841n_v9_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR841NV9_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR841NV9_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "WIFI button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR841NV9_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR841NV9_GPIO_BTN_WIFI, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led tl_wr841n_v11_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR841NV9_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR841NV9_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR841NV9_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR841NV9_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR841NV9_GPIO_LED_QSS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR841NV11_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR841NV9_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan_status", ++ .gpio = TL_WR841NV11_GPIO_LED_WAN_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR841NV9_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led tl_wr842n_v3_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR842NV3_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR842NV3_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR842NV3_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR842NV3_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR842NV3_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:red:wan", ++ .gpio = TL_WR842NV3_GPIO_LED_WAN_RED, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR842NV3_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR842NV3_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:3g", ++ .gpio = TL_WR842NV3_GPIO_LED_3G, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wps", ++ .gpio = TL_WR842NV3_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr842n_v3_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR841NV9_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR842NV3_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "WIFI button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR841NV9_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR842NV3_GPIO_BTN_WIFI, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led tl_wr740n_v6_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR740NV6_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR740NV6_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR740NV6_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR740NV6_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR740NV6_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR740NV6_GPIO_LED_QSS, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR740NV6_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:orange:wan", ++ .gpio = TL_WR740NV6_GPIO_LED_WAN_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR740NV6_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr740n_v6_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR841NV9_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR740NV6_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "WIFI button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR841NV9_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR740NV6_GPIO_BTN_WIFI, ++ .active_low = 1, ++ } ++}; ++ ++static void __init tl_ap143_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&tl_wr841n_v9_flash_data); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ ath79_init_mac(tmpmac, mac, 0); ++ ath79_register_wmac(ee, tmpmac); ++} ++ ++ ++static void __init tl_wr840n_v2_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr840n_v2_leds_gpio), ++ tl_wr840n_v2_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV9_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr840n_v2_gpio_keys), ++ tl_wr840n_v2_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR840N_V2, "TL-WR840N-v2", "TP-LINK TL-WR840N v2", ++ tl_wr840n_v2_setup); ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR840N_V3, "TL-WR840N-v3", "TP-LINK TL-WR840N v3", ++ tl_wr840n_v2_setup); ++ ++static void __init tl_wr841n_v9_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v9_leds_gpio), ++ tl_wr841n_v9_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV9_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr841n_v9_gpio_keys), ++ tl_wr841n_v9_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR841N_V9, "TL-WR841N-v9", "TP-LINK TL-WR841N/ND v9", ++ tl_wr841n_v9_setup); ++ ++static void __init tl_wr841n_v11_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v11_leds_gpio), ++ tl_wr841n_v11_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV9_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr841n_v9_gpio_keys), ++ tl_wr841n_v9_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR841N_V11, "TL-WR841N-v11", "TP-LINK TL-WR841N/ND v11", ++ tl_wr841n_v11_setup); ++ ++static void __init tl_wr842n_v3_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr842n_v3_leds_gpio), ++ tl_wr842n_v3_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV9_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr842n_v3_gpio_keys), ++ tl_wr842n_v3_gpio_keys); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR842N_V3, "TL-WR842N-v3", "TP-LINK TL-WR842N/ND v3", ++ tl_wr842n_v3_setup); ++ ++static void __init tl_wr740n_v6_setup(void) ++{ ++ tl_ap143_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr740n_v6_leds_gpio), ++ tl_wr740n_v6_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(1, TL_WR841NV9_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr740n_v6_gpio_keys), ++ tl_wr740n_v6_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR740N_V6, "TL-WR740N-v6", "TP-LINK TL-WR740N/ND v6", ++ tl_wr740n_v6_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n.c +new file mode 100644 +index 0000000000..11f853f057 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n.c +@@ -0,0 +1,140 @@ ++/* ++ * TP-LINK TL-WR841N/ND v1 board support ++ * ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "dev-dsa.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define TL_WR841ND_V1_GPIO_LED_SYSTEM 2 ++#define TL_WR841ND_V1_GPIO_LED_QSS_GREEN 4 ++#define TL_WR841ND_V1_GPIO_LED_QSS_RED 5 ++ ++#define TL_WR841ND_V1_GPIO_BTN_RESET 3 ++#define TL_WR841ND_V1_GPIO_BTN_QSS 7 ++ ++#define TL_WR841ND_V1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR841ND_V1_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * TL_WR841ND_V1_KEYS_POLL_INTERVAL) ++ ++static struct mtd_partition tl_wr841n_v1_partitions[] = { ++ { ++ .name = "redboot", ++ .offset = 0, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "kernel", ++ .offset = 0x020000, ++ .size = 0x140000, ++ }, { ++ .name = "rootfs", ++ .offset = 0x160000, ++ .size = 0x280000, ++ }, { ++ .name = "config", ++ .offset = 0x3e0000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x020000, ++ .size = 0x3c0000, ++ } ++}; ++ ++static struct flash_platform_data tl_wr841n_v1_flash_data = { ++ .parts = tl_wr841n_v1_partitions, ++ .nr_parts = ARRAY_SIZE(tl_wr841n_v1_partitions), ++}; ++ ++static struct gpio_led tl_wr841n_v1_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR841ND_V1_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:red:qss", ++ .gpio = TL_WR841ND_V1_GPIO_LED_QSS_RED, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR841ND_V1_GPIO_LED_QSS_GREEN, ++ } ++}; ++ ++static struct gpio_keys_button tl_wr841n_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR841ND_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR841ND_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR841ND_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR841ND_V1_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static struct dsa_chip_data tl_wr841n_v1_dsa_chip = { ++ .port_names[0] = "wan", ++ .port_names[1] = "lan1", ++ .port_names[2] = "lan2", ++ .port_names[3] = "lan3", ++ .port_names[4] = "lan4", ++ .port_names[5] = "cpu", ++}; ++ ++static struct dsa_platform_data tl_wr841n_v1_dsa_data = { ++ .nr_chips = 1, ++ .chip = &tl_wr841n_v1_dsa_chip, ++}; ++ ++static void __init tl_wr841n_v1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ath79_register_dsa(&ath79_eth0_device.dev, &ath79_mdio0_device.dev, ++ &tl_wr841n_v1_dsa_data); ++ ++ ath79_register_m25p80(&tl_wr841n_v1_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v1_leds_gpio), ++ tl_wr841n_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR841ND_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr841n_v1_gpio_keys), ++ tl_wr841n_v1_gpio_keys); ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR841N_V1, "TL-WR841N-v1.5", "TP-LINK TL-WR841N v1", ++ tl_wr841n_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr902ac-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr902ac-v1.c +new file mode 100644 +index 0000000000..8d2cea828a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr902ac-v1.c +@@ -0,0 +1,145 @@ ++/* ++ * TP-Link TL-WR902AC v1 board support ++ * ++ * Copyright (C) 2017 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++#define TL_WR902AC_V1_GPIO_LED_INTERNET 12 ++#define TL_WR902AC_V1_GPIO_LED_LAN 15 ++#define TL_WR902AC_V1_GPIO_LED_POWER 13 ++#define TL_WR902AC_V1_GPIO_LED_USB 4 ++#define TL_WR902AC_V1_GPIO_LED_WLAN2G 11 ++#define TL_WR902AC_V1_GPIO_LED_WPS 0 ++ ++#define TL_WR902AC_V1_GPIO_BTN_RESET 3 ++#define TL_WR902AC_V1_GPIO_BTN_SW1 17 ++#define TL_WR902AC_V1_GPIO_BTN_SW2 14 ++#define TL_WR902AC_V1_GPIO_BTN_WPS 2 ++ ++#define TL_WR902AC_V1_GPIO_USB_POWER 1 ++ ++#define TL_WR902AC_V1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR902AC_V1_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * TL_WR902AC_V1_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led tl_wr902ac_v1_leds_gpio[] __initdata = { ++ { ++ .name = "tl-wr902ac-v1:green:internet", ++ .gpio = TL_WR902AC_V1_GPIO_LED_INTERNET, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr902ac-v1:green:lan", ++ .gpio = TL_WR902AC_V1_GPIO_LED_LAN, ++ .active_low = 0, ++ }, { ++ .name = "tl-wr902ac-v1:green:power", ++ .gpio = TL_WR902AC_V1_GPIO_LED_POWER, ++ .active_low = 0, ++ }, { ++ .name = "tl-wr902ac-v1:green:usb", ++ .gpio = TL_WR902AC_V1_GPIO_LED_USB, ++ .active_low = 0, ++ }, { ++ .name = "tl-wr902ac-v1:green:wlan2g", ++ .gpio = TL_WR902AC_V1_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr902ac-v1:green:wps", ++ .gpio = TL_WR902AC_V1_GPIO_LED_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_wr902ac_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR902AC_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR902AC_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "sw1", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = TL_WR902AC_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR902AC_V1_GPIO_BTN_SW1, ++ .active_low = 1, ++ }, { ++ .desc = "sw2", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = TL_WR902AC_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR902AC_V1_GPIO_BTN_SW2, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR902AC_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR902AC_V1_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init tl_wr902ac_v1_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f7f0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f750008); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr902ac_v1_leds_gpio), ++ tl_wr902ac_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR902AC_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr902ac_v1_gpio_keys), ++ tl_wr902ac_v1_gpio_keys); ++ ++ gpio_request_one(TL_WR902AC_V1_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + 0x1000, mac); ++ ++ ap91_pci_init(art + 0x5000, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR902AC_V1, "TL-WR902AC-V1", "TP-LINK TL-WR902AC v1", ++ tl_wr902ac_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr940n-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr940n-v4.c +new file mode 100644 +index 0000000000..9324b2b924 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr940n-v4.c +@@ -0,0 +1,184 @@ ++/* ++ * TP-LINK TL-WR940N v4 and v6 board support ++ * ++ * Copyright (C) 2016 David Lutz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++#define TL_WR940N_V4_GPIO_LED_QSS 3 ++#define TL_WR940N_V4_GPIO_LED_WAN 14 ++#define TL_WR940N_V4_GPIO_LED_WAN_RED 15 ++#define TL_WR940N_V4_GPIO_LED_LAN4 4 ++#define TL_WR940N_V4_GPIO_LED_LAN3 18 ++#define TL_WR940N_V4_GPIO_LED_LAN2 6 ++#define TL_WR940N_V4_GPIO_LED_LAN1 8 ++#define TL_WR940N_V4_GPIO_LED_WLAN 7 ++#define TL_WR940N_V4_GPIO_LED_SYSTEM 5 ++/* WR940N v6 specific GPIO*/ ++#define TL_WR940N_V6_GPIO_LED_DIAG_ORANGE 15 ++#define TL_WR940N_V6_GPIO_LED_WAN_BLUE 14 ++ ++#define TL_WR940N_V4_GPIO_BTN_RESET 1 ++#define TL_WR940N_V4_GPIO_BTN_RFKILL 2 ++ ++#define TL_WR940N_KEYS_POLL_INTERVAL 20 ++#define TL_WR940N_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR940N_KEYS_POLL_INTERVAL) ++ ++ ++static struct gpio_led tl_wr940n_v4_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:qss", ++ .gpio = TL_WR940N_V4_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:wan", ++ .gpio = TL_WR940N_V4_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:red:wan", ++ .gpio = TL_WR940N_V4_GPIO_LED_WAN_RED, ++ .active_low = 0, ++ }, ++ { ++ .name = "tp-link:blue:lan1", ++ .gpio = TL_WR940N_V4_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:lan2", ++ .gpio = TL_WR940N_V4_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:lan3", ++ .gpio = TL_WR940N_V4_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:lan4", ++ .gpio = TL_WR940N_V4_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:wlan", ++ .gpio = TL_WR940N_V4_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:system", ++ .gpio = TL_WR940N_V4_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr940n_v4_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR940N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR940N_V4_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR940N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR940N_V4_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led tl_wr940n_v6_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:wan", ++ .gpio = TL_WR940N_V6_GPIO_LED_WAN_BLUE, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:orange:diag", ++ .gpio = TL_WR940N_V6_GPIO_LED_DIAG_ORANGE, ++ .active_low = 0, ++ }, ++}; ++ ++ ++static const char *tl_wr940n_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr940n_flash_data = { ++ .part_probes = tl_wr940n_part_probes, ++}; ++ ++ ++static void __init tl_wr940n_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&tl_wr940n_flash_data); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++ ++} ++ ++static void __init tl_wr940n_v4_setup(void) ++{ ++ tl_wr940n_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr940n_v4_leds_gpio), ++ tl_wr940n_v4_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR940N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr940n_v4_gpio_keys), ++ tl_wr940n_v4_gpio_keys); ++} ++ ++static void __init tl_wr940n_v6_setup(void) ++{ ++ tl_wr940n_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr940n_v6_leds_gpio), ++ tl_wr940n_v6_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR940N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr940n_v4_gpio_keys), ++ tl_wr940n_v4_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR940N_V4, "TL-WR940N-v4", "TP-LINK TL-WR940N v4", ++ tl_wr940n_v4_setup); ++MIPS_MACHINE(ATH79_MACH_TL_WR940N_V6, "TL-WR940N-v6", "TP-LINK TL-WR940N v6", ++ tl_wr940n_v6_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr941nd-v6.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr941nd-v6.c +new file mode 100644 +index 0000000000..8c788e2841 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr941nd-v6.c +@@ -0,0 +1,149 @@ ++/* ++ * TP-LINK TL-WR941N/ND v6 board support ++ * ++ * Copyright (C) 2015 Matthias Schiffer ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++#define TL_WR941ND_V6_GPIO_LED_QSS 3 ++#define TL_WR941ND_V6_GPIO_LED_WAN 14 ++#define TL_WR941ND_V6_GPIO_LED_WAN_RED 15 ++#define TL_WR941ND_V6_GPIO_LED_LAN1 7 ++#define TL_WR941ND_V6_GPIO_LED_LAN2 6 ++#define TL_WR941ND_V6_GPIO_LED_LAN3 5 ++#define TL_WR941ND_V6_GPIO_LED_LAN4 4 ++#define TL_WR941ND_V6_GPIO_LED_WLAN 8 ++#define TL_WR941ND_V6_GPIO_LED_SYSTEM 18 ++ ++#define TL_WR941ND_V6_GPIO_BTN_RESET 1 ++#define TL_WR941ND_V6_GPIO_BTN_RFKILL 2 ++ ++#define TL_WR941ND_V6_KEYS_POLL_INTERVAL 20 ++#define TL_WR941ND_V6_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR941ND_V6_KEYS_POLL_INTERVAL) ++ ++ ++static struct gpio_led tl_wr941nd_v6_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:qss", ++ .gpio = TL_WR941ND_V6_GPIO_LED_QSS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:wan", ++ .gpio = TL_WR941ND_V6_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:red:wan", ++ .gpio = TL_WR941ND_V6_GPIO_LED_WAN_RED, ++ .active_low = 0, ++ }, ++ { ++ .name = "tp-link:blue:lan1", ++ .gpio = TL_WR941ND_V6_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:lan2", ++ .gpio = TL_WR941ND_V6_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:lan3", ++ .gpio = TL_WR941ND_V6_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:lan4", ++ .gpio = TL_WR941ND_V6_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:wlan", ++ .gpio = TL_WR941ND_V6_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:blue:system", ++ .gpio = TL_WR941ND_V6_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr941nd_v6_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR941ND_V6_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR941ND_V6_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR941ND_V6_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR941ND_V6_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ } ++}; ++ ++ ++static const char *tl_wr941n_v6_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr941n_v6_flash_data = { ++ .part_probes = tl_wr941n_v6_part_probes, ++}; ++ ++ ++static void __init tl_wr941nd_v6_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(&tl_wr941n_v6_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr941nd_v6_leds_gpio), ++ tl_wr941nd_v6_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR941ND_V6_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr941nd_v6_gpio_keys), ++ tl_wr941nd_v6_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, -1); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, mac); ++ ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR941ND_V6, "TL-WR941ND-v6", "TP-LINK TL-WR941N/ND v6", ++ tl_wr941nd_v6_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr941nd.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr941nd.c +new file mode 100644 +index 0000000000..1ddeec730e +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr941nd.c +@@ -0,0 +1,121 @@ ++/* ++ * TP-LINK TL-WR941ND board support ++ * ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++ ++#include ++ ++#include "dev-dsa.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TL_WR941ND_GPIO_LED_SYSTEM 2 ++#define TL_WR941ND_GPIO_LED_QSS_RED 4 ++#define TL_WR941ND_GPIO_LED_QSS_GREEN 5 ++#define TL_WR941ND_GPIO_LED_WLAN 9 ++ ++#define TL_WR941ND_GPIO_BTN_RESET 3 ++#define TL_WR941ND_GPIO_BTN_QSS 7 ++ ++#define TL_WR941ND_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TL_WR941ND_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR941ND_KEYS_POLL_INTERVAL) ++ ++static const char *tl_wr941nd_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data tl_wr941nd_flash_data = { ++ .part_probes = tl_wr941nd_part_probes, ++}; ++ ++static struct gpio_led tl_wr941nd_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR941ND_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:red:qss", ++ .gpio = TL_WR941ND_GPIO_LED_QSS_RED, ++ }, { ++ .name = "tp-link:green:qss", ++ .gpio = TL_WR941ND_GPIO_LED_QSS_GREEN, ++ }, { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR941ND_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button tl_wr941nd_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR941ND_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR941ND_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = TL_WR941ND_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR941ND_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static struct dsa_chip_data tl_wr941nd_dsa_chip = { ++ .port_names[0] = "wan", ++ .port_names[1] = "lan1", ++ .port_names[2] = "lan2", ++ .port_names[3] = "lan3", ++ .port_names[4] = "lan4", ++ .port_names[5] = "cpu", ++}; ++ ++static struct dsa_platform_data tl_wr941nd_dsa_data = { ++ .nr_chips = 1, ++ .chip = &tl_wr941nd_dsa_chip, ++}; ++ ++static void __init tl_wr941nd_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ath79_register_dsa(&ath79_eth0_device.dev, &ath79_mdio0_device.dev, ++ &tl_wr941nd_dsa_data); ++ ++ ath79_register_m25p80(&tl_wr941nd_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr941nd_leds_gpio), ++ tl_wr941nd_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR941ND_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr941nd_gpio_keys), ++ tl_wr941nd_gpio_keys); ++ ath79_register_wmac(eeprom, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR941ND, "TL-WR941ND", "TP-LINK TL-WR941ND", ++ tl_wr941nd_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr942n-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr942n-v1.c +new file mode 100644 +index 0000000000..32e2bc9521 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr942n-v1.c +@@ -0,0 +1,279 @@ ++/* ++ * TP-Link TL-WR942N(RU) v1 board support ++ * ++ * Copyright (C) 2017 Sergey Studzinski ++ * Thanks to Henryk Heisig ++ * ++ * 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 ++ ++#include "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "nvram.h" ++ ++#define TL_WR942N_V1_KEYS_POLL_INTERVAL 20 ++#define TL_WR942N_V1_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * TL_WR942N_V1_KEYS_POLL_INTERVAL) ++ ++#define TL_WR942N_V1_GPIO_BTN_RESET 1 ++#define TL_WR942N_V1_GPIO_BTN_RFKILL 2 ++ ++#define TL_WR942N_V1_GPIO_UART_TX 4 ++#define TL_WR942N_V1_GPIO_UART_RX 5 ++ ++#define TL_WR942N_V1_GPIO_LED_USB2 14 ++#define TL_WR942N_V1_GPIO_LED_USB1 15 ++ ++#define TL_WR942N_V1_GPIO_SHIFT_OE 16 ++#define TL_WR942N_V1_GPIO_SHIFT_SER 17 ++#define TL_WR942N_V1_GPIO_SHIFT_SRCLK 18 ++#define TL_WR942N_V1_GPIO_SHIFT_SRCLR 19 ++#define TL_WR942N_V1_GPIO_SHIFT_RCLK 20 ++#define TL_WR942N_V1_GPIO_LED_WPS 21 ++#define TL_WR942N_V1_GPIO_LED_STATUS 22 ++ ++#define TL_WR942N_V1_74HC_GPIO_BASE 32 ++#define TL_WR942N_V1_74HC_GPIO_LED_LAN4 (TL_WR942N_V1_74HC_GPIO_BASE + 0) ++#define TL_WR942N_V1_74HC_GPIO_LED_LAN3 (TL_WR942N_V1_74HC_GPIO_BASE + 1) ++#define TL_WR942N_V1_74HC_GPIO_LED_LAN2 (TL_WR942N_V1_74HC_GPIO_BASE + 2) ++#define TL_WR942N_V1_74HC_GPIO_LED_LAN1 (TL_WR942N_V1_74HC_GPIO_BASE + 3) ++#define TL_WR942N_V1_74HC_GPIO_LED_WAN_GREEN (TL_WR942N_V1_74HC_GPIO_BASE + 4) ++#define TL_WR942N_V1_74HC_GPIO_LED_WAN_AMBER (TL_WR942N_V1_74HC_GPIO_BASE + 5) ++#define TL_WR942N_V1_74HC_GPIO_LED_WLAN (TL_WR942N_V1_74HC_GPIO_BASE + 6) ++#define TL_WR942N_V1_74HC_GPIO_HUB_RESET (TL_WR942N_V1_74HC_GPIO_BASE + 7) /* from u-boot sources */ ++ ++#define TL_WR942N_V1_SSR_BIT_0 0 ++#define TL_WR942N_V1_SSR_BIT_1 1 ++#define TL_WR942N_V1_SSR_BIT_2 2 ++#define TL_WR942N_V1_SSR_BIT_3 3 ++#define TL_WR942N_V1_SSR_BIT_4 4 ++#define TL_WR942N_V1_SSR_BIT_5 5 ++#define TL_WR942N_V1_SSR_BIT_6 6 ++#define TL_WR942N_V1_SSR_BIT_7 7 ++ ++#define TL_WR942N_V1_WMAC_CALDATA_OFFSET 0x1000 ++#define TL_WR942N_V1_DEFAULT_MAC_ADDR 0x1fe40008 ++#define TL_WR942N_V1_DEFAULT_MAC_SIZE 0x200 ++ ++#define GPIO_IN_ENABLE0_UART_SIN_LSB 8 ++#define GPIO_IN_ENABLE0_UART_SIN_MASK 0x0000ff00 ++ ++static struct gpio_led tl_wr942n_v1_leds_gpio[] __initdata = { ++ { ++ .name = "tl-wr942n-v1:green:status", ++ .gpio = TL_WR942N_V1_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:wlan", ++ .gpio = TL_WR942N_V1_74HC_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:lan1", ++ .gpio = TL_WR942N_V1_74HC_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:lan2", ++ .gpio = TL_WR942N_V1_74HC_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:lan3", ++ .gpio = TL_WR942N_V1_74HC_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:lan4", ++ .gpio = TL_WR942N_V1_74HC_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:wan", ++ .gpio = TL_WR942N_V1_74HC_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:amber:wan", ++ .gpio = TL_WR942N_V1_74HC_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:wps", ++ .gpio = TL_WR942N_V1_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:usb1", ++ .gpio = TL_WR942N_V1_GPIO_LED_USB1, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr942n-v1:green:usb2", ++ .gpio = TL_WR942N_V1_GPIO_LED_USB2, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button tl_wr942n_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TL_WR942N_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR942N_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = TL_WR942N_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TL_WR942N_V1_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static struct spi_gpio_platform_data tl_wr942n_v1_spi_data = { ++ .sck = TL_WR942N_V1_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = TL_WR942N_V1_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 tl_wr942n_v1_ssr_initdata[] = { ++ BIT(TL_WR942N_V1_SSR_BIT_7) | ++ BIT(TL_WR942N_V1_SSR_BIT_6) | ++ BIT(TL_WR942N_V1_SSR_BIT_5) | ++ BIT(TL_WR942N_V1_SSR_BIT_4) | ++ BIT(TL_WR942N_V1_SSR_BIT_3) | ++ BIT(TL_WR942N_V1_SSR_BIT_2) | ++ BIT(TL_WR942N_V1_SSR_BIT_1) | ++ BIT(TL_WR942N_V1_SSR_BIT_0) ++}; ++ ++static struct gen_74x164_chip_platform_data tl_wr942n_v1_ssr_data = { ++ .base = TL_WR942N_V1_74HC_GPIO_BASE, ++ .num_registers = ARRAY_SIZE(tl_wr942n_v1_ssr_initdata), ++ .init_data = tl_wr942n_v1_ssr_initdata, ++}; ++ ++static struct platform_device tl_wr942n_v1_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &tl_wr942n_v1_spi_data, ++ }, ++}; ++ ++static struct spi_board_info tl_wr942n_v1_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &tl_wr942n_v1_ssr_data, ++ .controller_data = (void *) TL_WR942N_V1_GPIO_SHIFT_RCLK, ++ }, ++}; ++ ++static void tl_wr942n_v1_get_mac(const char *name, char *mac) ++{ ++ u8 *nvram = (u8 *) KSEG1ADDR(TL_WR942N_V1_DEFAULT_MAC_ADDR); ++ int err; ++ ++ err = ath79_nvram_parse_mac_addr(nvram, TL_WR942N_V1_DEFAULT_MAC_SIZE, ++ name, mac); ++ ++ if (err) ++ pr_err("no MAC address found for %s\n", name); ++} ++ ++static void __init tl_wr942n_v1_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ void __iomem *base; ++ u32 t; ++ ++ ath79_register_m25p80(NULL); ++ ++ spi_register_board_info(tl_wr942n_v1_spi_info, ++ ARRAY_SIZE(tl_wr942n_v1_spi_info)); ++ platform_device_register(&tl_wr942n_v1_spi_device); ++ ++ /* Check inherited UART RX GPIO definition */ ++ base = ioremap(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); ++ ++ t = __raw_readl(base + QCA956X_GPIO_REG_IN_ENABLE0); ++ if (((t & GPIO_IN_ENABLE0_UART_SIN_MASK) ++ >> GPIO_IN_ENABLE0_UART_SIN_LSB) == TL_WR942N_V1_GPIO_LED_USB1) { ++ pr_warn("Active UART detected on USBLED's GPIOs!\n"); ++ ++ tl_wr942n_v1_leds_gpio[9].gpio = TL_WR942N_V1_GPIO_UART_TX; ++ tl_wr942n_v1_leds_gpio[10].gpio = TL_WR942N_V1_GPIO_UART_RX; ++ } ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr942n_v1_leds_gpio), ++ tl_wr942n_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR942N_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr942n_v1_gpio_keys), ++ tl_wr942n_v1_gpio_keys); ++ ++ tl_wr942n_v1_get_mac("MAC:", tmpmac); ++ ++ /* swap PHYs */ ++ ath79_setup_qca956x_eth_cfg(QCA956X_ETH_CFG_SW_PHY_SWAP | ++ QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ /* WAN port */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, tmpmac, 1); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ /* swaped PHYs */ ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, tmpmac, 0); ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ /* swaped PHYs */ ++ ath79_switch_data.phy_poll_mask |= BIT(0); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + TL_WR942N_V1_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ ath79_register_usb(); ++ ++ gpio_request_one(TL_WR942N_V1_74HC_GPIO_HUB_RESET, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ gpio_request_one(TL_WR942N_V1_GPIO_SHIFT_OE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "LED control"); ++ ++ gpio_request_one(TL_WR942N_V1_GPIO_SHIFT_SRCLR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LED reset"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR942N_V1, "TL-WR942N-V1", "TP-LINK TL-WR942N v1", ++ tl_wr942n_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ts-d084.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ts-d084.c +new file mode 100644 +index 0000000000..38786fdeda +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ts-d084.c +@@ -0,0 +1,86 @@ ++/* ++ * PISEN TS-D084 board support ++ * Based on TP-LINK TL-WR703N/TL-MR10U board support ++ * ++ * Copyright (C) 2011 dongyuqi <729650915@qq.com> ++ * Copyright (C) 2011-2012 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. ++ */ ++ ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TS_D084_GPIO_LED_SYSTEM 0 ++#define TS_D084_GPIO_BTN_RESET 12 ++ ++ ++#define TS_D084_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TS_D084_KEYS_DEBOUNCE_INTERVAL (3 * TS_D084_KEYS_POLL_INTERVAL) ++ ++static const char *ts_d084_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data ts_d084_flash_data = { ++ .part_probes = ts_d084_part_probes, ++}; ++ ++static struct gpio_led ts_d084_leds_gpio[] __initdata = { ++ { ++ .name = "ts-d084:blue:system", ++ .gpio = TS_D084_GPIO_LED_SYSTEM, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button ts_d084_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TS_D084_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TS_D084_GPIO_BTN_RESET, ++ .active_low = 0, ++ } ++}; ++ ++static void __init ts_d084_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ /* disable PHY_SWAP and PHY_ADDR_SWAP bits */ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_m25p80(&ts_d084_flash_data); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ts_d084_leds_gpio), ++ ts_d084_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TS_D084_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ts_d084_gpio_keys), ++ ts_d084_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TS_D084, "TS-D084", "PISEN TS-D084", ++ ts_d084_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tube2h.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tube2h.c +new file mode 100644 +index 0000000000..06b3616536 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tube2h.c +@@ -0,0 +1,129 @@ ++/* ++ * ALFA NETWORK Tube2H board support ++ * ++ * Copyright (C) 2014 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. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define TUBE2H_GPIO_LED_SIGNAL4 0 ++#define TUBE2H_GPIO_LED_SIGNAL3 1 ++#define TUBE2H_GPIO_LED_SIGNAL2 13 ++#define TUBE2H_GPIO_LED_LAN 17 ++#define TUBE2H_GPIO_LED_SIGNAL1 27 ++#define TUBE2H_GPIO_EXT_LNA 28 ++ ++#define TUBE2H_GPIO_WDT_EN 22 ++#define TUBE2H_GPIO_WDT_IN 18 ++ ++#define TUBE2H_GPIO_BTN_RESET 12 ++ ++#define TUBE2H_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define TUBE2H_KEYS_DEBOUNCE_INTERVAL (3 * TUBE2H_KEYS_POLL_INTERVAL) ++ ++#define TUBE2H_ART_ADDRESS 0x1fff0000 ++#define TUBE2H_LAN_MAC_OFFSET 0x06 ++#define TUBE2H_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led tube2h_leds_gpio[] __initdata = { ++ { ++ .name = "alfa:blue:lan", ++ .gpio = TUBE2H_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "alfa:red:signal1", ++ .gpio = TUBE2H_GPIO_LED_SIGNAL1, ++ .active_low = 1, ++ }, ++ { ++ .name = "alfa:orange:signal2", ++ .gpio = TUBE2H_GPIO_LED_SIGNAL2, ++ .active_low = 0, ++ }, ++ { ++ .name = "alfa:green:signal3", ++ .gpio = TUBE2H_GPIO_LED_SIGNAL3, ++ .active_low = 0, ++ }, ++ { ++ .name = "alfa:green:signal4", ++ .gpio = TUBE2H_GPIO_LED_SIGNAL4, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button tube2h_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = TUBE2H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = TUBE2H_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init tube2h_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(TUBE2H_ART_ADDRESS); ++ u32 t; ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_JTAG_DISABLE | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ /* Ensure that GPIO26 and GPIO27 are controllable by software */ ++ t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ t |= AR933X_BOOTSTRAP_MDIO_GPIO_EN; ++ ath79_reset_wr(AR933X_RESET_REG_BOOTSTRAP, t); ++ ++ gpio_request_one(TUBE2H_GPIO_EXT_LNA, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "external LNA0"); ++ ++ gpio_request_one(TUBE2H_GPIO_WDT_IN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "WDT input"); ++ ++ gpio_request_one(TUBE2H_GPIO_WDT_EN, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "WDT enable"); ++ ++ ath79_register_wmac(art + TUBE2H_CALDATA_OFFSET, NULL); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tube2h_leds_gpio), ++ tube2h_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TUBE2H_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tube2h_gpio_keys), ++ tube2h_gpio_keys); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + TUBE2H_LAN_MAC_OFFSET, 0); ++ ath79_register_mdio(0, 0x0); ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TUBE2H, "TUBE2H", "ALFA NETWORK Tube2H", ++ tube2h_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c +new file mode 100644 +index 0000000000..09a0bba867 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c +@@ -0,0 +1,179 @@ ++/* ++ * Ubiquiti UniFi AC (LITE) board support ++ * ++ * Copyright (C) 2015-2016 P. Wassi ++ * ++ * Derived from: mach-ubnt-xm.c ++ * ++ * 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 ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++ ++#define UNIFIAC_KEYS_POLL_INTERVAL 20 ++#define UNIFIAC_KEYS_DEBOUNCE_INTERVAL (3 * UNIFIAC_KEYS_POLL_INTERVAL) ++ ++#define UNIFIAC_GPIO_LED_WHITE 7 ++#define UNIFIAC_GPIO_LED_BLUE 8 ++ ++#define UNIFIAC_GPIO_BTN_RESET 2 ++ ++#define UNIFIAC_MAC0_OFFSET 0x0000 ++#define UNIFIAC_WMAC_CALDATA_OFFSET 0x1000 ++#define UNIFIAC_PCI_CALDATA_OFFSET 0x5000 ++ ++ ++static struct flash_platform_data ubnt_unifiac_flash_data = { ++ /* mx25l12805d and mx25l12835f have the same JEDEC ID */ ++ .type = "mx25l12805d", ++}; ++ ++static struct gpio_led ubnt_unifiac_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:white:dome", ++ .gpio = UNIFIAC_GPIO_LED_WHITE, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:blue:dome", ++ .gpio = UNIFIAC_GPIO_LED_BLUE, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button ubnt_unifiac_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = UNIFIAC_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = UNIFIAC_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init ubnt_unifiac_lite_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&ubnt_unifiac_flash_data); ++ ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ eeprom + UNIFIAC_MAC0_OFFSET, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_pll_data.pll_10 = 0x00001313; ++ ++ ath79_register_mdio(0, ~BIT(4)); ++ ath79_register_eth(0); ++ ++ ++ ath79_register_wmac(eeprom + UNIFIAC_WMAC_CALDATA_OFFSET, NULL); ++ ++ ++ ap91_pci_init(eeprom + UNIFIAC_PCI_CALDATA_OFFSET, NULL); ++ ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifiac_leds_gpio), ++ ubnt_unifiac_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, UNIFIAC_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_unifiac_gpio_keys), ++ ubnt_unifiac_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_UNIFIAC_LITE, "UBNT-UF-AC-LITE", ++ "Ubiquiti UniFi-AC-LITE/MESH", ubnt_unifiac_lite_setup); ++ ++static struct ar8327_pad_cfg ubnt_unifiac_pro_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data ubnt_unifiac_pro_ar8327_data = { ++ .pad0_cfg = &ubnt_unifiac_pro_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++ ++static struct mdio_board_info ubnt_unifiac_pro_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &ubnt_unifiac_pro_ar8327_data, ++ }, ++}; ++ ++static void __init ubnt_unifiac_pro_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&ubnt_unifiac_flash_data); ++ ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ eeprom + UNIFIAC_MAC0_OFFSET, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ mdiobus_register_board_info(ubnt_unifiac_pro_mdio0_info, ++ ARRAY_SIZE(ubnt_unifiac_pro_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x00); ++ ath79_register_eth(0); ++ ++ ++ ath79_register_usb(); ++ ++ ++ ath79_register_wmac(eeprom + UNIFIAC_WMAC_CALDATA_OFFSET, NULL); ++ ++ ++ ap91_pci_init(eeprom + UNIFIAC_PCI_CALDATA_OFFSET, NULL); ++ ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifiac_leds_gpio), ++ ubnt_unifiac_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, UNIFIAC_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_unifiac_gpio_keys), ++ ubnt_unifiac_gpio_keys); ++} ++ ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_UNIFIAC_PRO, "UBNT-UF-AC-PRO", ++ "Ubiquiti UniFi-AC-PRO/MESH-PRO", ubnt_unifiac_pro_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-xm.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-xm.c +new file mode 100644 +index 0000000000..6ceb91efff +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-xm.c +@@ -0,0 +1,781 @@ ++/* ++ * Ubiquiti Networks XM (rev 1.0) board support ++ * ++ * Copyright (C) 2011 René Bolldorf ++ * ++ * Derived from: mach-pb44.c ++ * ++ * 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 ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define UBNT_XM_GPIO_LED_L1 0 ++#define UBNT_XM_GPIO_LED_L2 1 ++#define UBNT_XM_GPIO_LED_L3 11 ++#define UBNT_XM_GPIO_LED_L4 7 ++ ++#define UBNT_XM_GPIO_BTN_RESET 12 ++ ++#define UBNT_XM_KEYS_POLL_INTERVAL 20 ++#define UBNT_XM_KEYS_DEBOUNCE_INTERVAL (3 * UBNT_XM_KEYS_POLL_INTERVAL) ++ ++#define UBNT_XM_EEPROM_ADDR 0x1fff1000 ++ ++static struct gpio_led ubnt_xm_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:red:link1", ++ .gpio = UBNT_XM_GPIO_LED_L1, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:orange:link2", ++ .gpio = UBNT_XM_GPIO_LED_L2, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:link3", ++ .gpio = UBNT_XM_GPIO_LED_L3, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:link4", ++ .gpio = UBNT_XM_GPIO_LED_L4, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_keys_button ubnt_xm_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = UBNT_XM_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = UBNT_XM_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++#define UBNT_M_WAN_PHYMASK BIT(4) ++ ++static void __init ubnt_xm_init(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(UBNT_XM_EEPROM_ADDR); ++ u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac2 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_xm_leds_gpio), ++ ubnt_xm_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ap91_pci_init(eeprom, NULL); ++ ++ ath79_register_mdio(0, ~UBNT_M_WAN_PHYMASK); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_eth1_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_XM, ++ "UBNT-XM", ++ "Ubiquiti Networks XM (rev 1.0) board", ++ ubnt_xm_init); ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_BULLET_M, "UBNT-BM", "Ubiquiti Bullet M", ++ ubnt_xm_init); ++ ++static void __init ubnt_rocket_m_setup(void) ++{ ++ ubnt_xm_init(); ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_ROCKET_M, "UBNT-RM", "Ubiquiti Rocket M", ++ ubnt_rocket_m_setup); ++ ++static void __init ubnt_nano_m_setup(void) ++{ ++ ubnt_xm_init(); ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_NANO_M, "UBNT-NM", "Ubiquiti Nanostation M", ++ ubnt_nano_m_setup); ++ ++static struct gpio_led ubnt_airrouter_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:green:globe", ++ .gpio = 0, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:green:power", ++ .gpio = 11, ++ .active_low = 1, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ } ++}; ++ ++static void __init ubnt_airrouter_setup(void) ++{ ++ u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_mdio(0, ~UBNT_M_WAN_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_local_mac(ath79_eth1_data.mac_addr, mac1); ++ ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ath79_register_usb(); ++ ++ ap91_pci_init(ee, NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_airrouter_leds_gpio), ++ ubnt_airrouter_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_AIRROUTER, "UBNT-AR", "Ubiquiti AirRouter", ++ ubnt_airrouter_setup); ++ ++static struct gpio_led ubnt_unifi_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:orange:dome", ++ .gpio = 1, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:dome", ++ .gpio = 0, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_led ubnt_unifi_outdoor_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:orange:front", ++ .gpio = 1, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:front", ++ .gpio = 0, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_led ubnt_unifi_outdoor_plus_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:white:front", ++ .gpio = 1, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:blue:front", ++ .gpio = 0, ++ .active_low = 0, ++ } ++}; ++ ++ ++static void __init ubnt_unifi_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(0, ~UBNT_M_WAN_PHYMASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_register_eth(0); ++ ++ ap91_pci_init(ee, NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_leds_gpio), ++ ubnt_unifi_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_UNIFI, "UBNT-UF", "Ubiquiti UniFi", ++ ubnt_unifi_setup); ++ ++ ++#define UBNT_UNIFIOD_PRI_PHYMASK BIT(4) ++#define UBNT_UNIFIOD_2ND_PHYMASK (BIT(0) | BIT(1) | BIT(2) | BIT(3)) ++ ++static void __init ubnt_unifi_outdoor_setup(void) ++{ ++ u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac2 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(0, ~(UBNT_UNIFIOD_PRI_PHYMASK | ++ UBNT_UNIFIOD_2ND_PHYMASK)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ap91_pci_init(ee, NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_outdoor_leds_gpio), ++ ubnt_unifi_outdoor_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_UNIFI_OUTDOOR, "UBNT-U20", ++ "Ubiquiti UniFiAP Outdoor", ++ ubnt_unifi_outdoor_setup); ++ ++ ++static void __init ubnt_unifi_outdoor_plus_setup(void) ++{ ++ u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac2 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(0, ~(UBNT_UNIFIOD_PRI_PHYMASK | ++ UBNT_UNIFIOD_2ND_PHYMASK)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0); ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ap9x_pci_get_wmac_data(0)->ubnt_hsr = true; ++ ap91_pci_init(ee, NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_outdoor_plus_leds_gpio), ++ ubnt_unifi_outdoor_plus_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_UNIFI_OUTDOOR_PLUS, "UBNT-UOP", ++ "Ubiquiti UniFiAP Outdoor+", ++ ubnt_unifi_outdoor_plus_setup); ++ ++ ++static struct gpio_led ubnt_uap_pro_gpio_leds[] __initdata = { ++ { ++ .name = "ubnt:white:dome", ++ .gpio = 12, ++ }, { ++ .name = "ubnt:blue:dome", ++ .gpio = 13, ++ } ++}; ++ ++static struct gpio_keys_button uap_pro_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = UBNT_XM_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 17, ++ .active_low = 1, ++ } ++}; ++ ++static struct ar8327_pad_cfg uap_pro_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data uap_pro_ar8327_data = { ++ .pad0_cfg = &uap_pro_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info uap_pro_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &uap_pro_ar8327_data, ++ }, ++}; ++ ++#define UAP_PRO_MAC0_OFFSET 0x0000 ++#define UAP_PRO_MAC1_OFFSET 0x0006 ++#define UAP_PRO_WMAC_CALDATA_OFFSET 0x1000 ++#define UAP_PRO_PCI_CALDATA_OFFSET 0x5000 ++ ++static void __init ubnt_uap_pro_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_uap_pro_gpio_leds), ++ ubnt_uap_pro_gpio_leds); ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(uap_pro_gpio_keys), ++ uap_pro_gpio_keys); ++ ++ ath79_register_wmac(eeprom + UAP_PRO_WMAC_CALDATA_OFFSET, NULL); ++ ap91_pci_init(eeprom + UAP_PRO_PCI_CALDATA_OFFSET, NULL); ++ ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(uap_pro_mdio0_info, ++ ARRAY_SIZE(uap_pro_mdio0_info)); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ eeprom + UAP_PRO_MAC0_OFFSET, 0); ++ ++ /* GMAC0 is connected to an AR8327 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_UAP_PRO, "UAP-PRO", "Ubiquiti UniFi AP Pro", ++ ubnt_uap_pro_setup); ++ ++#define UBNT_XW_GPIO_LED_L1 11 ++#define UBNT_XW_GPIO_LED_L2 16 ++#define UBNT_XW_GPIO_LED_L3 13 ++#define UBNT_XW_GPIO_LED_L4 14 ++ ++static struct gpio_led ubnt_xw_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:red:link1", ++ .gpio = UBNT_XW_GPIO_LED_L1, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:orange:link2", ++ .gpio = UBNT_XW_GPIO_LED_L2, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:green:link3", ++ .gpio = UBNT_XW_GPIO_LED_L3, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:green:link4", ++ .gpio = UBNT_XW_GPIO_LED_L4, ++ .active_low = 1, ++ }, ++}; ++ ++#define UBNT_ROCKET_TI_GPIO_LED_L1 16 ++#define UBNT_ROCKET_TI_GPIO_LED_L2 17 ++#define UBNT_ROCKET_TI_GPIO_LED_L3 18 ++#define UBNT_ROCKET_TI_GPIO_LED_L4 19 ++#define UBNT_ROCKET_TI_GPIO_LED_L5 20 ++#define UBNT_ROCKET_TI_GPIO_LED_L6 21 ++static struct gpio_led ubnt_rocket_ti_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:green:link1", ++ .gpio = UBNT_ROCKET_TI_GPIO_LED_L1, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:green:link2", ++ .gpio = UBNT_ROCKET_TI_GPIO_LED_L2, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:green:link3", ++ .gpio = UBNT_ROCKET_TI_GPIO_LED_L3, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:green:link4", ++ .gpio = UBNT_ROCKET_TI_GPIO_LED_L4, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:link5", ++ .gpio = UBNT_ROCKET_TI_GPIO_LED_L5, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:link6", ++ .gpio = UBNT_ROCKET_TI_GPIO_LED_L6, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init ubnt_xw_init(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_xw_leds_gpio), ++ ubnt_xw_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++ ++ ath79_register_wmac(eeprom + UAP_PRO_WMAC_CALDATA_OFFSET, NULL); ++ ap91_pci_init(eeprom + UAP_PRO_PCI_CALDATA_OFFSET, NULL); ++ ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_MII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0_SLAVE); ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ eeprom + UAP_PRO_MAC0_OFFSET, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++} ++ ++static void __init ubnt_nano_m_xw_setup(void) ++{ ++ ubnt_xw_init(); ++ ++ /* GMAC0 is connected to an AR8326 switch */ ++ ath79_register_mdio(0, ~(BIT(0) | BIT(1) | BIT(5))); ++ ath79_eth0_data.phy_mask = (BIT(0) | BIT(1) | BIT(5)); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_register_eth(0); ++} ++ ++static struct at803x_platform_data ubnt_loco_m_xw_at803x_data = { ++ .has_reset_gpio = 1, ++ .reset_gpio = 0, ++}; ++ ++static struct mdio_board_info ubnt_loco_m_xw_mdio_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 1, ++ .platform_data = &ubnt_loco_m_xw_at803x_data, ++ }, ++}; ++ ++static void __init ubnt_loco_m_xw_setup(void) ++{ ++ ubnt_xw_init(); ++ ++ mdiobus_register_board_info(ubnt_loco_m_xw_mdio_info, ++ ARRAY_SIZE(ubnt_loco_m_xw_mdio_info)); ++ ++ ath79_register_mdio(0, ~BIT(1)); ++ ath79_eth0_data.phy_mask = BIT(1); ++ ath79_register_eth(0); ++} ++ ++#define UBNT_LBE_M5_GPIO_LED_LAN 13 ++#define UBNT_LBE_M5_GPIO_LED_WLAN 14 ++#define UBNT_LBE_M5_GPIO_LED_SYS 16 ++ ++static struct gpio_led ubnt_lbe_m5_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:green:lan", ++ .gpio = UBNT_LBE_M5_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:green:wlan", ++ .gpio = UBNT_LBE_M5_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "ubnt:green:sys", ++ .gpio = UBNT_LBE_M5_GPIO_LED_SYS, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init ubnt_lbe_m5_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_wmac(eeprom + UAP_PRO_WMAC_CALDATA_OFFSET, NULL); ++ ap91_pci_init(eeprom + UAP_PRO_PCI_CALDATA_OFFSET, NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_lbe_m5_leds_gpio), ++ ubnt_lbe_m5_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_MII_GMAC0 | ++ AR934X_ETH_CFG_MII_GMAC0_SLAVE); ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ eeprom + UAP_PRO_MAC0_OFFSET, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ gpio_request_one(0, GPIOF_OUT_INIT_LOW | GPIOF_ACTIVE_LOW | ++ GPIOF_EXPORT_DIR_FIXED, "SPI nWP"); ++ ++ mdiobus_register_board_info(ubnt_loco_m_xw_mdio_info, ++ ARRAY_SIZE(ubnt_loco_m_xw_mdio_info)); ++ ++ ath79_register_mdio(0, ~BIT(1)); ++ ath79_eth0_data.phy_mask = BIT(1); ++ ath79_register_eth(0); ++} ++ ++static void __init ubnt_rocket_m_xw_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_xw_leds_gpio), ++ ubnt_xw_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++ ++ ath79_register_wmac(eeprom + UAP_PRO_WMAC_CALDATA_OFFSET, NULL); ++ ap91_pci_init(eeprom + UAP_PRO_PCI_CALDATA_OFFSET, NULL); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ eeprom + UAP_PRO_MAC0_OFFSET, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_mdio(0, ~BIT(4)); ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++} ++ ++static struct at803x_platform_data ubnt_rocket_m_ti_at803_data = { ++ .disable_smarteee = 1, ++ .enable_rgmii_rx_delay = 1, ++ .enable_rgmii_tx_delay = 1, ++}; ++static struct mdio_board_info ubnt_rocket_m_ti_mdio_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 4, ++ .platform_data = &ubnt_rocket_m_ti_at803_data, ++ }, ++}; ++ ++static void __init ubnt_rocket_m_ti_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_rocket_ti_leds_gpio), ++ ubnt_rocket_ti_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_xm_gpio_keys), ++ ubnt_xm_gpio_keys); ++ ++ ap91_pci_init(eeprom + 0x1000, NULL); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ath79_setup_ar934x_eth_rx_delay(3, 3); ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ eeprom + UAP_PRO_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, ++ eeprom + UAP_PRO_MAC1_OFFSET, 0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ++ mdiobus_register_board_info(ubnt_rocket_m_ti_mdio_info, ++ ARRAY_SIZE(ubnt_rocket_m_ti_mdio_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ++ ath79_eth0_data.phy_mask = BIT(4); ++ /* read out from vendor */ ++ ath79_eth0_pll_data.pll_1000 = 0x2000000; ++ ath79_eth0_pll_data.pll_10 = 0x1313; ++ ath79_register_eth(0); ++ ++ ath79_register_mdio(1, 0x0); ++ ath79_eth1_data.phy_mask = BIT(3); ++ ath79_register_eth(1); ++} ++ ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_NANO_M_XW, "UBNT-NM-XW", "Ubiquiti Nanostation M XW", ++ ubnt_nano_m_xw_setup); ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_LBE_M5, "UBNT-LBE-M5", "Ubiquiti Litebeam M5", ++ ubnt_lbe_m5_setup); ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_LOCO_M_XW, "UBNT-LOCO-XW", "Ubiquiti Loco M XW", ++ ubnt_loco_m_xw_setup); ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_ROCKET_M_XW, "UBNT-RM-XW", "Ubiquiti Rocket M XW", ++ ubnt_rocket_m_xw_setup); ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_BULLET_M_XW, "UBNT-BM-XW", "Ubiquiti Bullet M XW", ++ ubnt_rocket_m_xw_setup); ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_ROCKET_M_TI, "UBNT-RM-TI", "Ubiquiti Rocket M TI", ++ ubnt_rocket_m_ti_setup); ++ ++static struct gpio_led ubnt_airgateway_gpio_leds[] __initdata = { ++ { ++ .name = "ubnt:blue:wlan", ++ .gpio = 0, ++ }, { ++ .name = "ubnt:white:status", ++ .gpio = 1, ++ }, ++}; ++ ++static struct gpio_keys_button airgateway_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = UBNT_XM_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 12, ++ .active_low = 1, ++ } ++}; ++ ++static void __init ubnt_airgateway_setup(void) ++{ ++ u32 t; ++ u8 *mac0 = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ t |= AR933X_BOOTSTRAP_MDIO_GPIO_EN; ++ ath79_reset_wr(AR933X_RESET_REG_BOOTSTRAP, t); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_airgateway_gpio_leds), ++ ubnt_airgateway_gpio_leds); ++ ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(airgateway_gpio_keys), ++ airgateway_gpio_keys); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac0, 0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_register_eth(1); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(ee, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_AIRGW, "UBNT-AGW", "Ubiquiti AirGateway", ++ ubnt_airgateway_setup); ++ ++static struct gpio_led ubnt_airgateway_pro_gpio_leds[] __initdata = { ++ { ++ .name = "ubnt:blue:wlan", ++ .gpio = 13, ++ }, { ++ .name = "ubnt:white:status", ++ .gpio = 17, ++ }, ++}; ++ ++ ++static struct gpio_keys_button airgateway_pro_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = UBNT_XM_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 12, ++ .active_low = 1, ++ } ++}; ++ ++static void __init ubnt_airgateway_pro_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac0 = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_airgateway_pro_gpio_leds), ++ ubnt_airgateway_pro_gpio_leds); ++ ++ ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(airgateway_pro_gpio_keys), ++ airgateway_pro_gpio_keys); ++ ++ ath79_register_wmac(eeprom + UAP_PRO_WMAC_CALDATA_OFFSET, NULL); ++ ap91_pci_init(eeprom + UAP_PRO_PCI_CALDATA_OFFSET, NULL); ++ ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ /* GMAC0 is left unused in this configuration */ ++ ++ /* GMAC1 is connected to MAC0 on the internal switch */ ++ /* The PoE/WAN port connects to port 5 on the internal switch */ ++ /* The LAN port connects to port 4 on the internal switch */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac0, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_AIRGWP, "UBNT-AGWP", "Ubiquiti AirGateway Pro", ++ ubnt_airgateway_pro_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt.c +new file mode 100644 +index 0000000000..e49ac23fd1 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt.c +@@ -0,0 +1,205 @@ ++/* ++ * Ubiquiti RouterStation support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2008 Ubiquiti ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define UBNT_RS_GPIO_LED_RF 2 ++#define UBNT_RS_GPIO_SW4 8 ++ ++#define UBNT_LS_SR71_GPIO_LED_D25 0 ++#define UBNT_LS_SR71_GPIO_LED_D26 1 ++#define UBNT_LS_SR71_GPIO_LED_D24 2 ++#define UBNT_LS_SR71_GPIO_LED_D23 4 ++#define UBNT_LS_SR71_GPIO_LED_D22 5 ++#define UBNT_LS_SR71_GPIO_LED_D27 6 ++#define UBNT_LS_SR71_GPIO_LED_D28 7 ++ ++#define UBNT_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define UBNT_KEYS_DEBOUNCE_INTERVAL (3 * UBNT_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led ubnt_rs_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:green:rf", ++ .gpio = UBNT_RS_GPIO_LED_RF, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_led ubnt_ls_sr71_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:green:d22", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D22, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:d23", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D23, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:d24", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D24, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:red:d25", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D25, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:red:d26", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D26, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:d27", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D27, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:d28", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D28, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button ubnt_gpio_keys[] __initdata = { ++ { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = UBNT_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = UBNT_RS_GPIO_SW4, ++ .active_low = 1, ++ } ++}; ++ ++static const char *ubnt_part_probes[] = { ++ "RedBoot", ++ NULL, ++}; ++ ++static struct flash_platform_data ubnt_flash_data = { ++ .part_probes = ubnt_part_probes, ++}; ++ ++static void __init ubnt_generic_setup(void) ++{ ++ ath79_register_m25p80(&ubnt_flash_data); ++ ++ ath79_register_gpio_keys_polled(-1, UBNT_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_gpio_keys), ++ ubnt_gpio_keys); ++ ath79_register_pci(); ++} ++ ++#define UBNT_RS_WAN_PHYMASK BIT(20) ++#define UBNT_RS_LAN_PHYMASK (BIT(16) | BIT(17) | BIT(18) | BIT(19)) ++ ++static void __init ubnt_rs_setup(void) ++{ ++ ubnt_generic_setup(); ++ ++ ath79_register_mdio(0, ~(UBNT_RS_WAN_PHYMASK | UBNT_RS_LAN_PHYMASK)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = UBNT_RS_WAN_PHYMASK; ++ ++ /* ++ * There is Secondary MAC address duplicate problem with some ++ * UBNT HW batches. Do not increase Secondary MAC address by 1 ++ * but do workaround with 'Locally Administrated' bit. ++ */ ++ ath79_init_local_mac(ath79_eth1_data.mac_addr, ath79_mac_base); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.speed = SPEED_100; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_rs_leds_gpio), ++ ubnt_rs_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_RS, "UBNT-RS", "Ubiquiti RouterStation", ++ ubnt_rs_setup); ++ ++#define UBNT_RSPRO_WAN_PHYMASK BIT(4) ++#define UBNT_RSPRO_LAN_PHYMASK (BIT(0) | BIT(1) | BIT(2) | BIT(3)) ++ ++static void __init ubnt_rspro_setup(void) ++{ ++ ubnt_generic_setup(); ++ ++ ath79_register_mdio(0, ~(UBNT_RSPRO_WAN_PHYMASK | ++ UBNT_RSPRO_LAN_PHYMASK)); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = UBNT_RSPRO_WAN_PHYMASK; ++ ++ /* ++ * There is Secondary MAC address duplicate problem with some ++ * UBNT HW batches. Do not increase Secondary MAC address by 1 ++ * but do workaround with 'Locally Administrated' bit. ++ */ ++ ath79_init_local_mac(ath79_eth1_data.mac_addr, ath79_mac_base); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = UBNT_RSPRO_LAN_PHYMASK; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_rs_leds_gpio), ++ ubnt_rs_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_RSPRO, "UBNT-RSPRO", "Ubiquiti RouterStation Pro", ++ ubnt_rspro_setup); ++ ++static void __init ubnt_lsx_setup(void) ++{ ++ ubnt_generic_setup(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_LSX, "UBNT-LSX", "Ubiquiti LSX", ubnt_lsx_setup); ++ ++#define UBNT_LSSR71_PHY_MASK BIT(1) ++ ++static void __init ubnt_lssr71_setup(void) ++{ ++ ubnt_generic_setup(); ++ ++ ath79_register_mdio(0, ~UBNT_LSSR71_PHY_MASK); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = UBNT_LSSR71_PHY_MASK; ++ ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_ls_sr71_leds_gpio), ++ ubnt_ls_sr71_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_UBNT_LSSR71, "UBNT-LS-SR71", "Ubiquiti LS-SR71", ++ ubnt_lssr71_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wam250.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wam250.c +new file mode 100644 +index 0000000000..31817bddf2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wam250.c +@@ -0,0 +1,122 @@ ++/* ++ * Samsung WAM250 board support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WAM250_GPIO_LED_LAN 13 ++#define WAM250_GPIO_LED_POWER 15 ++#define WAM250_GPIO_LED_REPEATER 14 ++#define WAM250_GPIO_LED_WLAN 12 ++ ++#define WAM250_GPIO_BTN_RESET 17 ++#define WAM250_GPIO_BTN_SPKADD 1 ++ ++#define WAM250_GPIO_EXT_LNA 19 ++ ++#define WAM250_MAC_OFFSET 2 ++ ++#define WAM250_KEYS_POLL_INTERVAL 20 ++#define WAM250_KEYS_DEBOUNCE_INTERVAL (3 * WAM250_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led wam250_leds_gpio[] __initdata = { ++ { ++ .name = "wam250:white:lan", ++ .gpio = WAM250_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "wam250:white:power", ++ .gpio = WAM250_GPIO_LED_POWER, ++ .default_state = LEDS_GPIO_DEFSTATE_KEEP, ++ .active_low = 1, ++ }, { ++ .name = "wam250:white:repeater", ++ .gpio = WAM250_GPIO_LED_REPEATER, ++ .active_low = 1, ++ }, { ++ .name = "wam250:white:wlan", ++ .gpio = WAM250_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wam250_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WAM250_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WAM250_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WAM250_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WAM250_GPIO_BTN_SPKADD, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init wam250_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_PHY_SWAP); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = 0xfd; ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.phy_mask = BIT(1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + WAM250_MAC_OFFSET, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + WAM250_MAC_OFFSET, 1); ++ ath79_register_eth(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wam250_leds_gpio), ++ wam250_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WAM250_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wam250_gpio_keys), ++ wam250_gpio_keys); ++ ++ ath79_wmac_set_ext_lna_gpio(0, WAM250_GPIO_EXT_LNA); ++ ++ ath79_register_usb(); ++ ath79_register_wmac(art, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WAM250, "WAM250", "Samsung WAM250", wam250_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-weio.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-weio.c +new file mode 100644 +index 0000000000..3973ada7c3 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-weio.c +@@ -0,0 +1,140 @@ ++/** ++ * WEIO Web Of Things Platform ++ * ++ * Copyright (C) 2013 Drasko DRASKOVIC and Uros PETREVSKI ++ * ++ * ## ## ######## #### ####### ++ * ## ## ## ## ## ## ## ++ * ## ## ## ## ## ## ## ++ * ## ## ## ###### ## ## ## ++ * ## ## ## ## ## ## ## ++ * ## ## ## ## ## ## ## ++ * ### ### ######## #### ####### ++ * ++ * Web Of Things Platform ++ * ++ * 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. ++ * ++ * Authors : ++ * Drasko DRASKOVIC ++ * Uros PETREVSKI ++ */ ++ ++#include ++#include ++#include ++#include ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WEIO_GPIO_LED_STA 1 ++#define WEIO_GPIO_LED_AP 16 ++ ++#define WEIO_GPIO_BTN_AP 20 ++#define WEIO_GPIO_BTN_RESET 23 ++ ++#define WEIO_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WEIO_KEYS_DEBOUNCE_INTERVAL (3 * WEIO_KEYS_POLL_INTERVAL) ++ ++#define WEIO_MAC0_OFFSET 0x0000 ++#define WEIO_MAC1_OFFSET 0x0006 ++#define WEIO_CALDATA_OFFSET 0x1000 ++#define WEIO_WMAC_MAC_OFFSET 0x1002 ++ ++static struct gpio_led weio_leds_gpio[] __initdata = { ++ { ++ .name = "weio:green:sta", ++ .gpio = WEIO_GPIO_LED_STA, ++ .active_low = 1, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, ++ { ++ .name = "weio:green:ap", ++ .gpio = WEIO_GPIO_LED_AP, ++ .active_low = 1, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ } ++}; ++ ++static struct gpio_keys_button weio_gpio_keys[] __initdata = { ++ { ++ .desc = "ap button", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = WEIO_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WEIO_GPIO_BTN_AP, ++ .active_low = 1, ++ }, ++ { ++ .desc = "soft-reset button", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = WEIO_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WEIO_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct i2c_gpio_platform_data weio_i2c_gpio_data = { ++ .sda_pin = 18, ++ .scl_pin = 19, ++}; ++ ++static struct platform_device weio_i2c_gpio = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &weio_i2c_gpio_data, ++ }, ++}; ++ ++static void __init weio_common_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_wmac(art + WEIO_CALDATA_OFFSET, art + WEIO_WMAC_MAC_OFFSET); ++} ++ ++static void __init weio_setup(void) ++{ ++ weio_common_setup(); ++ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ platform_device_register(&weio_i2c_gpio); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(weio_leds_gpio), ++ weio_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WEIO_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(weio_gpio_keys), ++ weio_gpio_keys); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WEIO, "WEIO", "WeIO board", weio_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-whr-hp-g300n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-whr-hp-g300n.c +new file mode 100644 +index 0000000000..48f49ad0f7 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-whr-hp-g300n.c +@@ -0,0 +1,155 @@ ++/* ++ * Buffalo WHR-HP-G300N board support ++ * ++ * based on ... ++ * ++ * TP-LINK TL-WR741ND board support ++ * ++ * Copyright (C) 2009-2010 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. ++ */ ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define WHRHPG300N_GPIO_LED_SECURITY 0 ++#define WHRHPG300N_GPIO_LED_DIAG 1 ++#define WHRHPG300N_GPIO_LED_ROUTER 6 ++ ++#define WHRHPG300N_GPIO_BTN_ROUTER_ON 7 ++#define WHRHPG300N_GPIO_BTN_ROUTER_AUTO 8 ++#define WHRHPG300N_GPIO_BTN_RESET 11 ++#define WHRHPG300N_GPIO_BTN_AOSS 12 ++#define WHRHPG300N_GPIO_LED_LAN1 13 ++#define WHRHPG300N_GPIO_LED_LAN2 14 ++#define WHRHPG300N_GPIO_LED_LAN3 15 ++#define WHRHPG300N_GPIO_LED_LAN4 16 ++#define WHRHPG300N_GPIO_LED_WAN 17 ++ ++#define WHRHPG300N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WHRHPG300N_KEYS_DEBOUNCE_INTERVAL (3 * WHRHPG300N_KEYS_POLL_INTERVAL) ++ ++#define WHRHPG300N_MAC_OFFSET 0x20c ++ ++static struct gpio_led whrhpg300n_leds_gpio[] __initdata = { ++ { ++ .name = "buffalo:orange:security", ++ .gpio = WHRHPG300N_GPIO_LED_SECURITY, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:red:diag", ++ .gpio = WHRHPG300N_GPIO_LED_DIAG, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:router", ++ .gpio = WHRHPG300N_GPIO_LED_ROUTER, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:wan", ++ .gpio = WHRHPG300N_GPIO_LED_WAN, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:lan1", ++ .gpio = WHRHPG300N_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:lan2", ++ .gpio = WHRHPG300N_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:lan3", ++ .gpio = WHRHPG300N_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:lan4", ++ .gpio = WHRHPG300N_GPIO_LED_LAN4, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button whrhpg300n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WHRHPG300N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WHRHPG300N_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "aoss/wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .gpio = WHRHPG300N_GPIO_BTN_AOSS, ++ .debounce_interval = WHRHPG300N_KEYS_DEBOUNCE_INTERVAL, ++ .active_low = 1, ++ }, { ++ .desc = "router_on", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .gpio = WHRHPG300N_GPIO_BTN_ROUTER_ON, ++ .debounce_interval = WHRHPG300N_KEYS_DEBOUNCE_INTERVAL, ++ .active_low = 1, ++ }, { ++ .desc = "router_auto", ++ .type = EV_KEY, ++ .code = BTN_3, ++ .gpio = WHRHPG300N_GPIO_BTN_ROUTER_AUTO, ++ .debounce_interval = WHRHPG300N_KEYS_DEBOUNCE_INTERVAL, ++ .active_low = 1, ++ } ++}; ++ ++static void __init whrhpg300n_setup(void) ++{ ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 *mac = (u8 *) KSEG1ADDR(ee + WHRHPG300N_MAC_OFFSET); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(whrhpg300n_leds_gpio), ++ whrhpg300n_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WHRHPG300N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(whrhpg300n_gpio_keys), ++ whrhpg300n_gpio_keys); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN ports */ ++ ath79_register_eth(1); ++ /* WAN port */ ++ ath79_register_eth(0); ++ ++ ap9x_pci_setup_wmac_led_pin(0, 1); ++ ++ ap91_pci_init(ee, mac); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WHR_HP_G300N, "WHR-HP-G300N", "Buffalo WHR-HP-G300N", ++ whrhpg300n_setup); ++ ++MIPS_MACHINE(ATH79_MACH_WHR_G301N, "WHR-G301N", "Buffalo WHR-G301N", ++ whrhpg300n_setup); ++ ++MIPS_MACHINE(ATH79_MACH_WHR_HP_GN, "WHR-HP-GN", "Buffalo WHR-HP-GN", ++ whrhpg300n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wi2a-ac200i.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wi2a-ac200i.c +new file mode 100644 +index 0000000000..85e0c8fea3 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wi2a-ac200i.c +@@ -0,0 +1,217 @@ ++/* ++ * Nokia WI2A-AC200i support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * Copyright (c) 2017 Felix Fietkau ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define AC200I_GPIO_BTN_RESET 17 ++ ++#define AC200I_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define AC200I_KEYS_DEBOUNCE_INTERVAL (3 * AC200I_KEYS_POLL_INTERVAL) ++ ++#define AC200I_MAC_ADDR 0x1f040249 ++#define AC200I_MAC1_OFFSET 6 ++#define AC200I_WMAC_CALDATA_ADDR 0x1f061000 ++ ++static struct gpio_led ac200i_leds_gpio[] __initdata = { ++ { ++ .name = "nokia:red:wlan-2g", ++ .gpio = 0, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:green:power", ++ .gpio = 1, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:green:wlan-2g", ++ .gpio = 2, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:green:ctrl", ++ .gpio = 3, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:green:eth", ++ .gpio = 4, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:red:power", ++ .gpio = 13, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:red:eth", ++ .gpio = 14, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:red:wlan-5g", ++ .gpio = 18, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:green:wlan-5g", ++ .gpio = 19, ++ .active_low = 1, ++ }, ++ { ++ .name = "nokia:red:ctrl", ++ .gpio = 20, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button ac200i_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = AC200I_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = AC200I_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct mtd_partition ac200i_nand_partitions[] = { ++ { ++ .name = "cfg", ++ .offset = 0x0100000, ++ .size = 0x1800000, ++ .mask_flags = MTD_WRITEABLE, ++ }, ++ { ++ .name = "kernel", ++ .offset = 0x2000000, ++ .size = 0x0400000, ++ }, ++ { ++ .name = "ubi", ++ .offset = 0x2400000, ++ .size = 0x2000000, ++ }, ++ { ++ .name = "kernel", ++ .offset = 0x5000000, ++ .size = 0x0400000, ++ }, ++ { ++ .name = "ubi", ++ .offset = 0x5400000, ++ .size = 0x2000000, ++ }, ++}; ++ ++static const char *boot_getenv(const char *key) ++{ ++ const char *start = (const char *) KSEG1ADDR(0x1f070000); ++ const char *end = start + 0x20000; ++ const char *addr; ++ ++ for (addr = start + 4; ++ *addr && *addr != 0xff && addr < end && ++ strnlen(addr, end - addr) < end - addr; ++ addr += strnlen(addr, end - addr) + 1) { ++ const char *val; ++ ++ val = strchr(addr, '='); ++ if (!val) ++ continue; ++ ++ if (strncmp(addr, key, val - addr)) ++ continue; ++ ++ return val + 1; ++ } ++ return NULL; ++} ++ ++static void __init ac200i_setup(void) ++{ ++ const char *img; ++ u8 *wmac = (u8 *) KSEG1ADDR(AC200I_WMAC_CALDATA_ADDR); ++ u8 *mac_addr = (u8 *) KSEG1ADDR(AC200I_MAC_ADDR); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ac200i_leds_gpio), ++ ac200i_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, AC200I_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ac200i_gpio_keys), ++ ac200i_gpio_keys); ++ ++ ath79_register_usb(); ++ ath79_nfc_set_parts(ac200i_nand_partitions, ++ ARRAY_SIZE(ac200i_nand_partitions)); ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_HW); ++ ath79_register_nfc(); ++ ++ ath79_register_wmac(wmac, NULL); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac_addr, 0); ++ ++ /* GMAC0 is connected to the SGMII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x03000101; ++ ath79_eth0_pll_data.pll_100 = 0x80000101; ++ ath79_eth0_pll_data.pll_10 = 0x80001313; ++ ++ img = boot_getenv("dualPartition"); ++ if (img && !strcmp(img, "imgA")) { ++ ac200i_nand_partitions[3].name = "kernel_alt"; ++ ac200i_nand_partitions[4].name = "ubi_alt"; ++ } else { ++ ac200i_nand_partitions[1].name = "kernel_alt"; ++ ac200i_nand_partitions[2].name = "ubi_alt"; ++ } ++ ++ ath79_register_eth(0); ++ ++ ath79_register_pci(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WI2A_AC200I, "WI2A-AC200i", ++ "Nokia WI2A-AC200i", ++ ac200i_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wifi-pineapple-nano.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wifi-pineapple-nano.c +new file mode 100644 +index 0000000000..645f367f6c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wifi-pineapple-nano.c +@@ -0,0 +1,107 @@ ++/* ++ * Hak5 WiFi Pineapple NANO board support ++ * ++ * Copyright (C) 2018 Sebastian Kinne ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WIFI_PINEAPPLE_NANO_GPIO_LED_SYSTEM 18 ++ ++#define WIFI_PINEAPPLE_NANO_GPIO_BTN_RESET 12 ++#define WIFI_PINEAPPLE_NANO_GPIO_SD_DET 19 ++#define WIFI_PINEAPPLE_NANO_GPIO_USB_ALARM 20 ++#define WIFI_PINEAPPLE_NANO_GPIO_USB_POWER 23 ++ ++#define HAK5_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define HAK5_KEYS_DEBOUNCE_INTERVAL (3 * HAK5_KEYS_POLL_INTERVAL) ++ ++#define WIFI_PINEAPPLE_NANO_MAC1_OFFSET 0x0006 ++#define WIFI_PINEAPPLE_NANO_CALDATA_OFFSET 0x1000 ++ ++static const char *hak5_part_probes[] = { ++ "tp-link", ++ NULL, ++}; ++ ++static struct flash_platform_data hak5_flash_data = { ++ .part_probes = hak5_part_probes, ++}; ++ ++static struct gpio_led wifi_pineapple_nano_leds_gpio[] __initdata = { ++ { ++ .name = "wifi-pineapple-nano:blue:system", ++ .gpio = WIFI_PINEAPPLE_NANO_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wifi_pineapple_nano_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = HAK5_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WIFI_PINEAPPLE_NANO_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init wifi_pineapple_nano_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(&hak5_flash_data); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + WIFI_PINEAPPLE_NANO_MAC1_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ /* GPIO11/12 */ ++ ath79_gpio_function_disable(AR933X_GPIO_FUNC_UART_RTS_CTS_EN); ++ ++ gpio_request_one(WIFI_PINEAPPLE_NANO_GPIO_SD_DET, ++ GPIOF_IN | GPIOF_EXPORT_DIR_FIXED | GPIOF_ACTIVE_LOW, ++ "SD card present"); ++ ++ gpio_request_one(WIFI_PINEAPPLE_NANO_GPIO_USB_ALARM, ++ GPIOF_IN | GPIOF_EXPORT_DIR_FIXED | GPIOF_ACTIVE_LOW, ++ "USB alarm"); ++ ++ gpio_request_one(WIFI_PINEAPPLE_NANO_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED | ++ GPIOF_ACTIVE_LOW, "USB power"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wifi_pineapple_nano_leds_gpio), ++ wifi_pineapple_nano_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, HAK5_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wifi_pineapple_nano_gpio_keys), ++ wifi_pineapple_nano_gpio_keys); ++ ++ ath79_register_usb(); ++ ath79_register_wmac(art + WIFI_PINEAPPLE_NANO_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WIFI_PINEAPPLE_NANO, "WIFI-PINEAPPLE-NANO", ++ "Hak5 WiFi Pineapple NANO", wifi_pineapple_nano_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wlae-ag300n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wlae-ag300n.c +new file mode 100644 +index 0000000000..11006fd1bc +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wlae-ag300n.c +@@ -0,0 +1,114 @@ ++/* ++ * Buffalo WLAE-AG300N board support ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define WLAEAG300N_MAC_OFFSET 0x20c ++#define WLAEAG300N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WLAEAG300N_KEYS_DEBOUNCE_INTERVAL (3 * WLAEAG300N_KEYS_POLL_INTERVAL) ++ ++ ++static struct gpio_led wlaeag300n_leds_gpio[] __initdata = { ++ /* ++ * Note: Writing 1 into GPIO 13 will power down the device. ++ */ ++ { ++ .name = "buffalo:green:wireless", ++ .gpio = 14, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:red:wireless", ++ .gpio = 15, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:status", ++ .gpio = 16, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:red:status", ++ .gpio = 17, ++ .active_low = 1, ++ } ++}; ++ ++ ++static struct gpio_keys_button wlaeag300n_gpio_keys[] __initdata = { ++ { ++ .desc = "function", ++ .type = EV_KEY, ++ .code = KEY_MODE, ++ .debounce_interval = WLAEAG300N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 0, ++ .active_low = 1, ++ }, { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WLAEAG300N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 1, ++ .active_low = 1, ++ }, { ++ .desc = "power", ++ .type = EV_KEY, ++ .code = KEY_POWER, ++ .debounce_interval = WLAEAG300N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 11, ++ .active_low = 1, ++ }, { ++ .desc = "aoss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WLAEAG300N_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 12, ++ .active_low = 1, ++ } ++}; ++ ++static void __init wlaeag300n_setup(void) ++{ ++ u8 *eeprom1 = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 *mac1 = eeprom1 + WLAEAG300N_MAC_OFFSET; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 1); ++ ++ ath79_register_mdio(0, ~(BIT(0) | BIT(4))); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = BIT(4); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wlaeag300n_leds_gpio), ++ wlaeag300n_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WLAEAG300N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wlaeag300n_gpio_keys), ++ wlaeag300n_gpio_keys); ++ ++ ath79_register_m25p80(NULL); ++ ++ ap91_pci_init(eeprom1, mac1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WLAE_AG300N, "WLAE-AG300N", ++ "Buffalo WLAE-AG300N", wlaeag300n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wlr8100.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wlr8100.c +new file mode 100644 +index 0000000000..04b12fc7cc +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wlr8100.c +@@ -0,0 +1,195 @@ ++/* ++ * Sitecom X8 AC1750 WLR-8100 board support ++ * ++ * Based on the Qualcomm Atheros AP135/AP136 reference board support code ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WLR8100_GPIO_LED_USB 4 ++#define WLR8100_GPIO_LED_WLAN_5G 12 ++#define WLR8100_GPIO_LED_WLAN_2G 13 ++#define WLR8100_GPIO_LED_STATUS_RED 14 ++#define WLR8100_GPIO_LED_WPS_RED 15 ++#define WLR8100_GPIO_LED_STATUS_AMBER 19 ++#define WLR8100_GPIO_LED_WPS_GREEN 20 ++ ++#define WLR8100_GPIO_BTN_WPS 16 ++#define WLR8100_GPIO_BTN_RFKILL 21 ++ ++#define WLR8100_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WLR8100_KEYS_DEBOUNCE_INTERVAL (3 * WLR8100_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led wlr8100_leds_gpio[] __initdata = { ++ { ++ .name = "wlr8100:amber:status", ++ .gpio = WLR8100_GPIO_LED_STATUS_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "wlr8100:red:status", ++ .gpio = WLR8100_GPIO_LED_STATUS_RED, ++ .active_low = 1, ++ }, ++ { ++ .name = "wlr8100:green:wps", ++ .gpio = WLR8100_GPIO_LED_WPS_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "wlr8100:red:wps", ++ .gpio = WLR8100_GPIO_LED_WPS_RED, ++ .active_low = 1, ++ }, ++ { ++ .name = "wlr8100:red:wlan-2g", ++ .gpio = WLR8100_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "wlr8100:red:usb", ++ .gpio = WLR8100_GPIO_LED_USB, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wlr8100_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WLR8100_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WLR8100_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WLR8100_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WLR8100_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg wlr8100_ar8327_pad0_cfg; ++static struct ar8327_pad_cfg wlr8100_ar8327_pad6_cfg; ++ ++static struct ar8327_platform_data wlr8100_ar8327_data = { ++ .pad0_cfg = &wlr8100_ar8327_pad0_cfg, ++ .pad6_cfg = &wlr8100_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info wlr8100_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &wlr8100_ar8327_data, ++ }, ++}; ++ ++static void __init wlr8100_common_setup(void) ++{ ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wlr8100_leds_gpio), ++ wlr8100_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WLR8100_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wlr8100_gpio_keys), ++ wlr8100_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac_simple(); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(wlr8100_mdio0_info, ++ ARRAY_SIZE(wlr8100_mdio0_info)); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected tot eh SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(1); ++} ++ ++static void __init wlr8100_010_setup(void) ++{ ++ /* GMAC0 of the AR8337 switch is connected to GMAC0 via RGMII */ ++ wlr8100_ar8327_pad0_cfg.mode = AR8327_PAD_MAC_RGMII; ++ wlr8100_ar8327_pad0_cfg.txclk_delay_en = true; ++ wlr8100_ar8327_pad0_cfg.rxclk_delay_en = true; ++ wlr8100_ar8327_pad0_cfg.txclk_delay_sel = AR8327_CLK_DELAY_SEL1; ++ wlr8100_ar8327_pad0_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL2; ++ ++ /* GMAC6 of the AR8337 switch is connected to GMAC1 via SGMII */ ++ wlr8100_ar8327_pad6_cfg.mode = AR8327_PAD_MAC_SGMII; ++ wlr8100_ar8327_pad6_cfg.rxclk_delay_en = true; ++ wlr8100_ar8327_pad6_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL0; ++ ++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ wlr8100_common_setup(); ++ ap91_pci_init_simple(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WLR8100, "WLR8100", ++ "Sitecom WLR-8100", ++ wlr8100_010_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wndap360.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndap360.c +new file mode 100644 +index 0000000000..eae1c383ee +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndap360.c +@@ -0,0 +1,105 @@ ++/* ++ * Netgear WNDAP360 board support (proper leds / button support missing) ++ * ++ * Based on AP96 ++ * Copyright (C) 2013 Jacek Kikiewicz ++ * Copyright (C) 2009 Marco Porsch ++ * Copyright (C) 2009-2012 Gabor Juhos ++ * Copyright (C) 2010 Atheros Communications ++ * ++ * 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 "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define WNDAP360_GPIO_LED_POWER_ORANGE 0 ++#define WNDAP360_GPIO_LED_POWER_GREEN 2 ++ ++/* Reset button - next to the power connector */ ++#define WNDAP360_GPIO_BTN_RESET 8 ++ ++#define WNDAP360_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WNDAP360_KEYS_DEBOUNCE_INTERVAL (3 * WNDAP360_KEYS_POLL_INTERVAL) ++ ++#define WNDAP360_WMAC0_MAC_OFFSET 0x120c ++#define WNDAP360_WMAC1_MAC_OFFSET 0x520c ++#define WNDAP360_CALDATA0_OFFSET 0x1000 ++#define WNDAP360_CALDATA1_OFFSET 0x5000 ++ ++/* ++ * WNDAP360 this still uses leds definitions from AP96 ++ * ++ */ ++static struct gpio_led wndap360_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:green:power", ++ .gpio = WNDAP360_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:orange:power", ++ .gpio = WNDAP360_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wndap360_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNDAP360_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNDAP360_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++#define WNDAP360_LAN_PHYMASK 0x0f ++ ++static void __init wndap360_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_mdio(0, ~(WNDAP360_LAN_PHYMASK)); ++ ++ /* Reusing wifi MAC with offset of 1 as eth0 MAC */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + WNDAP360_WMAC0_MAC_OFFSET, 1); ++ ath79_eth0_pll_data.pll_1000 = 0x11110000; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = WNDAP360_LAN_PHYMASK; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_register_eth(0); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wndap360_leds_gpio), ++ wndap360_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WNDAP360_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wndap360_gpio_keys), ++ wndap360_gpio_keys); ++ ++ ap9x_pci_setup_wmac_led_pin(0, 5); ++ ap9x_pci_setup_wmac_led_pin(1, 5); ++ ++ ap94_pci_init(art + WNDAP360_CALDATA0_OFFSET, ++ art + WNDAP360_WMAC0_MAC_OFFSET, ++ art + WNDAP360_CALDATA1_OFFSET, ++ art + WNDAP360_WMAC1_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNDAP360, "WNDAP360", "NETGEAR WNDAP360", wndap360_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr3700.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr3700.c +new file mode 100644 +index 0000000000..b9132fc363 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr3700.c +@@ -0,0 +1,172 @@ ++/* ++ * Netgear WNDR3700 board support ++ * ++ * Copyright (C) 2009 Marco Porsch ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define WNDR3700_GPIO_LED_WPS_ORANGE 0 ++#define WNDR3700_GPIO_LED_POWER_ORANGE 1 ++#define WNDR3700_GPIO_LED_POWER_GREEN 2 ++#define WNDR3700_GPIO_LED_WPS_GREEN 4 ++#define WNDR3700_GPIO_LED_WAN_GREEN 6 ++ ++#define WNDR3700_GPIO_BTN_WPS 3 ++#define WNDR3700_GPIO_BTN_RESET 8 ++#define WNDR3700_GPIO_BTN_RFKILL 11 ++ ++#define WNDR3700_GPIO_RTL8366_SDA 5 ++#define WNDR3700_GPIO_RTL8366_SCK 7 ++ ++#define WNDR3700_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WNDR3700_KEYS_DEBOUNCE_INTERVAL (3 * WNDR3700_KEYS_POLL_INTERVAL) ++ ++#define WNDR3700_ETH0_MAC_OFFSET 0 ++#define WNDR3700_ETH1_MAC_OFFSET 0x6 ++ ++#define WNDR3700_WMAC0_MAC_OFFSET 0 ++#define WNDR3700_WMAC1_MAC_OFFSET 0xc ++#define WNDR3700_CALDATA0_OFFSET 0x1000 ++#define WNDR3700_CALDATA1_OFFSET 0x5000 ++ ++static struct gpio_led wndr3700_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:green:power", ++ .gpio = WNDR3700_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:orange:power", ++ .gpio = WNDR3700_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wps", ++ .gpio = WNDR3700_GPIO_LED_WPS_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:orange:wps", ++ .gpio = WNDR3700_GPIO_LED_WPS_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wan", ++ .gpio = WNDR3700_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wndr3700_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNDR3700_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNDR3700_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WNDR3700_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNDR3700_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, { ++ .desc = "rfkill", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WNDR3700_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNDR3700_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ } ++}; ++ ++static struct rtl8366_platform_data wndr3700_rtl8366s_data = { ++ .gpio_sda = WNDR3700_GPIO_RTL8366_SDA, ++ .gpio_sck = WNDR3700_GPIO_RTL8366_SCK, ++}; ++ ++static struct platform_device wndr3700_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &wndr3700_rtl8366s_data, ++ } ++}; ++ ++static void __init wndr3700_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ /* ++ * The eth0 and wmac0 interfaces share the same MAC address which ++ * can lead to problems if operated unbridged. Set the locally ++ * administered bit on the eth0 MAC to make it unique. ++ */ ++ ath79_init_local_mac(ath79_eth0_data.mac_addr, ++ art + WNDR3700_ETH0_MAC_OFFSET); ++ ath79_eth0_pll_data.pll_1000 = 0x11110000; ++ ath79_eth0_data.mii_bus_dev = &wndr3700_rtl8366s_device.dev; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, ++ art + WNDR3700_ETH1_MAC_OFFSET, 0); ++ ath79_eth1_pll_data.pll_1000 = 0x11110000; ++ ath79_eth1_data.mii_bus_dev = &wndr3700_rtl8366s_device.dev; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wndr3700_leds_gpio), ++ wndr3700_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WNDR3700_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wndr3700_gpio_keys), ++ wndr3700_gpio_keys); ++ ++ platform_device_register(&wndr3700_rtl8366s_device); ++ platform_device_register_simple("wndr3700-led-usb", -1, NULL, 0); ++ ++ ap9x_pci_setup_wmac_led_pin(0, 5); ++ ap9x_pci_setup_wmac_led_pin(1, 5); ++ ++ /* 2.4 GHz uses the first fixed antenna group (1, 0, 1, 0) */ ++ ap9x_pci_setup_wmac_gpio(0, (0xf << 6), (0xa << 6)); ++ ++ /* 5 GHz uses the second fixed antenna group (0, 1, 1, 0) */ ++ ap9x_pci_setup_wmac_gpio(1, (0xf << 6), (0x6 << 6)); ++ ++ ap94_pci_init(art + WNDR3700_CALDATA0_OFFSET, ++ art + WNDR3700_WMAC0_MAC_OFFSET, ++ art + WNDR3700_CALDATA1_OFFSET, ++ art + WNDR3700_WMAC1_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNDR3700, "WNDR3700", ++ "NETGEAR WNDR3700/WNDR3800/WNDRMAC", ++ wndr3700_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr4300.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr4300.c +new file mode 100644 +index 0000000000..339216da1b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wndr4300.c +@@ -0,0 +1,215 @@ ++/* ++ * NETGEAR WNDR3700v4/WNDR4300 board support ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2014 Ralph Perlich ++ * ++ * 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 ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++ ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++/* AR9344 GPIOs */ ++#define WNDR4300_GPIO_LED_POWER_GREEN 0 ++#define WNDR4300_GPIO_LED_POWER_AMBER 2 ++#define WNDR4300_GPIO_LED_USB 13 ++#define WNDR4300_GPIO_LED_WAN_GREEN 1 ++#define WNDR4300_GPIO_LED_WAN_AMBER 3 ++#define WNDR4300_GPIO_LED_WLAN2G 11 ++#define WNDR4300_GPIO_LED_WLAN5G 14 ++#define WNDR4300_GPIO_LED_WPS_GREEN 16 ++#define WNDR4300_GPIO_LED_WPS_AMBER 17 ++ ++#define WNDR4300_GPIO_BTN_RESET 21 ++#define WNDR4300_GPIO_BTN_WIRELESS 15 ++#define WNDR4300_GPIO_BTN_WPS 12 ++ ++/* AR9580 GPIOs */ ++#define WNDR4300_GPIO_USB_5V 0 ++ ++#define WNDR4300_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WNDR4300_KEYS_DEBOUNCE_INTERVAL (3 * WNDR4300_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led wndr4300_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:green:power", ++ .gpio = WNDR4300_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:power", ++ .gpio = WNDR4300_GPIO_LED_POWER_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:wan", ++ .gpio = WNDR4300_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:wan", ++ .gpio = WNDR4300_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:usb", ++ .gpio = WNDR4300_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:wps", ++ .gpio = WNDR4300_GPIO_LED_WPS_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:wps", ++ .gpio = WNDR4300_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:wlan2g", ++ .gpio = WNDR4300_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:blue:wlan5g", ++ .gpio = WNDR4300_GPIO_LED_WLAN5G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wndr4300_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNDR4300_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNDR4300_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WNDR4300_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNDR4300_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "rfkill", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WNDR4300_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNDR4300_GPIO_BTN_WIRELESS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg wndr4300_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg wndr4300_ar8327_led_cfg = { ++ .led_ctrl0 = 0xcc35cc35, ++ .led_ctrl1 = 0xcb37cb37, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x00f3cf00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data wndr4300_ar8327_data = { ++ .pad0_cfg = &wndr4300_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &wndr4300_ar8327_led_cfg, ++}; ++ ++static struct mdio_board_info wndr4300_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &wndr4300_ar8327_data, ++ }, ++}; ++ ++static void __init wndr4300_setup(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(wndr4300_leds_gpio); i++) ++ ath79_gpio_output_select(wndr4300_leds_gpio[i].gpio, ++ AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wndr4300_leds_gpio), ++ wndr4300_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WNDR4300_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wndr4300_gpio_keys), ++ wndr4300_gpio_keys); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0); ++ ++ mdiobus_register_board_info(wndr4300_mdio0_info, ++ ARRAY_SIZE(wndr4300_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* GMAC0 is connected to an AR8327N switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++ ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_HW); ++ ath79_register_nfc(); ++ ath79_register_usb(); ++ ++ ath79_register_wmac_simple(); ++ ++ /* enable power for the USB port */ ++ ap9x_pci_setup_wmac_gpio(0, BIT(WNDR4300_GPIO_USB_5V), ++ BIT(WNDR4300_GPIO_USB_5V)); ++ ++ ap91_pci_init_simple(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNDR3700_V4, "WNDR3700_V4", "NETGEAR WNDR3700v4", ++ wndr4300_setup); ++MIPS_MACHINE(ATH79_MACH_WNDR4300, "WNDR4300", "NETGEAR WNDR4300", ++ wndr4300_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v3.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v3.c +new file mode 100644 +index 0000000000..76c9cb99c9 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v3.c +@@ -0,0 +1,637 @@ ++/* ++ * NETGEAR WNR2000v3/WNR612v2/WNR1000v2/WPN824N board support ++ * ++ * Copyright (C) 2015 Hartmut Knaack ++ * Copyright (C) 2013 Mathieu Olivari ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2008-2009 Andy Boyett ++ * ++ * 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 /* for max() macro */ ++#include /* PLATFORM_DEVID_AUTO is defined here */ ++ ++#include ++#include /* needed to disable switch LEDs */ ++#include "common.h" /* needed to disable switch LEDs */ ++ ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++/* WNR2000v3 - connected through AR7241 */ ++#define WNR2000V3_GPIO_LED_WAN_GREEN 0 ++#define WNR2000V3_GPIO_LED_LAN1_AMBER 1 ++#define WNR2000V3_GPIO_LED_LAN2_AMBER 6 ++#define WNR2000V3_GPIO_LED_WPS_GREEN 7 ++#define WNR2000V3_GPIO_LED_LAN3_AMBER 8 ++#define WNR2000V3_GPIO_BTN_WPS 11 ++#define WNR2000V3_GPIO_LED_LAN4_AMBER 12 ++#define WNR2000V3_GPIO_LED_LAN1_GREEN 13 ++#define WNR2000V3_GPIO_LED_LAN2_GREEN 14 ++#define WNR2000V3_GPIO_LED_LAN3_GREEN 15 ++#define WNR2000V3_GPIO_LED_LAN4_GREEN 16 ++#define WNR2000V3_GPIO_LED_WAN_AMBER 17 ++ ++/* WNR2000v3 - connected through AR9287 */ ++#define WNR2000V3_GPIO_WMAC_LED_WLAN_BLUE 1 ++#define WNR2000V3_GPIO_WMAC_LED_TEST_AMBER 2 ++#define WNR2000V3_GPIO_WMAC_LED_POWER_GREEN 3 ++#define WNR2000V3_GPIO_WMAC_BTN_RESET 8 ++#define WNR2000V3_GPIO_WMAC_BTN_RFKILL 9 ++ ++/* WNR612v2 - connected through AR7241 */ ++#define WNR612V2_GPIO_LED_POWER_GREEN 11 ++#define WNR612V2_GPIO_LED_LAN1_GREEN 13 ++#define WNR612V2_GPIO_LED_LAN2_GREEN 14 ++#define WNR612V2_GPIO_LED_WAN_GREEN 17 ++ ++/* WNR612v2 - connected through AR9285 */ ++#define WNR612V2_GPIO_WMAC_LED_WLAN_GREEN 1 ++#define WNR612V2_GPIO_WMAC_BTN_RESET 7 ++ ++/* WNR1000v2 - connected through AR7240 */ ++#define WNR1000V2_GPIO_LED_WAN_AMBER 0 ++#define WNR1000V2_GPIO_LED_TEST_AMBER 1 ++#define WNR1000V2_GPIO_LED_LAN1_AMBER 6 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WNR1000V2_GPIO_LED_LAN2_AMBER 7 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WNR1000V2_GPIO_LED_LAN3_AMBER 8 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WNR1000V2_GPIO_LED_POWER_GREEN 11 ++#define WNR1000V2_GPIO_LED_LAN4_AMBER 12 ++#define WNR1000V2_GPIO_LED_LAN1_GREEN 13 /* AR724X_..._ETH_SWITCH_LED0 */ ++#define WNR1000V2_GPIO_LED_LAN2_GREEN 14 /* AR724X_..._ETH_SWITCH_LED1 */ ++#define WNR1000V2_GPIO_LED_LAN3_GREEN 15 /* AR724X_..._ETH_SWITCH_LED2 */ ++#define WNR1000V2_GPIO_LED_LAN4_GREEN 16 /* AR724X_..._ETH_SWITCH_LED3 */ ++#define WNR1000V2_GPIO_LED_WAN_GREEN 17 /* AR724X_..._ETH_SWITCH_LED4 */ ++ ++/* WNR1000v2 - connected through AR9285 */ ++#define WNR1000V2_GPIO_WMAC_LED_WLAN_BLUE 1 ++#define WNR1000V2_GPIO_WMAC_LED_WPS_GREEN 5 ++#define WNR1000V2_GPIO_WMAC_BTN_WPS 6 ++#define WNR1000V2_GPIO_WMAC_BTN_RESET 7 ++#define WNR1000V2_GPIO_WMAC_BTN_RFKILL 8 ++ ++/* WPN824N - connected through AR7240 */ ++#define WPN824N_GPIO_LED_WAN_AMBER 0 ++#define WPN824N_GPIO_LED_STATUS_AMBER 1 ++#define WPN824N_GPIO_LED_LAN1_AMBER 6 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WPN824N_GPIO_LED_LAN2_AMBER 7 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WPN824N_GPIO_LED_LAN3_AMBER 8 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WPN824N_GPIO_LED_LAN4_AMBER 12 ++#define WPN824N_GPIO_LED_LAN1_GREEN 13 ++#define WPN824N_GPIO_LED_LAN2_GREEN 14 ++#define WPN824N_GPIO_LED_LAN3_GREEN 15 /* AR724X_GPIO_FUNC_CLK_OBS3_EN */ ++#define WPN824N_GPIO_LED_LAN4_GREEN 16 ++#define WPN824N_GPIO_LED_WAN_GREEN 17 ++ ++/* WPN824N - connected through AR9285 */ ++#define WPN824N_WGPIO_LED_PWR_GREEN 0 ++#define WPN824N_WGPIO_LED_WLAN_BLUE 1 ++#define WPN824N_WGPIO_LED_WPS1_BLUE 5 ++#define WPN824N_WGPIO_LED_WPS2_BLUE 9 ++#define WPN824N_WGPIO_LED_TEST_AMBER 10 ++#define WPN824N_WGPIO_BTN_WPS 6 ++#define WPN824N_WGPIO_BTN_RESET 7 ++#define WPN824N_WGPIO_BTN_WLAN 8 ++ ++#define WNR2000V3_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WNR2000V3_KEYS_DEBOUNCE_INTERVAL (3 * WNR2000V3_KEYS_POLL_INTERVAL) ++ ++/* ART offsets for: WNR2000v3, WNR612v2, WNR1000v2 */ ++#define WNR2000V3_MAC0_OFFSET 0 ++#define WNR2000V3_MAC1_OFFSET 6 ++#define WNR2000V3_PCIE_CALDATA_OFFSET 0x1000 ++#define WNR2000V3_WMAC_OFFSET 0x108c /* wireless MAC is inside ART */ ++ ++static struct gpio_led wnr2000v3_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:green:wan", ++ .gpio = WNR2000V3_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan1", ++ .gpio = WNR2000V3_GPIO_LED_LAN1_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan2", ++ .gpio = WNR2000V3_GPIO_LED_LAN2_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan3", ++ .gpio = WNR2000V3_GPIO_LED_LAN3_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan4", ++ .gpio = WNR2000V3_GPIO_LED_LAN4_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wps", ++ .gpio = WNR2000V3_GPIO_LED_WPS_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan1", ++ .gpio = WNR2000V3_GPIO_LED_LAN1_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan2", ++ .gpio = WNR2000V3_GPIO_LED_LAN2_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan3", ++ .gpio = WNR2000V3_GPIO_LED_LAN3_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan4", ++ .gpio = WNR2000V3_GPIO_LED_LAN4_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:wan", ++ .gpio = WNR2000V3_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led wnr2000v3_wmac_leds_gpio[] = { ++ { ++ .name = "netgear:green:power", ++ .gpio = WNR2000V3_GPIO_WMAC_LED_POWER_GREEN, ++ .active_low = 1, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, { ++ .name = "netgear:amber:test", ++ .gpio = WNR2000V3_GPIO_WMAC_LED_TEST_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:blue:wlan", ++ .gpio = WNR2000V3_GPIO_WMAC_LED_WLAN_BLUE, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led wnr612v2_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:green:power", ++ .gpio = WNR612V2_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan1", ++ .gpio = WNR612V2_GPIO_LED_LAN1_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan2", ++ .gpio = WNR612V2_GPIO_LED_LAN2_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wan", ++ .gpio = WNR612V2_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led wnr612v2_wmac_leds_gpio[] = { ++ { ++ .name = "netgear:green:wlan", ++ .gpio = WNR612V2_GPIO_WMAC_LED_WLAN_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led wnr1000v2_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:amber:lan1", ++ .gpio = WNR1000V2_GPIO_LED_LAN1_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan2", ++ .gpio = WNR1000V2_GPIO_LED_LAN2_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan3", ++ .gpio = WNR1000V2_GPIO_LED_LAN3_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan4", ++ .gpio = WNR1000V2_GPIO_LED_LAN4_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:test", ++ .gpio = WNR1000V2_GPIO_LED_TEST_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:wan", ++ .gpio = WNR1000V2_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan1", ++ .gpio = WNR1000V2_GPIO_LED_LAN1_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan2", ++ .gpio = WNR1000V2_GPIO_LED_LAN2_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan3", ++ .gpio = WNR1000V2_GPIO_LED_LAN3_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan4", ++ .gpio = WNR1000V2_GPIO_LED_LAN4_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:power", ++ .gpio = WNR1000V2_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wan", ++ .gpio = WNR1000V2_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led wnr1000v2_wmac_leds_gpio[] = { ++ { ++ .name = "netgear:green:wps", ++ .gpio = WNR1000V2_GPIO_WMAC_LED_WPS_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:blue:wlan", ++ .gpio = WNR1000V2_GPIO_WMAC_LED_WLAN_BLUE, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led wpn824n_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:amber:wan", ++ .gpio = WPN824N_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:status", ++ .gpio = WPN824N_GPIO_LED_STATUS_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan1", ++ .gpio = WPN824N_GPIO_LED_LAN1_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan2", ++ .gpio = WPN824N_GPIO_LED_LAN2_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan3", ++ .gpio = WPN824N_GPIO_LED_LAN3_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan4", ++ .gpio = WPN824N_GPIO_LED_LAN4_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan1", ++ .gpio = WPN824N_GPIO_LED_LAN1_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan2", ++ .gpio = WPN824N_GPIO_LED_LAN2_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan3", ++ .gpio = WPN824N_GPIO_LED_LAN3_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan4", ++ .gpio = WPN824N_GPIO_LED_LAN4_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wan", ++ .gpio = WPN824N_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led wpn824n_wmac_leds_gpio[] = { ++ { ++ .name = "netgear:green:power", ++ .gpio = WPN824N_WGPIO_LED_PWR_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:blue:wps1", ++ .gpio = WPN824N_WGPIO_LED_WPS1_BLUE, ++ .active_low = 1, ++ }, { ++ .name = "netgear:blue:wps2", ++ .gpio = WPN824N_WGPIO_LED_WPS2_BLUE, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:test", ++ .gpio = WPN824N_WGPIO_LED_TEST_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:blue:wlan", ++ .gpio = WPN824N_WGPIO_LED_WLAN_BLUE, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wnr2000v3_keys_gpio[] __initdata = { ++ { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2000V3_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wnr2000v3_wmac_keys_gpio[] = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2000V3_GPIO_WMAC_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "rfkill", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2000V3_GPIO_WMAC_BTN_RFKILL, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wnr612v2_wmac_keys_gpio[] = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR612V2_GPIO_WMAC_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wnr1000v2_wmac_keys_gpio[] = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR1000V2_GPIO_WMAC_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "rfkill", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR1000V2_GPIO_WMAC_BTN_RFKILL, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR1000V2_GPIO_WMAC_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wpn824n_wmac_keys_gpio[] = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPN824N_WGPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "rfkill", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPN824N_WGPIO_BTN_WLAN, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WNR2000V3_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPN824N_WGPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++/* ++ * For WNR2000v3 ART flash area used for WLAN MAC is usually empty (0xff) ++ * so ath9k driver uses random MAC instead each time module is loaded. ++ * To fix that, assign permanent WLAN MAC equal to ethN's MAC plus 1, ++ * so network interfaces get sequential addresses. ++ * If ART wireless MAC address field has been filled by user, use it. ++ */ ++static void __init wnr_get_wmac(u8 *wmac_gen_addr, int mac0_art_offset, ++ int mac1_art_offset, int wmac_art_offset) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *eth0_mac_addr = (u8 *) (art + mac0_art_offset); ++ u8 *eth1_mac_addr = (u8 *) (art + mac1_art_offset); ++ u8 *wlan_mac_addr = (u8 *) (art + wmac_art_offset); ++ ++ /* only 0xff if all bits are set - address is invalid, empty area */ ++ if ((wlan_mac_addr[0] & wlan_mac_addr[1] & wlan_mac_addr[2] & ++ wlan_mac_addr[3] & wlan_mac_addr[4] & wlan_mac_addr[5]) == 0xff) { ++ memcpy(wmac_gen_addr, eth0_mac_addr, 5); ++ wmac_gen_addr[5] = max(eth0_mac_addr[5], eth1_mac_addr[5]) + 1; ++ ++ /* Avoid potential conflict in case max(0xff,0x00)+1==0x00 */ ++ if (!wmac_gen_addr[5]) ++ wmac_gen_addr[5] = 1; ++ } else ++ memcpy(wmac_gen_addr, wlan_mac_addr, 6); ++} ++ ++static void __init wnr_common_setup(u8 *wmac_addr) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art+WNR2000V3_MAC0_OFFSET, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art+WNR2000V3_MAC1_OFFSET, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ap91_pci_init(art + WNR2000V3_PCIE_CALDATA_OFFSET, wmac_addr); ++} ++ ++static void __init wnr2000v3_setup(void) ++{ ++ u8 wlan_mac_addr[6]; ++ ++ /* ++ * Disable JTAG to use all AR724X GPIO LEDs. ++ * Also disable CLKs and bit 20 as u-boot does. ++ * Finally, allow OS to control all link LEDs. ++ */ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE | ++ AR724X_GPIO_FUNC_UART_EN, ++ AR724X_GPIO_FUNC_CLK_OBS1_EN | ++ AR724X_GPIO_FUNC_CLK_OBS2_EN | ++ AR724X_GPIO_FUNC_CLK_OBS3_EN | ++ AR724X_GPIO_FUNC_CLK_OBS4_EN | ++ AR724X_GPIO_FUNC_CLK_OBS5_EN | ++ AR724X_GPIO_FUNC_GE0_MII_CLK_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN | ++ BIT(20)); ++ ++ wnr_get_wmac(wlan_mac_addr, WNR2000V3_MAC0_OFFSET, ++ WNR2000V3_MAC1_OFFSET, WNR2000V3_WMAC_OFFSET); ++ ++ wnr_common_setup(wlan_mac_addr); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wnr2000v3_leds_gpio), ++ wnr2000v3_leds_gpio); ++ ++ /* Do not use id=-1, we can have more GPIO key-polled devices */ ++ ath79_register_gpio_keys_polled(PLATFORM_DEVID_AUTO, ++ WNR2000V3_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wnr2000v3_keys_gpio), ++ wnr2000v3_keys_gpio); ++ ++ ap9x_pci_setup_wmac_leds(0, wnr2000v3_wmac_leds_gpio, ++ ARRAY_SIZE(wnr2000v3_wmac_leds_gpio)); ++ ++ ap9x_pci_setup_wmac_btns(0, wnr2000v3_wmac_keys_gpio, ++ ARRAY_SIZE(wnr2000v3_wmac_keys_gpio), ++ WNR2000V3_KEYS_POLL_INTERVAL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNR2000_V3, "WNR2000V3", "NETGEAR WNR2000 V3", wnr2000v3_setup); ++ ++static void __init wnr612v2_setup(void) ++{ ++ u8 wlan_mac_addr[6]; ++ ++ /* ++ * Disable JTAG and CLKs. Allow OS to control all link LEDs. ++ * Note: U-Boot for WNR612v2 sets undocumented bit 15 but ++ * we leave it for now. ++ */ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE | ++ AR724X_GPIO_FUNC_UART_EN, ++ AR724X_GPIO_FUNC_CLK_OBS1_EN | ++ AR724X_GPIO_FUNC_CLK_OBS2_EN | ++ AR724X_GPIO_FUNC_CLK_OBS3_EN | ++ AR724X_GPIO_FUNC_CLK_OBS4_EN | ++ AR724X_GPIO_FUNC_CLK_OBS5_EN | ++ AR724X_GPIO_FUNC_GE0_MII_CLK_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ wnr_get_wmac(wlan_mac_addr, WNR2000V3_MAC0_OFFSET, ++ WNR2000V3_MAC1_OFFSET, WNR2000V3_WMAC_OFFSET); ++ ++ wnr_common_setup(wlan_mac_addr); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wnr612v2_leds_gpio), ++ wnr612v2_leds_gpio); ++ ++ ap9x_pci_setup_wmac_leds(0, wnr612v2_wmac_leds_gpio, ++ ARRAY_SIZE(wnr612v2_wmac_leds_gpio)); ++ ++ ap9x_pci_setup_wmac_btns(0, wnr612v2_wmac_keys_gpio, ++ ARRAY_SIZE(wnr612v2_wmac_keys_gpio), ++ WNR2000V3_KEYS_POLL_INTERVAL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNR612_V2, "WNR612V2", "NETGEAR WNR612 V2", wnr612v2_setup); ++ ++static void __init wnr1000v2_setup(void) ++{ ++ u8 wlan_mac_addr[6]; ++ ++ /* ++ * Disable JTAG and CLKs. Allow OS to control all link LEDs. ++ * Note: U-Boot for WNR1000v2 sets undocumented bit 15 but ++ * we leave it for now. ++ */ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE | ++ AR724X_GPIO_FUNC_UART_EN, ++ AR724X_GPIO_FUNC_CLK_OBS1_EN | ++ AR724X_GPIO_FUNC_CLK_OBS2_EN | ++ AR724X_GPIO_FUNC_CLK_OBS3_EN | ++ AR724X_GPIO_FUNC_CLK_OBS4_EN | ++ AR724X_GPIO_FUNC_CLK_OBS5_EN | ++ AR724X_GPIO_FUNC_GE0_MII_CLK_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ wnr_get_wmac(wlan_mac_addr, WNR2000V3_MAC0_OFFSET, ++ WNR2000V3_MAC1_OFFSET, WNR2000V3_WMAC_OFFSET); ++ ++ wnr_common_setup(wlan_mac_addr); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wnr1000v2_leds_gpio), ++ wnr1000v2_leds_gpio); ++ ++ ap9x_pci_setup_wmac_leds(0, wnr1000v2_wmac_leds_gpio, ++ ARRAY_SIZE(wnr1000v2_wmac_leds_gpio)); ++ ++ /* All 3 buttons are connected to wireless chip */ ++ ap9x_pci_setup_wmac_btns(0, wnr1000v2_wmac_keys_gpio, ++ ARRAY_SIZE(wnr1000v2_wmac_keys_gpio), ++ WNR2000V3_KEYS_POLL_INTERVAL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNR1000_V2, "WNR1000V2", "NETGEAR WNR1000 V2", wnr1000v2_setup); ++ ++static void __init wpn824n_setup(void) ++{ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE, ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN | ++ AR724X_GPIO_FUNC_CLK_OBS3_EN); ++ ++ wnr_common_setup(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wpn824n_leds_gpio), ++ wpn824n_leds_gpio); ++ ++ ap9x_pci_setup_wmac_leds(0, wpn824n_wmac_leds_gpio, ++ ARRAY_SIZE(wpn824n_wmac_leds_gpio)); ++ ap9x_pci_setup_wmac_btns(0, wpn824n_wmac_keys_gpio, ++ ARRAY_SIZE(wpn824n_wmac_keys_gpio), ++ WNR2000V3_KEYS_POLL_INTERVAL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WPN824N, "WPN824N", "NETGEAR WPN824N", wpn824n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v4.c +new file mode 100644 +index 0000000000..c5159a30ca +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000-v4.c +@@ -0,0 +1,214 @@ ++/* ++ * NETGEAR WNR2000v4 board support ++ * ++ * Copyright (C) 2015 Michael Bazzinotti ++ * Copyright (C) 2014 Michaël Burtin ++ * Copyright (C) 2013 Mathieu Olivari ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2008-2009 Andy Boyett ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++/* AR9341 GPIOs */ ++#define WNR2000V4_GPIO_LED_PWR_GREEN 0 ++#define WNR2000V4_GPIO_LED_PWR_AMBER 1 ++#define WNR2000V4_GPIO_LED_WPS 2 ++#define WNR2000V4_GPIO_LED_WLAN 12 ++#define WNR2000V4_GPIO_LED_LAN1_GREEN 13 ++#define WNR2000V4_GPIO_LED_LAN2_GREEN 14 ++#define WNR2000V4_GPIO_LED_LAN3_GREEN 15 ++#define WNR2000V4_GPIO_LED_LAN4_GREEN 16 ++#define WNR2000V4_GPIO_LED_LAN1_AMBER 18 ++#define WNR2000V4_GPIO_LED_LAN2_AMBER 19 ++#define WNR2000V4_GPIO_LED_LAN3_AMBER 20 ++#define WNR2000V4_GPIO_LED_LAN4_AMBER 21 ++#define WNR2000V4_GPIO_LED_WAN_GREEN 17 ++#define WNR2000V4_GPIO_LED_WAN_AMBER 22 ++/* Buttons */ ++#define WNR2000V4_GPIO_BTN_WPS 3 ++#define WNR2000V4_GPIO_BTN_RESET 4 ++#define WNR2000V4_GPIO_BTN_WLAN 11 ++#define WNR2000V4_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WNR2000V4_KEYS_DEBOUNCE_INTERVAL (3 * WNR2000V4_KEYS_POLL_INTERVAL) ++ ++ ++/* ART offsets */ ++#define WNR2000V4_MAC0_OFFSET 0 /* WAN/WLAN0 MAC */ ++#define WNR2000V4_MAC1_OFFSET 6 /* Eth-switch0 MAC */ ++ ++static struct gpio_led wnr2000v4_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:green:power", ++ .gpio = WNR2000V4_GPIO_LED_PWR_GREEN, ++ .active_low = 1, ++ .default_trigger = "default-on", ++ }, ++ { ++ .name = "netgear:amber:status", ++ .gpio = WNR2000V4_GPIO_LED_PWR_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:wan", ++ .gpio = WNR2000V4_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:wan", ++ .gpio = WNR2000V4_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:blue:wlan", ++ .gpio = WNR2000V4_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ /* LAN LEDS */ ++ { ++ .name = "netgear:green:lan1", ++ .gpio = WNR2000V4_GPIO_LED_LAN1_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:lan2", ++ .gpio = WNR2000V4_GPIO_LED_LAN2_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:lan3", ++ .gpio = WNR2000V4_GPIO_LED_LAN3_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:lan4", ++ .gpio = WNR2000V4_GPIO_LED_LAN4_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:lan1", ++ .gpio = WNR2000V4_GPIO_LED_LAN1_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:lan2", ++ .gpio = WNR2000V4_GPIO_LED_LAN2_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:lan3", ++ .gpio = WNR2000V4_GPIO_LED_LAN3_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:amber:lan4", ++ .gpio = WNR2000V4_GPIO_LED_LAN4_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "netgear:green:wps", ++ .gpio = WNR2000V4_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wnr2000v4_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WNR2000V4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2000V4_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNR2000V4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2000V4_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WLAN button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WNR2000V4_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2000V4_GPIO_BTN_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init wnr_common_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_register_usb(); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art+WNR2000V4_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art+WNR2000V4_MAC1_OFFSET, 0); ++ ++ /* GMAC0 is connected to the PHY0 of the internal switch, GE0 */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = BIT(4); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio1_device.dev; ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the internal switch, GE1 */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(ee, art); ++} ++ ++static void __init wnr2000v4_setup(void) ++{ ++ int i; ++ ++ wnr_common_setup(); ++ ++ /* Ensure no LED has an internal MUX signal, otherwise ++ control of LED could be lost... This is especially important ++ for most green LEDS (Eth,WAN).. who arrive in this function with ++ MUX signals set. */ ++ for (i = 0; i < ARRAY_SIZE(wnr2000v4_leds_gpio); i++) ++ ath79_gpio_output_select(wnr2000v4_leds_gpio[i].gpio, ++ AR934X_GPIO_OUT_GPIO); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wnr2000v4_leds_gpio), ++ wnr2000v4_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WNR2000V4_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wnr2000v4_gpio_keys), ++ wnr2000v4_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNR2000_V4, "WNR2000V4", "NETGEAR WNR2000 V4", wnr2000v4_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000.c +new file mode 100644 +index 0000000000..6e3becab3a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2000.c +@@ -0,0 +1,102 @@ ++/* ++ * NETGEAR WNR2000 board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2008-2009 Andy Boyett ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WNR2000_GPIO_LED_PWR_GREEN 14 ++#define WNR2000_GPIO_LED_PWR_AMBER 7 ++#define WNR2000_GPIO_LED_WPS 4 ++#define WNR2000_GPIO_LED_WLAN 6 ++#define WNR2000_GPIO_BTN_RESET 21 ++#define WNR2000_GPIO_BTN_WPS 8 ++ ++#define WNR2000_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WNR2000_KEYS_DEBOUNCE_INTERVAL (3 * WNR2000_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led wnr2000_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:green:power", ++ .gpio = WNR2000_GPIO_LED_PWR_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:power", ++ .gpio = WNR2000_GPIO_LED_PWR_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wps", ++ .gpio = WNR2000_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "netgear:blue:wlan", ++ .gpio = WNR2000_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wnr2000_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNR2000_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2000_GPIO_BTN_RESET, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WNR2000_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2000_GPIO_BTN_WPS, ++ } ++}; ++ ++static void __init wnr2000_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, eeprom, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.has_ar8216 = 1; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, eeprom, 1); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wnr2000_leds_gpio), ++ wnr2000_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WNR2000_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wnr2000_gpio_keys), ++ wnr2000_gpio_keys); ++ ++ ath79_register_wmac(eeprom, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNR2000, "WNR2000", "NETGEAR WNR2000", wnr2000_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2200.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2200.c +new file mode 100644 +index 0000000000..74166c5376 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wnr2200.c +@@ -0,0 +1,246 @@ ++/* ++ * NETGEAR WNR2200 board support ++ * ++ * Copyright (C) 2013 Aidan Kissane ++ * ++ * 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 /* for max() macro */ ++ ++#include ++#include /* needed to disable switch LEDs */ ++#include "common.h" /* needed to disable switch LEDs */ ++ ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++/* WNR2200 - connected through AR7241 */ ++#define WNR2200_GPIO_LED_LAN2_AMBER 0 ++#define WNR2200_GPIO_LED_LAN4_AMBER 1 ++#define WNR2200_GPIO_LED_LAN1_AMBER 6 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WNR2200_GPIO_LED_WPS_GREEN 7 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WNR2200_GPIO_LED_USB_GREEN 8 /* AR724X_GPIO_FUNC_JTAG_DISABLE */ ++#define WNR2200_GPIO_LED_LAN3_AMBER 11 ++#define WNR2200_GPIO_LED_WAN_AMBER 12 ++#define WNR2200_GPIO_LED_LAN1_GREEN 13 /* AR724X_..._ETH_SWITCH_LED0 */ ++#define WNR2200_GPIO_LED_LAN2_GREEN 14 /* AR724X_..._ETH_SWITCH_LED1 */ ++#define WNR2200_GPIO_LED_LAN3_GREEN 15 /* AR724X_..._ETH_SWITCH_LED2 */ ++#define WNR2200_GPIO_LED_LAN4_GREEN 16 /* AR724X_..._ETH_SWITCH_LED3 */ ++#define WNR2200_GPIO_LED_WAN_GREEN 17 /* AR724X_..._ETH_SWITCH_LED4 */ ++ ++/* WNR2200 - connected through AR9287 */ ++#define WNR2200_GPIO_WMAC_LED_WLAN_BLUE 0 ++#define WNR2200_GPIO_WMAC_LED_TEST_AMBER 1 ++#define WNR2200_GPIO_WMAC_LED_POWER_GREEN 2 ++#define WNR2200_GPIO_WMAC_BTN_RFKILL 3 ++#define WNR2200_GPIO_WMAC_USB_5V 4 ++#define WNR2200_GPIO_WMAC_BTN_WPS 5 ++#define WNR2200_GPIO_WMAC_BTN_RESET 6 ++ ++#define WNR2200_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WNR2200_KEYS_DEBOUNCE_INTERVAL (3 * WNR2200_KEYS_POLL_INTERVAL) ++ ++#define WNR2200_MAC0_OFFSET 0 ++#define WNR2200_MAC1_OFFSET 6 ++#define WNR2200_PCIE_CALDATA_OFFSET 0x1000 ++#define WNR2200_WMAC_OFFSET 0x108c /* wireless MAC is inside ART */ ++ ++static struct gpio_led wnr2200_leds_gpio[] __initdata = { ++ { ++ .name = "netgear:amber:lan1", ++ .gpio = WNR2200_GPIO_LED_LAN1_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan2", ++ .gpio = WNR2200_GPIO_LED_LAN2_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan3", ++ .gpio = WNR2200_GPIO_LED_LAN3_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:lan4", ++ .gpio = WNR2200_GPIO_LED_LAN4_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:amber:wan", ++ .gpio = WNR2200_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan1", ++ .gpio = WNR2200_GPIO_LED_LAN1_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan2", ++ .gpio = WNR2200_GPIO_LED_LAN2_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan3", ++ .gpio = WNR2200_GPIO_LED_LAN3_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:lan4", ++ .gpio = WNR2200_GPIO_LED_LAN4_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:usb", ++ .gpio = WNR2200_GPIO_LED_USB_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wan", ++ .gpio = WNR2200_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:wps", ++ .gpio = WNR2200_GPIO_LED_WPS_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led wnr2200_wmac_leds_gpio[] = { ++ { ++ .name = "netgear:amber:test", ++ .gpio = WNR2200_GPIO_WMAC_LED_TEST_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "netgear:green:power", ++ .gpio = WNR2200_GPIO_WMAC_LED_POWER_GREEN, ++ .active_low = 1, ++ .default_state = LEDS_GPIO_DEFSTATE_ON, ++ }, { ++ .name = "netgear:blue:wlan", ++ .gpio = WNR2200_GPIO_WMAC_LED_WLAN_BLUE, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wnr2200_wmac_keys_gpio[] = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WNR2200_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2200_GPIO_WMAC_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "rfkill", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WNR2200_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2200_GPIO_WMAC_BTN_RFKILL, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WNR2200_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WNR2200_GPIO_WMAC_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++/* ++ * For WNR2200 ART flash area used for WLAN MAC is usually empty (0xff) ++ * so ath9k driver uses random MAC instead each time module is loaded. ++ * OpenWrt's original fix was to copy eth1 address to WLAN interface. ++ * New solution does not duplicate hardware addresses and is taken from ++ * WNR2000v3 code. It assigns permanent WLAN MAC equal to ethN's MAC ++ * plus 1, so network interfaces get sequential addresses. ++ * If ART wireless MAC address field has been filled by user, use it. ++ */ ++static void __init wnr2200_get_wmac(u8 *wmac_gen_addr, int mac0_art_offset, ++ int mac1_art_offset, int wmac_art_offset) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *eth0_mac_addr = (u8 *) (art + mac0_art_offset); ++ u8 *eth1_mac_addr = (u8 *) (art + mac1_art_offset); ++ u8 *wlan_mac_addr = (u8 *) (art + wmac_art_offset); ++ ++ /* only 0xff if all bits are set - address is invalid, empty area */ ++ if ((wlan_mac_addr[0] & wlan_mac_addr[1] & wlan_mac_addr[2] & ++ wlan_mac_addr[3] & wlan_mac_addr[4] & wlan_mac_addr[5]) == 0xff) { ++ memcpy(wmac_gen_addr, eth0_mac_addr, 5); ++ wmac_gen_addr[5] = max(eth0_mac_addr[5], eth1_mac_addr[5]) + 1; ++ ++ /* Avoid potential conflict in case max(0xff,0x00)+1==0x00 */ ++ if (!wmac_gen_addr[5]) ++ wmac_gen_addr[5] = 1; ++ } else ++ memcpy(wmac_gen_addr, wlan_mac_addr, 6); ++} ++ ++static void __init wnr2200_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 wlan_mac_addr[6]; ++ ++ /* ++ * Disable JTAG to use all AR724X GPIO LEDs. Disable CLKs. ++ * Allow OS to control all link LEDs. ++ */ ++ ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE | ++ AR724X_GPIO_FUNC_UART_EN, ++ AR724X_GPIO_FUNC_CLK_OBS1_EN | ++ AR724X_GPIO_FUNC_CLK_OBS2_EN | ++ AR724X_GPIO_FUNC_CLK_OBS3_EN | ++ AR724X_GPIO_FUNC_CLK_OBS4_EN | ++ AR724X_GPIO_FUNC_CLK_OBS5_EN | ++ AR724X_GPIO_FUNC_GE0_MII_CLK_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + WNR2200_MAC0_OFFSET, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + WNR2200_MAC1_OFFSET, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(NULL); ++ ++ wnr2200_get_wmac(wlan_mac_addr, WNR2200_MAC0_OFFSET, ++ WNR2200_MAC1_OFFSET, WNR2200_WMAC_OFFSET); ++ ap9x_pci_setup_wmac_led_pin(0, 0); ++ ap91_pci_init(art + WNR2200_PCIE_CALDATA_OFFSET, wlan_mac_addr); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wnr2200_leds_gpio), ++ wnr2200_leds_gpio); ++ ++ ap9x_pci_setup_wmac_leds(0, wnr2200_wmac_leds_gpio, ++ ARRAY_SIZE(wnr2200_wmac_leds_gpio)); ++ ++ /* All 3 buttons are connected to wireless chip */ ++ ap9x_pci_setup_wmac_btns(0, wnr2200_wmac_keys_gpio, ++ ARRAY_SIZE(wnr2200_wmac_keys_gpio), ++ WNR2200_KEYS_POLL_INTERVAL); ++ ++ /* enable power for the USB port */ ++ ap9x_pci_setup_wmac_gpio(0, BIT(WNR2200_GPIO_WMAC_USB_5V), ++ BIT(WNR2200_GPIO_WMAC_USB_5V)); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WNR2200, "WNR2200", "NETGEAR WNR2200", wnr2200_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wp543.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wp543.c +new file mode 100644 +index 0000000000..dc4aee0c1b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wp543.c +@@ -0,0 +1,109 @@ ++/* ++ * Compex WP543/WPJ543 board support ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define WP543_GPIO_SW6 2 ++#define WP543_GPIO_LED_1 3 ++#define WP543_GPIO_LED_2 4 ++#define WP543_GPIO_LED_WLAN 5 ++#define WP543_GPIO_LED_CONN 6 ++#define WP543_GPIO_LED_DIAG 7 ++#define WP543_GPIO_SW4 8 ++ ++#define WP543_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WP543_KEYS_DEBOUNCE_INTERVAL (3 * WP543_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led wp543_leds_gpio[] __initdata = { ++ { ++ .name = "wp543:green:led1", ++ .gpio = WP543_GPIO_LED_1, ++ .active_low = 1, ++ }, { ++ .name = "wp543:green:led2", ++ .gpio = WP543_GPIO_LED_2, ++ .active_low = 1, ++ }, { ++ .name = "wp543:green:wlan", ++ .gpio = WP543_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "wp543:green:conn", ++ .gpio = WP543_GPIO_LED_CONN, ++ .active_low = 1, ++ }, { ++ .name = "wp543:green:diag", ++ .gpio = WP543_GPIO_LED_DIAG, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wp543_gpio_keys[] __initdata = { ++ { ++ .desc = "sw6", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = WP543_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WP543_GPIO_SW6, ++ .active_low = 1, ++ }, { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WP543_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WP543_GPIO_SW4, ++ .active_low = 1, ++ } ++}; ++ ++static const char *wp543_part_probes[] = { ++ "MyLoader", ++ NULL, ++}; ++ ++static struct flash_platform_data wp543_flash_data = { ++ .part_probes = wp543_part_probes, ++}; ++ ++static void __init wp543_setup(void) ++{ ++ ath79_register_m25p80(&wp543_flash_data); ++ ++ ath79_register_mdio(0, 0xfffffff0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = 0x0f; ++ ath79_eth0_data.reset_bit = AR71XX_RESET_GE0_MAC | ++ AR71XX_RESET_GE0_PHY; ++ ath79_register_eth(0); ++ ++ ath79_register_usb(); ++ ath79_register_pci(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wp543_leds_gpio), ++ wp543_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WP543_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wp543_gpio_keys), ++ wp543_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WP543, "WP543", "Compex WP543", wp543_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wpe72.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpe72.c +new file mode 100644 +index 0000000000..9452484279 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpe72.c +@@ -0,0 +1,97 @@ ++/* ++ * Compex WPE72 board support ++ * ++ * Copyright (C) 2012 Johnathan Boyce ++ * ++ * 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 "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define WPE72_GPIO_RESET 12 ++#define WPE72_GPIO_LED_DIAG 13 ++#define WPE72_GPIO_LED_1 14 ++#define WPE72_GPIO_LED_2 15 ++#define WPE72_GPIO_LED_3 16 ++#define WPE72_GPIO_LED_4 17 ++ ++#define WPE72_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WPE72_KEYS_DEBOUNCE_INTERVAL (3 * WPE72_KEYS_POLL_INTERVAL) ++ ++static struct gpio_led wpe72_leds_gpio[] __initdata = { ++ { ++ .name = "wpe72:green:led1", ++ .gpio = WPE72_GPIO_LED_1, ++ .active_low = 1, ++ }, { ++ .name = "wpe72:green:led2", ++ .gpio = WPE72_GPIO_LED_2, ++ .active_low = 1, ++ }, { ++ .name = "wpe72:green:led3", ++ .gpio = WPE72_GPIO_LED_3, ++ .active_low = 1, ++ }, { ++ .name = "wpe72:green:led4", ++ .gpio = WPE72_GPIO_LED_4, ++ .active_low = 1, ++ }, { ++ .name = "wpe72:green:diag", ++ .gpio = WPE72_GPIO_LED_DIAG, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wpe72_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WPE72_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPE72_GPIO_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static const char *wpe72_part_probes[] = { ++ "MyLoader", ++ NULL, ++}; ++ ++static struct flash_platform_data wpe72_flash_data = { ++ .part_probes = wpe72_part_probes, ++}; ++ ++static void __init wpe72_setup(void) ++{ ++ ath79_register_m25p80(&wpe72_flash_data); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ath79_register_pci(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wpe72_leds_gpio), ++ wpe72_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WPE72_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wpe72_gpio_keys), ++ wpe72_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WPE72, "WPE72", "Compex WPE72", wpe72_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj342.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj342.c +new file mode 100644 +index 0000000000..65d6478867 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj342.c +@@ -0,0 +1,178 @@ ++/* ++ * Compex WPJ342 board support ++ * ++ * Copyright (c) 2011 Qualcomm Atheros ++ * Copyright (c) 2011-2012 Gabor Juhos ++ * ++ * 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 "pci.h" ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-nfc.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WPJ342_GPIO_LED_STATUS 11 ++#define WPJ342_GPIO_LED_SIG1 14 ++#define WPJ342_GPIO_LED_SIG2 13 ++#define WPJ342_GPIO_LED_SIG3 12 ++#define WPJ342_GPIO_LED_SIG4 11 ++#define WPJ342_GPIO_BUZZER 15 ++ ++#define WPJ342_GPIO_BTN_RESET 17 ++ ++#define WPJ342_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WPJ342_KEYS_DEBOUNCE_INTERVAL (3 * WPJ342_KEYS_POLL_INTERVAL) ++ ++#define WPJ342_MAC0_OFFSET 0x10 ++#define WPJ342_MAC1_OFFSET 0x18 ++#define WPJ342_WMAC_CALDATA_OFFSET 0x1000 ++#define WPJ342_PCIE_CALDATA_OFFSET 0x5000 ++ ++#define WPJ342_ART_SIZE 0x8000 ++ ++static struct gpio_led wpj342_leds_gpio[] __initdata = { ++ { ++ .name = "wpj342:red:sig1", ++ .gpio = WPJ342_GPIO_LED_SIG1, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj342:yellow:sig2", ++ .gpio = WPJ342_GPIO_LED_SIG2, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj342:green:sig3", ++ .gpio = WPJ342_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj342:green:sig4", ++ .gpio = WPJ342_GPIO_LED_SIG4, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj342:buzzer", ++ .gpio = WPJ342_GPIO_BUZZER, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button wpj342_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WPJ342_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPJ342_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg wpj342_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg wpj342_ar8327_led_cfg = { ++ .led_ctrl0 = 0x00000000, ++ .led_ctrl1 = 0xc737c737, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x00c30c00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data wpj342_ar8327_data = { ++ .pad0_cfg = &wpj342_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &wpj342_ar8327_led_cfg, ++}; ++ ++static struct mdio_board_info wpj342_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &wpj342_ar8327_data, ++ }, ++}; ++ ++ ++static void __init wpj342_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f02e000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wpj342_leds_gpio), ++ wpj342_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WPJ342_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wpj342_gpio_keys), ++ wpj342_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + WPJ342_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ++ mdiobus_register_board_info(wpj342_mdio0_info, ++ ARRAY_SIZE(wpj342_mdio0_info)); ++ ++ ath79_register_mdio(1, 0x0); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac + WPJ342_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac + WPJ342_MAC1_OFFSET, 0); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_MII_GMAC0); ++ ++ /* GMAC0 is connected to an AR8236 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WPJ342, "WPJ342", "Compex WPJ342", wpj342_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj344.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj344.c +new file mode 100644 +index 0000000000..ffb9ef6dfa +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj344.c +@@ -0,0 +1,169 @@ ++/* ++ * Compex WPJ344 board support ++ * ++ * Copyright (c) 2011 Qualcomm Atheros ++ * Copyright (c) 2011-2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-usb.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WPJ344_GPIO_LED_SIG1 15 ++#define WPJ344_GPIO_LED_SIG2 20 ++#define WPJ344_GPIO_LED_SIG3 21 ++#define WPJ344_GPIO_LED_SIG4 22 ++#define WPJ344_GPIO_LED_STATUS 14 ++ ++#define WPJ344_GPIO_BTN_RESET 12 ++ ++#define WPJ344_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WPJ344_KEYS_DEBOUNCE_INTERVAL (3 * WPJ344_KEYS_POLL_INTERVAL) ++ ++#define WPJ344_MAC0_OFFSET 0x10 ++#define WPJ344_MAC1_OFFSET 0x18 ++#define WPJ344_WMAC_CALDATA_OFFSET 0x1000 ++#define WPJ344_PCIE_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led wpj344_leds_gpio[] __initdata = { ++ { ++ .name = "wpj344:green:status", ++ .gpio = WPJ344_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj344:red:sig1", ++ .gpio = WPJ344_GPIO_LED_SIG1, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj344:yellow:sig2", ++ .gpio = WPJ344_GPIO_LED_SIG2, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj344:green:sig3", ++ .gpio = WPJ344_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj344:green:sig4", ++ .gpio = WPJ344_GPIO_LED_SIG4, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wpj344_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WPJ344_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPJ344_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg wpj344_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++ .mac06_exchange_dis = true, ++}; ++ ++static struct ar8327_led_cfg wpj344_ar8327_led_cfg = { ++ .led_ctrl0 = 0x00000000, ++ .led_ctrl1 = 0xc737c737, ++ .led_ctrl2 = 0x00000000, ++ .led_ctrl3 = 0x00c30c00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data wpj344_ar8327_data = { ++ .pad0_cfg = &wpj344_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &wpj344_ar8327_led_cfg, ++}; ++ ++static struct mdio_board_info wpj344_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &wpj344_ar8327_data, ++ }, ++}; ++ ++static void __init wpj344_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f02e000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wpj344_leds_gpio), ++ wpj344_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WPJ344_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wpj344_gpio_keys), ++ wpj344_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + WPJ344_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ++ mdiobus_register_board_info(wpj344_mdio0_info, ++ ARRAY_SIZE(wpj344_mdio0_info)); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac + WPJ344_MAC0_OFFSET, 0); ++ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ /* GMAC0 is connected to an AR8327 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WPJ344, "WPJ344", "Compex WPJ344", wpj344_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj531.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj531.c +new file mode 100644 +index 0000000000..351293230f +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj531.c +@@ -0,0 +1,143 @@ ++/* ++ * Compex WPJ531 board support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012 Gabor Juhos ++ * ++ * 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 "pci.h" ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WPJ531_GPIO_LED_SIG1 12 ++#define WPJ531_GPIO_LED_SIG2 14 ++#define WPJ531_GPIO_LED_SIG3 15 ++#define WPJ531_GPIO_LED_SIG4 16 ++#define WPJ531_GPIO_BUZZER 4 ++ ++#define WPJ531_GPIO_BTN_RESET 17 ++ ++#define WPJ531_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WPJ531_KEYS_DEBOUNCE_INTERVAL (3 * WPJ531_KEYS_POLL_INTERVAL) ++ ++#define WPJ531_MAC0_OFFSET 0x10 ++#define WPJ531_MAC1_OFFSET 0x18 ++#define WPJ531_WMAC_CALDATA_OFFSET 0x1000 ++#define WPJ531_PCIE_CALDATA_OFFSET 0x5000 ++ ++#define WPJ531_ART_SIZE 0x8000 ++ ++static struct gpio_led wpj531_leds_gpio[] __initdata = { ++ { ++ .name = "wpj531:red:sig1", ++ .gpio = WPJ531_GPIO_LED_SIG1, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj531:yellow:sig2", ++ .gpio = WPJ531_GPIO_LED_SIG2, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj531:green:sig3", ++ .gpio = WPJ531_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj531:green:sig4", ++ .gpio = WPJ531_GPIO_LED_SIG4, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj531:buzzer", ++ .gpio = WPJ531_GPIO_BUZZER, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button wpj531_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WPJ531_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPJ531_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init common_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f02e000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac + WPJ531_MAC0_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ /* WAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac + WPJ531_MAC1_OFFSET, 0); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + WPJ531_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++} ++ ++static void __init wpj531_setup(void) ++{ ++ common_setup(); ++ ++ ath79_register_leds_gpio(-1, ++ ARRAY_SIZE(wpj531_leds_gpio), ++ wpj531_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ++ WPJ531_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wpj531_gpio_keys), ++ wpj531_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WPJ531, "WPJ531", "Compex WPJ531", wpj531_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj558.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj558.c +new file mode 100644 +index 0000000000..1839cc6676 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj558.c +@@ -0,0 +1,170 @@ ++/* ++ * Compex WPJ558 board support ++ * ++ * Copyright (c) 2012 Qualcomm Atheros ++ * Copyright (c) 2012-2013 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-eth.h" ++#include "dev-usb.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WPJ558_GPIO_LED_SIG1 14 ++#define WPJ558_GPIO_LED_SIG2 15 ++#define WPJ558_GPIO_LED_SIG3 22 ++#define WPJ558_GPIO_LED_SIG4 23 ++#define WPJ558_GPIO_BUZZER 4 ++ ++#define WPJ558_GPIO_BTN_RESET 17 ++ ++#define WPJ558_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WPJ558_KEYS_DEBOUNCE_INTERVAL (3 * WPJ558_KEYS_POLL_INTERVAL) ++ ++#define WPJ558_MAC_OFFSET 0x10 ++#define WPJ558_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led wpj558_leds_gpio[] __initdata = { ++ { ++ .name = "wpj558:red:sig1", ++ .gpio = WPJ558_GPIO_LED_SIG1, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj558:yellow:sig2", ++ .gpio = WPJ558_GPIO_LED_SIG2, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj558:green:sig3", ++ .gpio = WPJ558_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj558:green:sig4", ++ .gpio = WPJ558_GPIO_LED_SIG4, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj558:buzzer", ++ .gpio = WPJ558_GPIO_BUZZER, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button wpj558_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WPJ558_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPJ558_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg wpj558_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_pad_cfg wpj558_ar8327_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data wpj558_ar8327_data = { ++ .pad0_cfg = &wpj558_ar8327_pad0_cfg, ++ .pad6_cfg = &wpj558_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info wpj558_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &wpj558_ar8327_data, ++ }, ++}; ++ ++static void __init wpj558_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f02e000); ++ ++ ath79_register_m25p80(NULL); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wpj558_leds_gpio), ++ wpj558_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WPJ558_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wpj558_gpio_keys), ++ wpj558_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + WPJ558_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ++ mdiobus_register_board_info(wpj558_mdio0_info, ++ ARRAY_SIZE(wpj558_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac + WPJ558_MAC_OFFSET, 0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* GMAC0 is connected to an AR8327 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WPJ558, "WPJ558", "Compex WPJ558", wpj558_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj563.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj563.c +new file mode 100644 +index 0000000000..d884be916b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wpj563.c +@@ -0,0 +1,150 @@ ++/* ++ * Compex WPJ563 board support ++ * ++ * Copyright (c) 2015 Qualcomm Atheros ++ * Copyright (c) 2012 Gabor Juhos ++ * ++ * 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 "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++#define WPJ563_GPIO_LED_SIG1 1 ++#define WPJ563_GPIO_LED_SIG2 5 ++#define WPJ563_GPIO_LED_SIG3 6 ++#define WPJ563_GPIO_LED_SIG4 7 ++#define WPJ563_GPIO_BUZZER 19 ++ ++#define WPJ563_GPIO_BTN_RESET 2 ++#define WPJ563_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WPJ563_KEYS_DEBOUNCE_INTERVAL (3 * WPJ563_KEYS_POLL_INTERVAL) ++ ++#define WPJ563_MAC0_OFFSET 0x10 ++#define WPJ563_MAC1_OFFSET 0x18 ++#define WPJ563_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led WPJ563_leds_gpio[] __initdata = { ++ { ++ .name = "wpj563:green:sig1", ++ .gpio = WPJ563_GPIO_LED_SIG1, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj563:green:sig2", ++ .gpio = WPJ563_GPIO_LED_SIG2, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj563:green:sig3", ++ .gpio = WPJ563_GPIO_LED_SIG3, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj563:green:sig4", ++ .gpio = WPJ563_GPIO_LED_SIG4, ++ .active_low = 1, ++ }, ++ { ++ .name = "wpj563:buzzer", ++ .gpio = WPJ563_GPIO_BUZZER, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_keys_button WPJ563_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WPJ563_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WPJ563_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg WPJ563_ar8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data WPJ563_ar8337_data = { ++ .pad0_cfg = &WPJ563_ar8337_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info WPJ563_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &WPJ563_ar8337_data, ++ }, ++}; ++ ++static void __init WPJ563_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f02e000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(WPJ563_leds_gpio), ++ WPJ563_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WPJ563_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(WPJ563_gpio_keys), ++ WPJ563_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + WPJ563_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_pci(); ++ ++ mdiobus_register_board_info(WPJ563_mdio0_info, ++ ARRAY_SIZE(WPJ563_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac + WPJ563_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac + WPJ563_MAC1_OFFSET, 0); ++ ++ /* GMAC0 is connected to an QCA8334 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WPJ563, "WPJ563", "Compex WPJ563", WPJ563_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wrt160nl.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wrt160nl.c +new file mode 100644 +index 0000000000..ede3c214c2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wrt160nl.c +@@ -0,0 +1,126 @@ ++/* ++ * Linksys WRT160NL board support ++ * ++ * Copyright (C) 2009-2012 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. ++ */ ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "nvram.h" ++#include "machtypes.h" ++ ++#define WRT160NL_GPIO_LED_POWER 14 ++#define WRT160NL_GPIO_LED_WPS_AMBER 9 ++#define WRT160NL_GPIO_LED_WPS_BLUE 8 ++#define WRT160NL_GPIO_LED_WLAN 6 ++ ++#define WRT160NL_GPIO_BTN_WPS 7 ++#define WRT160NL_GPIO_BTN_RESET 21 ++ ++#define WRT160NL_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WRT160NL_KEYS_DEBOUNCE_INTERVAL (3 * WRT160NL_KEYS_POLL_INTERVAL) ++ ++#define WRT160NL_NVRAM_ADDR 0x1f7e0000 ++#define WRT160NL_NVRAM_SIZE 0x10000 ++ ++static const char *wrt160nl_part_probes[] = { ++ "cybertan", ++ NULL, ++}; ++ ++static struct flash_platform_data wrt160nl_flash_data = { ++ .part_probes = wrt160nl_part_probes, ++}; ++ ++static struct gpio_led wrt160nl_leds_gpio[] __initdata = { ++ { ++ .name = "wrt160nl:blue:power", ++ .gpio = WRT160NL_GPIO_LED_POWER, ++ .active_low = 1, ++ .default_trigger = "default-on", ++ }, { ++ .name = "wrt160nl:amber:wps", ++ .gpio = WRT160NL_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "wrt160nl:blue:wps", ++ .gpio = WRT160NL_GPIO_LED_WPS_BLUE, ++ .active_low = 1, ++ }, { ++ .name = "wrt160nl:blue:wlan", ++ .gpio = WRT160NL_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wrt160nl_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WRT160NL_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WRT160NL_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WRT160NL_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WRT160NL_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init wrt160nl_setup(void) ++{ ++ const char *nvram = (char *) KSEG1ADDR(WRT160NL_NVRAM_ADDR); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[6]; ++ ++ if (ath79_nvram_parse_mac_addr(nvram, WRT160NL_NVRAM_SIZE, ++ "lan_hwaddr=", mac) == 0) { ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ } ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.phy_mask = 0x01; ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(&wrt160nl_flash_data); ++ ++ ath79_register_usb(); ++ ++ if (ath79_nvram_parse_mac_addr(nvram, WRT160NL_NVRAM_SIZE, ++ "wl0_hwaddr=", mac) == 0) ++ ath79_register_wmac(eeprom, mac); ++ else ++ ath79_register_wmac(eeprom, NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wrt160nl_leds_gpio), ++ wrt160nl_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WRT160NL_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wrt160nl_gpio_keys), ++ wrt160nl_gpio_keys); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WRT160NL, "WRT160NL", "Linksys WRT160NL", ++ wrt160nl_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wrt400n.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wrt400n.c +new file mode 100644 +index 0000000000..6c4c1cb0d6 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wrt400n.c +@@ -0,0 +1,161 @@ ++/* ++ * Linksys WRT400N board support ++ * ++ * Copyright (C) 2009-2012 Gabor Juhos ++ * Copyright (C) 2009 Imre Kaloz ++ * ++ * 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 "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++ ++#define WRT400N_GPIO_LED_POWER 1 ++#define WRT400N_GPIO_LED_WPS_BLUE 4 ++#define WRT400N_GPIO_LED_WPS_AMBER 5 ++#define WRT400N_GPIO_LED_WLAN 6 ++ ++#define WRT400N_GPIO_BTN_RESET 8 ++#define WRT400N_GPIO_BTN_WLSEC 3 ++ ++#define WRT400N_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WRT400N_KEYS_DEBOUNE_INTERVAL (3 * WRT400N_KEYS_POLL_INTERVAL) ++ ++#define WRT400N_MAC_ADDR_OFFSET 0x120c ++#define WRT400N_CALDATA0_OFFSET 0x1000 ++#define WRT400N_CALDATA1_OFFSET 0x5000 ++ ++static struct mtd_partition wrt400n_partitions[] = { ++ { ++ .name = "uboot", ++ .offset = 0, ++ .size = 0x030000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "env", ++ .offset = 0x030000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "linux", ++ .offset = 0x040000, ++ .size = 0x140000, ++ }, { ++ .name = "rootfs", ++ .offset = 0x180000, ++ .size = 0x630000, ++ }, { ++ .name = "nvram", ++ .offset = 0x7b0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "factory", ++ .offset = 0x7c0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "language", ++ .offset = 0x7d0000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "caldata", ++ .offset = 0x7f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x040000, ++ .size = 0x770000, ++ } ++}; ++ ++static struct flash_platform_data wrt400n_flash_data = { ++ .parts = wrt400n_partitions, ++ .nr_parts = ARRAY_SIZE(wrt400n_partitions), ++}; ++ ++static struct gpio_led wrt400n_leds_gpio[] __initdata = { ++ { ++ .name = "wrt400n:blue:wps", ++ .gpio = WRT400N_GPIO_LED_WPS_BLUE, ++ .active_low = 1, ++ }, { ++ .name = "wrt400n:amber:wps", ++ .gpio = WRT400N_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "wrt400n:blue:wlan", ++ .gpio = WRT400N_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "wrt400n:blue:power", ++ .gpio = WRT400N_GPIO_LED_POWER, ++ .active_low = 0, ++ .default_trigger = "default-on", ++ } ++}; ++ ++static struct gpio_keys_button wrt400n_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WRT400N_KEYS_DEBOUNE_INTERVAL, ++ .gpio = WRT400N_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wlsec", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WRT400N_KEYS_DEBOUNE_INTERVAL, ++ .gpio = WRT400N_GPIO_BTN_WLSEC, ++ .active_low = 1, ++ } ++}; ++ ++static void __init wrt400n_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = art + WRT400N_MAC_ADDR_OFFSET; ++ ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 2); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_m25p80(&wrt400n_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wrt400n_leds_gpio), ++ wrt400n_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WRT400N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wrt400n_gpio_keys), ++ wrt400n_gpio_keys); ++ ++ ap94_pci_init(art + WRT400N_CALDATA0_OFFSET, NULL, ++ art + WRT400N_CALDATA1_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WRT400N, "WRT400N", "Linksys WRT400N", wrt400n_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wrtnode2q.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wrtnode2q.c +new file mode 100644 +index 0000000000..150a28b0d7 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wrtnode2q.c +@@ -0,0 +1,126 @@ ++/* ++ * WRTnode2Q board support ++ * ++ * Copyright (c) 2013 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012 Gabor Juhos ++ * Copyright (c) 2015 Kelei ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++#include "pci.h" ++ ++#define WRTNODE2Q_GPIO_LED_WLAN 12 ++#define WRTNODE2Q_GPIO_LED_WPS 13 ++#define WRTNODE2Q_GPIO_LED_STATUS 13 ++ ++#define WRTNODE2Q_GPIO_LED_WAN 4 ++#define WRTNODE2Q_GPIO_LED_LAN1 16 ++#define WRTNODE2Q_GPIO_LED_LAN2 15 ++#define WRTNODE2Q_GPIO_LED_LAN3 14 ++#define WRTNODE2Q_GPIO_LED_LAN4 11 ++ ++#define WRTNODE2Q_GPIO_BTN_WPS 17 ++ ++#define WRTNODE2Q_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WRTNODE2Q_KEYS_DEBOUNCE_INTERVAL (3 * WRTNODE2Q_KEYS_POLL_INTERVAL) ++ ++#define WRTNODE2Q_MAC0_OFFSET 0 ++#define WRTNODE2Q_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led wrtnode2q_leds_gpio[] __initdata = { ++ { ++ .name = "wrtnode2q:green:status", ++ .gpio = WRTNODE2Q_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "wrtnode2q:green:wlan", ++ .gpio = WRTNODE2Q_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wrtnode2q_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WRTNODE2Q_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WRTNODE2Q_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init wrtnode2q_gpio_led_setup(void) ++{ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wrtnode2q_leds_gpio), ++ wrtnode2q_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WRTNODE2Q_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wrtnode2q_gpio_keys), ++ wrtnode2q_gpio_keys); ++} ++ ++static void __init wrtnode2q_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f040000); ++ ++ ath79_register_m25p80(NULL); ++ ++ wrtnode2q_gpio_led_setup(); ++ ++ ath79_register_pci(); ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + WRTNODE2Q_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + WRTNODE2Q_MAC0_OFFSET, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + WRTNODE2Q_MAC0_OFFSET, 1); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WRTNODE2Q, "WRTNODE2Q", "WRTnode2Q board", ++ wrtnode2q_setup); +\ No newline at end of file +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-450hp2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-450hp2.c +new file mode 100644 +index 0000000000..ca45309487 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-450hp2.c +@@ -0,0 +1,221 @@ ++/* ++ * Buffalo WZR-450HP2 board support ++ * ++ * Copyright (c) 2013 Gabor Juhos ++ * ++ * Based on the Qualcomm Atheros AP135/AP136 reference board support code ++ * Copyright (c) 2012 Qualcomm Atheros ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WZR_450HP2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WZR_450HP2_KEYS_DEBOUNCE_INTERVAL (3 * WZR_450HP2_KEYS_POLL_INTERVAL) ++ ++#define WZR_450HP2_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct mtd_partition wzrhpg450h_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x0040000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "u-boot-env", ++ .offset = 0x0040000, ++ .size = 0x0010000, ++ }, { ++ .name = "ART", ++ .offset = 0x0ff0000, ++ .size = 0x0010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0050000, ++ .size = 0x0f90000, ++ }, { ++ .name = "user_property", ++ .offset = 0x0fe0000, ++ .size = 0x0010000, ++ } ++}; ++ ++static struct flash_platform_data wzr_450hp2_flash_data = { ++ .parts = wzrhpg450h_partitions, ++ .nr_parts = ARRAY_SIZE(wzrhpg450h_partitions), ++}; ++ ++static struct gpio_led wzr_450hp2_leds_gpio[] __initdata = { ++ { ++ .name = "buffalo:green:wps", ++ .gpio = 3, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:system", ++ .gpio = 20, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:wlan", ++ .gpio = 18, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wzr_450hp2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WZR_450HP2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 17, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = WZR_450HP2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 21, ++ .active_low = 1, ++ }, ++}; ++ ++static const struct ar8327_led_info wzr_450hp2_leds_ar8327[] = { ++ AR8327_LED_INFO(PHY0_0, HW, "buffalo:green:lan1"), ++ AR8327_LED_INFO(PHY1_0, HW, "buffalo:green:lan2"), ++ AR8327_LED_INFO(PHY2_0, HW, "buffalo:green:lan3"), ++ AR8327_LED_INFO(PHY3_0, HW, "buffalo:green:lan4"), ++ AR8327_LED_INFO(PHY4_0, HW, "buffalo:green:wan"), ++}; ++ ++/* GMAC0 of the AR8327 switch is connected to the QCA9558 SoC via SGMII */ ++static struct ar8327_pad_cfg wzr_450hp2_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++/* GMAC6 of the AR8327 switch is connected to the QCA9558 SoC via RGMII */ ++static struct ar8327_pad_cfg wzr_450hp2_ar8327_pad6_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_led_cfg wzr_450hp2_ar8327_led_cfg = { ++ .led_ctrl0 = 0xcc35cc35, ++ .led_ctrl1 = 0xca35ca35, ++ .led_ctrl2 = 0xc935c935, ++ .led_ctrl3 = 0x03ffff00, ++ .open_drain = true, ++}; ++ ++static struct ar8327_platform_data wzr_450hp2_ar8327_data = { ++ .pad0_cfg = &wzr_450hp2_ar8327_pad0_cfg, ++ .pad6_cfg = &wzr_450hp2_ar8327_pad6_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .port6_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++ .led_cfg = &wzr_450hp2_ar8327_led_cfg, ++ .num_leds = ARRAY_SIZE(wzr_450hp2_leds_ar8327), ++ .leds = wzr_450hp2_leds_ar8327, ++}; ++ ++static struct mdio_board_info wzr_450hp2_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = 0, ++ .platform_data = &wzr_450hp2_ar8327_data, ++ }, ++}; ++ ++static void __init wzr_450hp2_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac_wan = art; ++ u8 *mac_lan = mac_wan + ETH_ALEN; ++ ++ ath79_register_m25p80(&wzr_450hp2_flash_data); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wzr_450hp2_leds_gpio), ++ wzr_450hp2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WZR_450HP2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wzr_450hp2_gpio_keys), ++ wzr_450hp2_gpio_keys); ++ ++ ath79_register_wmac(art + WZR_450HP2_WMAC_CALDATA_OFFSET, mac_lan); ++ ++ mdiobus_register_board_info(wzr_450hp2_mdio0_info, ++ ARRAY_SIZE(wzr_450hp2_mdio0_info)); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++ /* GMAC0 is connected to the RMGII interface */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x56000000; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac_wan, 0); ++ ath79_register_eth(0); ++ ++ /* GMAC1 is connected to the SGMII interface */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_pll_data.pll_1000 = 0x03000101; ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac_lan, 0); ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WZR_450HP2, "WZR-450HP2", ++ "Buffalo WZR-450HP2", wzr_450hp2_setup); ++ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-ag300h.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-ag300h.c +new file mode 100644 +index 0000000000..a9ed3fdd46 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-ag300h.c +@@ -0,0 +1,202 @@ ++/* ++ * Buffalo WZR-HP-AG300H board support ++ * ++ * Copyright (C) 2011 Felix Fietkau ++ * ++ * 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 "dev-eth.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define WZRHPAG300H_MAC_OFFSET 0x20c ++#define WZRHPAG300H_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL (3 * WZRHPAG300H_KEYS_POLL_INTERVAL) ++ ++static struct mtd_partition wzrhpag300h_flash_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x0040000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "u-boot-env", ++ .offset = 0x0040000, ++ .size = 0x0010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "art", ++ .offset = 0x0050000, ++ .size = 0x0010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0060000, ++ .size = 0x1f90000, ++ }, { ++ .name = "user_property", ++ .offset = 0x1ff0000, ++ .size = 0x0010000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++ ++static struct flash_platform_data wzrhpag300h_flash_data = { ++ .parts = wzrhpag300h_flash_partitions, ++ .nr_parts = ARRAY_SIZE(wzrhpag300h_flash_partitions), ++}; ++ ++static struct gpio_led wzrhpag300h_leds_gpio[] __initdata = { ++ { ++ .name = "buffalo:red:diag", ++ .gpio = 1, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led wzrhpag300h_wmac0_leds_gpio[] = { ++ { ++ .name = "buffalo:amber:band2g", ++ .gpio = 1, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:usb", ++ .gpio = 3, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:band2g", ++ .gpio = 5, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led wzrhpag300h_wmac1_leds_gpio[] = { ++ { ++ .name = "buffalo:green:band5g", ++ .gpio = 1, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:router", ++ .gpio = 3, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:blue:movie_engine", ++ .gpio = 4, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:amber:band5g", ++ .gpio = 5, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wzrhpag300h_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 11, ++ .active_low = 1, ++ }, { ++ .desc = "usb", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 3, ++ .active_low = 1, ++ }, { ++ .desc = "aoss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 5, ++ .active_low = 1, ++ }, { ++ .desc = "router_auto", ++ .type = EV_SW, ++ .code = BTN_6, ++ .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 6, ++ .active_low = 1, ++ }, { ++ .desc = "router_off", ++ .type = EV_SW, ++ .code = BTN_5, ++ .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 7, ++ .active_low = 1, ++ }, { ++ .desc = "movie_engine", ++ .type = EV_SW, ++ .code = BTN_7, ++ .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 8, ++ .active_low = 1, ++ } ++}; ++ ++static void __init wzrhpag300h_setup(void) ++{ ++ u8 *eeprom1 = (u8 *) KSEG1ADDR(0x1f051000); ++ u8 *eeprom2 = (u8 *) KSEG1ADDR(0x1f055000); ++ u8 *mac1 = eeprom1 + WZRHPAG300H_MAC_OFFSET; ++ u8 *mac2 = eeprom2 + WZRHPAG300H_MAC_OFFSET; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 1); ++ ++ ath79_register_mdio(0, ~(BIT(0) | BIT(4))); ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = BIT(4); ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ gpio_request_one(2, GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wzrhpag300h_leds_gpio), ++ wzrhpag300h_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WZRHPAG300H_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wzrhpag300h_gpio_keys), ++ wzrhpag300h_gpio_keys); ++ ++ ath79_register_m25p80_multi(&wzrhpag300h_flash_data); ++ ++ ap94_pci_init(eeprom1, mac1, eeprom2, mac2); ++ ++ ap9x_pci_setup_wmac_leds(0, wzrhpag300h_wmac0_leds_gpio, ++ ARRAY_SIZE(wzrhpag300h_wmac0_leds_gpio)); ++ ap9x_pci_setup_wmac_leds(1, wzrhpag300h_wmac1_leds_gpio, ++ ARRAY_SIZE(wzrhpag300h_wmac1_leds_gpio)); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WZR_HP_AG300H, "WZR-HP-AG300H", ++ "Buffalo WZR-HP-AG300H/WZR-600DHP", wzrhpag300h_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh.c +new file mode 100644 +index 0000000000..0a3eba9f77 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh.c +@@ -0,0 +1,279 @@ ++/* ++ * Buffalo WZR-HP-G300NH board support ++ * ++ * Copyright (C) 2010-2012 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define WZRHPG300NH_GPIO_LED_USB 0 ++#define WZRHPG300NH_GPIO_LED_DIAG 1 ++#define WZRHPG300NH_GPIO_LED_WIRELESS 6 ++#define WZRHPG300NH_GPIO_LED_SECURITY 17 ++#define WZRHPG300NH_GPIO_LED_ROUTER 18 ++ ++#define WZRHPG300NH_GPIO_RTL8366_SDA 19 ++#define WZRHPG300NH_GPIO_RTL8366_SCK 20 ++ ++#define WZRHPG300NH_GPIO_74HC153_S0 9 ++#define WZRHPG300NH_GPIO_74HC153_S1 11 ++#define WZRHPG300NH_GPIO_74HC153_1Y 12 ++#define WZRHPG300NH_GPIO_74HC153_2Y 14 ++ ++#define WZRHPG300NH_GPIO_EXP_BASE 32 ++#define WZRHPG300NH_GPIO_BTN_AOSS (WZRHPG300NH_GPIO_EXP_BASE + 0) ++#define WZRHPG300NH_GPIO_BTN_RESET (WZRHPG300NH_GPIO_EXP_BASE + 1) ++#define WZRHPG300NH_GPIO_BTN_ROUTER_ON (WZRHPG300NH_GPIO_EXP_BASE + 2) ++#define WZRHPG300NH_GPIO_BTN_QOS_ON (WZRHPG300NH_GPIO_EXP_BASE + 3) ++#define WZRHPG300NH_GPIO_BTN_USB (WZRHPG300NH_GPIO_EXP_BASE + 5) ++#define WZRHPG300NH_GPIO_BTN_ROUTER_AUTO (WZRHPG300NH_GPIO_EXP_BASE + 6) ++#define WZRHPG300NH_GPIO_BTN_QOS_OFF (WZRHPG300NH_GPIO_EXP_BASE + 7) ++ ++#define WZRHPG300NH_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WZRHPG300NH_KEYS_DEBOUNCE_INTERVAL (3 * WZRHPG300NH_KEYS_POLL_INTERVAL) ++ ++#define WZRHPG300NH_MAC_OFFSET 0x20c ++ ++static struct mtd_partition wzrhpg300nh_flash_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x0040000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "u-boot-env", ++ .offset = 0x0040000, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0060000, ++ .size = 0x1f60000, ++ }, { ++ .name = "user_property", ++ .offset = 0x1fc0000, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "art", ++ .offset = 0x1fe0000, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++ ++static struct physmap_flash_data wzrhpg300nh_flash_data = { ++ .width = 2, ++ .parts = wzrhpg300nh_flash_partitions, ++ .nr_parts = ARRAY_SIZE(wzrhpg300nh_flash_partitions), ++}; ++ ++#define WZRHPG300NH_FLASH_BASE 0x1e000000 ++#define WZRHPG300NH_FLASH_SIZE (32 * 1024 * 1024) ++ ++static struct resource wzrhpg300nh_flash_resources[] = { ++ [0] = { ++ .start = WZRHPG300NH_FLASH_BASE, ++ .end = WZRHPG300NH_FLASH_BASE + WZRHPG300NH_FLASH_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device wzrhpg300nh_flash_device = { ++ .name = "physmap-flash", ++ .id = -1, ++ .resource = wzrhpg300nh_flash_resources, ++ .num_resources = ARRAY_SIZE(wzrhpg300nh_flash_resources), ++ .dev = { ++ .platform_data = &wzrhpg300nh_flash_data, ++ } ++}; ++ ++static struct gpio_led wzrhpg300nh_leds_gpio[] __initdata = { ++ { ++ .name = "buffalo:orange:security", ++ .gpio = WZRHPG300NH_GPIO_LED_SECURITY, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:wireless", ++ .gpio = WZRHPG300NH_GPIO_LED_WIRELESS, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:green:router", ++ .gpio = WZRHPG300NH_GPIO_LED_ROUTER, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:red:diag", ++ .gpio = WZRHPG300NH_GPIO_LED_DIAG, ++ .active_low = 1, ++ }, { ++ .name = "buffalo:blue:usb", ++ .gpio = WZRHPG300NH_GPIO_LED_USB, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_keys_button wzrhpg300nh_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WZRHPG300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WZRHPG300NH_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "aoss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WZRHPG300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WZRHPG300NH_GPIO_BTN_AOSS, ++ .active_low = 1, ++ }, { ++ .desc = "usb", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = WZRHPG300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WZRHPG300NH_GPIO_BTN_USB, ++ .active_low = 1, ++ }, { ++ .desc = "qos_on", ++ .type = EV_KEY, ++ .code = BTN_3, ++ .debounce_interval = WZRHPG300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WZRHPG300NH_GPIO_BTN_QOS_ON, ++ .active_low = 0, ++ }, { ++ .desc = "qos_off", ++ .type = EV_KEY, ++ .code = BTN_4, ++ .debounce_interval = WZRHPG300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WZRHPG300NH_GPIO_BTN_QOS_OFF, ++ .active_low = 0, ++ }, { ++ .desc = "router_on", ++ .type = EV_KEY, ++ .code = BTN_5, ++ .debounce_interval = WZRHPG300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WZRHPG300NH_GPIO_BTN_ROUTER_ON, ++ .active_low = 0, ++ }, { ++ .desc = "router_auto", ++ .type = EV_KEY, ++ .code = BTN_6, ++ .debounce_interval = WZRHPG300NH_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = WZRHPG300NH_GPIO_BTN_ROUTER_AUTO, ++ .active_low = 0, ++ } ++}; ++ ++static struct nxp_74hc153_platform_data wzrhpg300nh_74hc153_data = { ++ .gpio_base = WZRHPG300NH_GPIO_EXP_BASE, ++ .gpio_pin_s0 = WZRHPG300NH_GPIO_74HC153_S0, ++ .gpio_pin_s1 = WZRHPG300NH_GPIO_74HC153_S1, ++ .gpio_pin_1y = WZRHPG300NH_GPIO_74HC153_1Y, ++ .gpio_pin_2y = WZRHPG300NH_GPIO_74HC153_2Y, ++}; ++ ++static struct platform_device wzrhpg300nh_74hc153_device = { ++ .name = NXP_74HC153_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &wzrhpg300nh_74hc153_data, ++ } ++}; ++ ++static struct rtl8366_platform_data wzrhpg300nh_rtl8366_data = { ++ .gpio_sda = WZRHPG300NH_GPIO_RTL8366_SDA, ++ .gpio_sck = WZRHPG300NH_GPIO_RTL8366_SCK, ++}; ++ ++static struct platform_device wzrhpg300nh_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &wzrhpg300nh_rtl8366_data, ++ } ++}; ++ ++static struct platform_device wzrhpg300nh_rtl8366rb_device = { ++ .name = RTL8366RB_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &wzrhpg300nh_rtl8366_data, ++ } ++}; ++ ++static void __init wzrhpg300nh_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 *mac = eeprom + WZRHPG300NH_MAC_OFFSET; ++ bool hasrtl8366rb = false; ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ if (rtl8366_smi_detect(&wzrhpg300nh_rtl8366_data) == RTL8366_TYPE_RB) ++ hasrtl8366rb = true; ++ ++ if (hasrtl8366rb) { ++ ath79_eth0_pll_data.pll_1000 = 0x1f000000; ++ ath79_eth0_data.mii_bus_dev = &wzrhpg300nh_rtl8366rb_device.dev; ++ ath79_eth1_pll_data.pll_1000 = 0x100; ++ ath79_eth1_data.mii_bus_dev = &wzrhpg300nh_rtl8366rb_device.dev; ++ } else { ++ ath79_eth0_pll_data.pll_1000 = 0x1e000100; ++ ath79_eth0_data.mii_bus_dev = &wzrhpg300nh_rtl8366s_device.dev; ++ ath79_eth1_pll_data.pll_1000 = 0x1e000100; ++ ath79_eth1_data.mii_bus_dev = &wzrhpg300nh_rtl8366s_device.dev; ++ } ++ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth1_data.phy_mask = 0x10; ++ ++ ath79_register_eth(0); ++ ath79_register_eth(1); ++ ++ ath79_register_usb(); ++ ath79_register_wmac(eeprom, NULL); ++ ++ platform_device_register(&wzrhpg300nh_74hc153_device); ++ platform_device_register(&wzrhpg300nh_flash_device); ++ ++ if (hasrtl8366rb) ++ platform_device_register(&wzrhpg300nh_rtl8366rb_device); ++ else ++ platform_device_register(&wzrhpg300nh_rtl8366s_device); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wzrhpg300nh_leds_gpio), ++ wzrhpg300nh_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WZRHPG300NH_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wzrhpg300nh_gpio_keys), ++ wzrhpg300nh_gpio_keys); ++ ++} ++ ++MIPS_MACHINE(ATH79_MACH_WZR_HP_G300NH, "WZR-HP-G300NH", ++ "Buffalo WZR-HP-G300NH", wzrhpg300nh_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh2.c +new file mode 100644 +index 0000000000..c44a9cf770 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g300nh2.c +@@ -0,0 +1,174 @@ ++/* ++ * Buffalo WZR-HP-G300NH2 board support ++ * ++ * Copyright (C) 2011 Felix Fietkau ++ * Copyright (C) 2011 Mark Deneen ++ * ++ * 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 "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define WZRHPG300NH2_MAC_OFFSET 0x20c ++#define WZRHPG300NH2_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WZRHPG300NH2_KEYS_DEBOUNCE_INTERVAL (3 * WZRHPG300NH2_KEYS_POLL_INTERVAL) ++ ++static struct mtd_partition wzrhpg300nh2_flash_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x0040000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "u-boot-env", ++ .offset = 0x0040000, ++ .size = 0x0010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "art", ++ .offset = 0x0050000, ++ .size = 0x0010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0060000, ++ .size = 0x1f90000, ++ }, { ++ .name = "user_property", ++ .offset = 0x1ff0000, ++ .size = 0x0010000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++ ++static struct flash_platform_data wzrhpg300nh2_flash_data = { ++ .parts = wzrhpg300nh2_flash_partitions, ++ .nr_parts = ARRAY_SIZE(wzrhpg300nh2_flash_partitions), ++}; ++ ++static struct gpio_led wzrhpg300nh2_leds_gpio[] __initdata = { ++ { ++ .name = "buffalo:red:diag", ++ .gpio = 16, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_led wzrhpg300nh2_wmac_leds_gpio[] = { ++ { ++ .name = "buffalo:blue:usb", ++ .gpio = 4, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:wireless", ++ .gpio = 5, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:orange:security", ++ .gpio = 6, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:router", ++ .gpio = 7, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:blue:movie_engine_on", ++ .gpio = 8, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:blue:movie_engine_off", ++ .gpio = 9, ++ .active_low = 1, ++ }, ++}; ++ ++/* The AOSS button is wmac gpio 12 */ ++static struct gpio_keys_button wzrhpg300nh2_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WZRHPG300NH2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 1, ++ .active_low = 1, ++ }, { ++ .desc = "usb", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = WZRHPG300NH2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 7, ++ .active_low = 1, ++ }, { ++ .desc = "qos", ++ .type = EV_KEY, ++ .code = BTN_3, ++ .debounce_interval = WZRHPG300NH2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 11, ++ .active_low = 0, ++ }, { ++ .desc = "router_on", ++ .type = EV_KEY, ++ .code = BTN_5, ++ .debounce_interval = WZRHPG300NH2_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 8, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init wzrhpg300nh2_setup(void) ++{ ++ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1f051000); ++ u8 *mac0 = eeprom + WZRHPG300NH2_MAC_OFFSET; ++ /* There is an eth1 but it is not connected to the switch */ ++ ++ ath79_register_m25p80_multi(&wzrhpg300nh2_flash_data); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac0, 0); ++ ath79_register_mdio(0, ~(BIT(0))); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac0, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ ath79_register_eth(0); ++ ++ /* gpio13 is usb power. Turn it on. */ ++ gpio_request_one(13, GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wzrhpg300nh2_leds_gpio), ++ wzrhpg300nh2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, WZRHPG300NH2_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wzrhpg300nh2_gpio_keys), ++ wzrhpg300nh2_gpio_keys); ++ ap9x_pci_setup_wmac_leds(0, wzrhpg300nh2_wmac_leds_gpio, ++ ARRAY_SIZE(wzrhpg300nh2_wmac_leds_gpio)); ++ ++ ap91_pci_init(eeprom, mac0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WZR_HP_G300NH2, "WZR-HP-G300NH2", ++ "Buffalo WZR-HP-G300NH2", wzrhpg300nh2_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g450h.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g450h.c +new file mode 100644 +index 0000000000..5d235c49f4 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-wzr-hp-g450h.c +@@ -0,0 +1,169 @@ ++/* ++ * Buffalo WZR-HP-G450G board support ++ * ++ * Copyright (C) 2011 Felix Fietkau ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++#include "machtypes.h" ++ ++#define WZRHPG450H_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define WZRHPG450H_KEYS_DEBOUNCE_INTERVAL (3 * WZRHPG450H_KEYS_POLL_INTERVAL) ++ ++static struct mtd_partition wzrhpg450h_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x0040000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "u-boot-env", ++ .offset = 0x0040000, ++ .size = 0x0010000, ++ }, { ++ .name = "ART", ++ .offset = 0x0050000, ++ .size = 0x0010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0060000, ++ .size = 0x1f80000, ++ }, { ++ .name = "user_property", ++ .offset = 0x1fe0000, ++ .size = 0x0020000, ++ } ++}; ++ ++static struct flash_platform_data wzrhpg450h_flash_data = { ++ .parts = wzrhpg450h_partitions, ++ .nr_parts = ARRAY_SIZE(wzrhpg450h_partitions), ++}; ++ ++static struct gpio_led wzrhpg450h_leds_gpio[] __initdata = { ++ { ++ .name = "buffalo:red:diag", ++ .gpio = 14, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:orange:security", ++ .gpio = 13, ++ .active_low = 1, ++ }, ++}; ++ ++ ++static struct gpio_led wzrhpg450h_wmac_leds_gpio[] = { ++ { ++ .name = "buffalo:blue:movie_engine", ++ .gpio = 13, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:router", ++ .gpio = 14, ++ .active_low = 1, ++ }, ++ { ++ .name = "buffalo:green:wireless", ++ .gpio = 15, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button wzrhpg450h_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = WZRHPG450H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 6, ++ .active_low = 1, ++ }, { ++ .desc = "usb", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .debounce_interval = WZRHPG450H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 1, ++ .active_low = 1, ++ }, { ++ .desc = "aoss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = WZRHPG450H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 8, ++ .active_low = 1, ++ }, { ++ .desc = "movie_engine", ++ .type = EV_KEY, ++ .code = BTN_6, ++ .debounce_interval = WZRHPG450H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 7, ++ .active_low = 0, ++ }, { ++ .desc = "router_off", ++ .type = EV_KEY, ++ .code = BTN_5, ++ .debounce_interval = WZRHPG450H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = 12, ++ .active_low = 0, ++ } ++}; ++ ++ ++static void __init wzrhpg450h_init(void) ++{ ++ u8 *ee = (u8 *) KSEG1ADDR(0x1f051000); ++ u8 *mac = (u8 *) ee + 2; ++ ++ ath79_register_m25p80_multi(&wzrhpg450h_flash_data); ++ ++ ath79_register_mdio(0, ~BIT(0)); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(wzrhpg450h_leds_gpio), ++ wzrhpg450h_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, WZRHPG450H_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(wzrhpg450h_gpio_keys), ++ wzrhpg450h_gpio_keys); ++ ++ ath79_register_eth(0); ++ ++ gpio_request_one(16, GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ath79_register_usb(); ++ ++ ap91_pci_init(ee, NULL); ++ ap9x_pci_get_wmac_data(0)->tx_gain_buffalo = true; ++ ap9x_pci_get_wmac_data(1)->tx_gain_buffalo = true; ++ ap9x_pci_setup_wmac_leds(0, wzrhpg450h_wmac_leds_gpio, ++ ARRAY_SIZE(wzrhpg450h_wmac_leds_gpio)); ++} ++ ++MIPS_MACHINE(ATH79_MACH_WZR_HP_G450H, "WZR-HP-G450H", "Buffalo WZR-HP-G450H", ++ wzrhpg450h_init); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-z1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-z1.c +new file mode 100644 +index 0000000000..912e9b2a6f +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-z1.c +@@ -0,0 +1,164 @@ ++/* ++ * Cisco Meraki Z1 board support ++ * ++ * Copyright (C) 2016 Chris Blake ++ * Copyright (C) 2016 Christian Lamparter ++ * ++ * Based on Cisco Meraki GPL Release r23-20150601 Z1 Device Config ++ * ++ * 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 ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-nfc.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "dev-ap9x-pci.h" ++#include "machtypes.h" ++ ++#define Z1_GPIO_LED_POWER_ORANGE 17 ++ ++#define Z1_GPIO_NU801_CKI 14 ++#define Z1_GPIO_NU801_SDI 15 ++ ++#define Z1_GPIO_XLNA0 18 ++#define Z1_GPIO_XLNA1 19 ++ ++#define Z1_GPIO_BTN_RESET 12 ++#define Z1_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define Z1_KEYS_DEBOUNCE_INTERVAL (3 * Z1_KEYS_POLL_INTERVAL) ++ ++#define Z1_ETH_SWITCH_PHY 0 ++ ++static struct gpio_led Z1_leds_gpio[] __initdata = { ++ { ++ .name = "z1:orange:power", ++ .gpio = Z1_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button Z1_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = Z1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = Z1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct led_nu801_template tricolor_led_template = { ++ .device_name = "z1", ++ .name = "tricolor", ++ .num_leds = 1, ++ .cki = Z1_GPIO_NU801_CKI, ++ .sdi = Z1_GPIO_NU801_SDI, ++ .lei = -1, ++ .ndelay = 500, ++ .init_brightness = { ++ LED_OFF, ++ LED_OFF, ++ LED_OFF, ++ }, ++ .default_trigger = "none", ++}; ++ ++static struct led_nu801_platform_data tricolor_led_data = { ++ .num_controllers = 1, ++ .template = &tricolor_led_template, ++}; ++ ++static struct platform_device tricolor_leds = { ++ .name = "leds-nu801", ++ .id = -1, ++ .dev.platform_data = &tricolor_led_data, ++}; ++ ++static struct ar8327_pad_cfg z1_ar8327_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_RGMII, ++ .txclk_delay_en = true, ++ .rxclk_delay_en = true, ++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, ++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++}; ++ ++static struct ar8327_platform_data z1_ar8327_data = { ++ .pad0_cfg = &z1_ar8327_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info z1_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .mdio_addr = Z1_ETH_SWITCH_PHY, ++ .platform_data = &z1_ar8327_data, ++ }, ++}; ++ ++static void __init z1_setup(void) ++{ ++ /* NAND */ ++ ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_SOFT_BCH); ++ ath79_register_nfc(); ++ ++ /* Eth Config */ ++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | ++ AR934X_ETH_CFG_SW_ONLY_MODE); ++ ++ /* MDIO Interface */ ++ ath79_register_mdio(1, 0x0); ++ ath79_register_mdio(0, 0x0); ++ mdiobus_register_board_info(z1_mdio0_info, ++ ARRAY_SIZE(z1_mdio0_info)); ++ ++ /* GMAC0 is connected to an AR8327 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ath79_eth0_data.phy_mask = BIT(Z1_ETH_SWITCH_PHY); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_eth0_pll_data.pll_1000 = 0x06000000; ++ ath79_register_eth(0); ++ ++ /* XLNA */ ++ ath79_wmac_set_ext_lna_gpio(0, Z1_GPIO_XLNA0); ++ ath79_wmac_set_ext_lna_gpio(1, Z1_GPIO_XLNA1); ++ ++ /* LEDs and Buttons */ ++ platform_device_register(&tricolor_leds); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(Z1_leds_gpio), ++ Z1_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, Z1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(Z1_gpio_keys), ++ Z1_gpio_keys); ++ ++ /* USB */ ++ ath79_register_usb(); ++ ++ /* Wireless */ ++ ath79_register_wmac_simple(); ++ ap91_pci_init_simple(); ++} ++MIPS_MACHINE(ATH79_MACH_Z1, "Z1", "Meraki Z1", z1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-zbt-we1526.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-zbt-we1526.c +new file mode 100644 +index 0000000000..42bad11905 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-zbt-we1526.c +@@ -0,0 +1,153 @@ ++/* ++ * Zbtlink ZBT-WE1526 board support ++ * ++ * Copyright (C) 2016 Piotr Dymacz ++ * ++ * Based on mach-dr531.c and mach-tl-wr841n-v9.c ++ * ++ * 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 "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define ZBT_WE1526_GPIO_LED_STATUS 13 ++#define ZBT_WE1526_GPIO_LED_LAN1 16 ++#define ZBT_WE1526_GPIO_LED_LAN2 15 ++#define ZBT_WE1526_GPIO_LED_LAN3 14 ++#define ZBT_WE1526_GPIO_LED_LAN4 11 ++#define ZBT_WE1526_GPIO_LED_WAN 4 ++#define ZBT_WE1526_GPIO_LED_WLAN 12 ++ ++#define ZBT_WE1526_GPIO_BTN_RESET 17 ++ ++#define ZBT_WE1526_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ZBT_WE1526_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * ZBT_WE1526_KEYS_POLL_INTERVAL) ++ ++#define ZBT_WE1526_MAC0_OFFSET 0x0 ++#define ZBT_WE1526_MAC1_OFFSET 0x6 ++#define ZBT_WE1526_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct gpio_led zbt_we1526_leds_gpio[] __initdata = { ++ { ++ .name = "zbt-we1526:green:status", ++ .gpio = ZBT_WE1526_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, ++ { ++ .name = "zbt-we1526:green:lan1", ++ .gpio = ZBT_WE1526_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, ++ { ++ .name = "zbt-we1526:green:lan2", ++ .gpio = ZBT_WE1526_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "zbt-we1526:green:lan3", ++ .gpio = ZBT_WE1526_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, ++ { ++ .name = "zbt-we1526:green:lan4", ++ .gpio = ZBT_WE1526_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, ++ { ++ .name = "zbt-we1526:green:wan", ++ .gpio = ZBT_WE1526_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "zbt-we1526:green:wlan", ++ .gpio = ZBT_WE1526_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button zbt_we1526_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ZBT_WE1526_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ZBT_WE1526_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init zbt_we1526_gpio_setup(void) ++{ ++ /* For LED on GPIO4 */ ++ ath79_gpio_function_disable(AR934X_GPIO_FUNC_CLK_OBS4_EN); ++ ath79_gpio_output_select(ZBT_WE1526_GPIO_LED_WAN, 0); ++ ++ ath79_gpio_direction_select(ZBT_WE1526_GPIO_LED_STATUS, true); ++ ath79_gpio_direction_select(ZBT_WE1526_GPIO_LED_LAN1, true); ++ ath79_gpio_direction_select(ZBT_WE1526_GPIO_LED_LAN2, true); ++ ath79_gpio_direction_select(ZBT_WE1526_GPIO_LED_LAN3, true); ++ ath79_gpio_direction_select(ZBT_WE1526_GPIO_LED_LAN4, true); ++ ath79_gpio_direction_select(ZBT_WE1526_GPIO_LED_WAN, true); ++ ath79_gpio_direction_select(ZBT_WE1526_GPIO_LED_WLAN, true); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(zbt_we1526_leds_gpio), ++ zbt_we1526_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ZBT_WE1526_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(zbt_we1526_gpio_keys), ++ zbt_we1526_gpio_keys); ++} ++ ++static void __init zbt_we1526_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ zbt_we1526_gpio_setup(); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_init_mac(ath79_eth1_data.mac_addr, ++ art + ZBT_WE1526_MAC0_OFFSET, 0); ++ ath79_register_eth(1); ++ ++ /* WAN */ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, ++ art + ZBT_WE1526_MAC1_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ ath79_register_wmac(art + ZBT_WE1526_WMAC_CALDATA_OFFSET, NULL); ++ ++ ath79_register_usb(); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ZBT_WE1526, "ZBT-WE1526", "Zbtlink ZBT-WE1526", ++ zbt_we1526_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-zcn-1523h.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-zcn-1523h.c +new file mode 100644 +index 0000000000..bc79ab9953 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-zcn-1523h.c +@@ -0,0 +1,154 @@ ++/* ++ * Zcomax ZCN-1523H-2-8/5-16 board support ++ * ++ * Copyright (C) 2010-2012 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. ++ */ ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-m25p80.h" ++#include "dev-ap9x-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "machtypes.h" ++ ++#define ZCN_1523H_GPIO_BTN_RESET 0 ++#define ZCN_1523H_GPIO_LED_INIT 11 ++#define ZCN_1523H_GPIO_LED_LAN1 17 ++ ++#define ZCN_1523H_2_GPIO_LED_WEAK 13 ++#define ZCN_1523H_2_GPIO_LED_MEDIUM 14 ++#define ZCN_1523H_2_GPIO_LED_STRONG 15 ++ ++#define ZCN_1523H_5_GPIO_LAN2_POWER 1 ++#define ZCN_1523H_5_GPIO_LED_LAN2 13 ++#define ZCN_1523H_5_GPIO_LED_WEAK 14 ++#define ZCN_1523H_5_GPIO_LED_MEDIUM 15 ++#define ZCN_1523H_5_GPIO_LED_STRONG 16 ++ ++#define ZCN_1523H_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ZCN_1523H_KEYS_DEBOUNCE_INTERVAL (3 * ZCN_1523H_KEYS_POLL_INTERVAL) ++ ++static struct gpio_keys_button zcn_1523h_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ZCN_1523H_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ZCN_1523H_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led zcn_1523h_leds_gpio[] __initdata = { ++ { ++ .name = "zcn-1523h:amber:init", ++ .gpio = ZCN_1523H_GPIO_LED_INIT, ++ .active_low = 1, ++ }, { ++ .name = "zcn-1523h:green:lan1", ++ .gpio = ZCN_1523H_GPIO_LED_LAN1, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led zcn_1523h_2_leds_gpio[] __initdata = { ++ { ++ .name = "zcn-1523h:red:weak", ++ .gpio = ZCN_1523H_2_GPIO_LED_WEAK, ++ .active_low = 1, ++ }, { ++ .name = "zcn-1523h:amber:medium", ++ .gpio = ZCN_1523H_2_GPIO_LED_MEDIUM, ++ .active_low = 1, ++ }, { ++ .name = "zcn-1523h:green:strong", ++ .gpio = ZCN_1523H_2_GPIO_LED_STRONG, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_led zcn_1523h_5_leds_gpio[] __initdata = { ++ { ++ .name = "zcn-1523h:red:weak", ++ .gpio = ZCN_1523H_5_GPIO_LED_WEAK, ++ .active_low = 1, ++ }, { ++ .name = "zcn-1523h:amber:medium", ++ .gpio = ZCN_1523H_5_GPIO_LED_MEDIUM, ++ .active_low = 1, ++ }, { ++ .name = "zcn-1523h:green:strong", ++ .gpio = ZCN_1523H_5_GPIO_LED_STRONG, ++ .active_low = 1, ++ }, { ++ .name = "zcn-1523h:green:lan2", ++ .gpio = ZCN_1523H_5_GPIO_LED_LAN2, ++ .active_low = 1, ++ } ++}; ++ ++static void __init zcn_1523h_generic_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f7e0004); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(0, ARRAY_SIZE(zcn_1523h_leds_gpio), ++ zcn_1523h_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ZCN_1523H_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(zcn_1523h_gpio_keys), ++ zcn_1523h_gpio_keys); ++ ++ ap91_pci_init(ee, mac); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* LAN1 port */ ++ ath79_register_eth(0); ++} ++ ++static void __init zcn_1523h_2_setup(void) ++{ ++ zcn_1523h_generic_setup(); ++ ap9x_pci_setup_wmac_gpio(0, BIT(9), 0); ++ ++ ath79_register_leds_gpio(1, ARRAY_SIZE(zcn_1523h_2_leds_gpio), ++ zcn_1523h_2_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ZCN_1523H_2, "ZCN-1523H-2", "Zcomax ZCN-1523H-2", ++ zcn_1523h_2_setup); ++ ++static void __init zcn_1523h_5_setup(void) ++{ ++ zcn_1523h_generic_setup(); ++ ap9x_pci_setup_wmac_gpio(0, BIT(8), 0); ++ ++ ath79_register_leds_gpio(1, ARRAY_SIZE(zcn_1523h_5_leds_gpio), ++ zcn_1523h_5_leds_gpio); ++ ++ /* LAN2 port */ ++ ath79_register_eth(1); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ZCN_1523H_5, "ZCN-1523H-5", "Zcomax ZCN-1523H-5", ++ zcn_1523h_5_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +new file mode 100644 +index 0000000000..900b4ec87b +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -0,0 +1,387 @@ ++/* ++ * Atheros AR71XX/AR724X/AR913X machine type definitions ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 _ATH79_MACHTYPE_H ++#define _ATH79_MACHTYPE_H ++ ++#include ++ ++enum ath79_mach_type { ++ ATH79_MACH_GENERIC_OF = -1, /* Device tree board */ ++ ATH79_MACH_GENERIC = 0, ++ ATH79_MACH_A40, /* OpenMesh A40 */ ++ ATH79_MACH_A60, /* OpenMesh A60 */ ++ ATH79_MACH_WI2A_AC200I, /* Nokia WI2A-AC200i */ ++ ATH79_MACH_ALFA_AP120C, /* ALFA Network AP120C board */ ++ ATH79_MACH_ALFA_AP96, /* ALFA Network AP96 board */ ++ ATH79_MACH_ALFA_NX, /* ALFA Network N2/N5 board */ ++ ATH79_MACH_ALL0258N, /* Allnet ALL0258N */ ++ ATH79_MACH_ALL0305, /* Allnet ALL0305 */ ++ ATH79_MACH_ALL0315N, /* Allnet ALL0315N */ ++ ATH79_MACH_ANTMINER_S1, /* Antminer S1 */ ++ ATH79_MACH_ANTMINER_S3, /* Antminer S3 */ ++ ATH79_MACH_ANTROUTER_R1, /* Antrouter R1 */ ++ ATH79_MACH_AP121, /* Atheros AP121 reference board */ ++ ATH79_MACH_AP121_MINI, /* Atheros AP121-MINI reference board */ ++ ATH79_MACH_AP121F, /* ALFA Network AP121F */ ++ ATH79_MACH_AP132, /* Atheros AP132 reference board */ ++ ATH79_MACH_AP135_020, /* Atheros AP135-020 reference board */ ++ ATH79_MACH_AP136_010, /* Atheros AP136-010 reference board */ ++ ATH79_MACH_AP136_020, /* Atheros AP136-020 reference board */ ++ ATH79_MACH_AP143, /* Atheros AP143 reference board */ ++ ATH79_MACH_AP147_010, /* Atheros AP147-010 reference board */ ++ ATH79_MACH_AP152, /* Atheros AP152 reference board */ ++ ATH79_MACH_AP531B0, /* Rockeetech AP531B0 */ ++ ATH79_MACH_AP90Q, /* YunCore AP80Q/AP90Q */ ++ ATH79_MACH_AP91_5G, /* ALFA Network AP91-5G */ ++ ATH79_MACH_AP96, /* Atheros AP96 */ ++ ATH79_MACH_ARCHER_C25_V1, /* TP-LINK Archer C25 V1 board */ ++ ATH79_MACH_ARCHER_C5, /* TP-LINK Archer C5 board */ ++ ATH79_MACH_ARCHER_C58_V1, /* TP-LINK Archer C58 V1 board */ ++ ATH79_MACH_ARCHER_C59_V1, /* TP-LINK Archer C59 V1 board */ ++ ATH79_MACH_ARCHER_C59_V2, /* TP-LINK Archer C59 V2 board */ ++ ATH79_MACH_ARCHER_C60_V1, /* TP-LINK Archer C60 V1 board */ ++ ATH79_MACH_ARCHER_C60_V2, /* TP-LINK Archer C60 V2 board */ ++ ATH79_MACH_ARCHER_C7, /* TP-LINK Archer C7 board */ ++ ATH79_MACH_ARCHER_C7_V2, /* TP-LINK Archer C7 V2 board */ ++ ATH79_MACH_ARCHER_C7_V4, /* TP-LINK Archer C7 V4 board */ ++ ATH79_MACH_ARCHER_C7_V5, /* TP-LINK Archer C7 V5 board */ ++ ATH79_MACH_ARDUINO_YUN, /* Yun */ ++ ATH79_MACH_AW_NR580, /* AzureWave AW-NR580 */ ++ ATH79_MACH_BHR_4GRV2, /* Buffalo BHR-4GRV2 */ ++ ATH79_MACH_BHU_BXU2000N2_A1, /* BHU BXU2000n-2 A1 */ ++ ATH79_MACH_BSB, /* Smart Electronics Black Swift board */ ++ ATH79_MACH_C55, /* AirTight Networks C-55 */ ++ ATH79_MACH_C60, /* AirTight Networks C-60 */ ++ ATH79_MACH_CAP324, /* PowerCloud Systems CAP324 */ ++ ATH79_MACH_CAP4200AG, /* Senao CAP4200AG */ ++ ATH79_MACH_CARAMBOLA2, /* 8devices Carambola2 */ ++ ATH79_MACH_CF_E316N_V2, /* COMFAST CF-E316N v2 */ ++ ATH79_MACH_CF_E320N_V2, /* COMFAST CF-E320N v2 */ ++ ATH79_MACH_CF_E355AC, /* COMFAST CF-E355AC */ ++ ATH79_MACH_CF_E355AC_V2, /* COMFAST CF-E355AC v2*/ ++ ATH79_MACH_CF_E375AC, /* COMFAST CF-E375AC */ ++ ATH79_MACH_CF_E380AC_V1, /* COMFAST CF-E380AC v1 */ ++ ATH79_MACH_CF_E380AC_V2, /* COMFAST CF-E380AC v2 */ ++ ATH79_MACH_CF_E385AC, /* COMFAST CF-E385AC */ ++ ATH79_MACH_CF_E520N, /* COMFAST CF-E520N */ ++ ATH79_MACH_CF_E530N, /* COMFAST CF-E530N */ ++ ATH79_MACH_CPE210, /* TP-LINK CPE210 v1 */ ++ ATH79_MACH_CPE210_V2, /* TP-LINK CPE210 v2 */ ++ ATH79_MACH_CPE210_V3, /* TP-LINK CPE210 v3 */ ++ ATH79_MACH_CPE505N, /* P&W CPE505N */ ++ ATH79_MACH_CPE510, /* TP-LINK CPE510 */ ++ ATH79_MACH_CPE510_V2, /* TP-LINK CPE510 v2 */ ++ ATH79_MACH_CPE830, /* YunCore CPE830 */ ++ ATH79_MACH_CPE870, /* YunCore CPE870 */ ++ ATH79_MACH_CR3000, /* PowerCloud Systems CR3000 */ ++ ATH79_MACH_CR5000, /* PowerCloud Systems CR5000 */ ++ ATH79_MACH_DAP_1330_A1, /* D-Link DAP-1330 rev. A1 */ ++ ATH79_MACH_DAP_2695_A1, /* D-Link DAP-2695 rev. A1 */ ++ ATH79_MACH_DB120, /* Atheros DB120 reference board */ ++ ATH79_MACH_DGL_5500_A1, /* D-link DGL-5500 rev. A1 */ ++ ATH79_MACH_DHP_1565_A1, /* D-Link DHP-1565 rev. A1 */ ++ ATH79_MACH_DIR_505_A1, /* D-Link DIR-505 rev. A1 */ ++ ATH79_MACH_DIR_600_A1, /* D-Link DIR-600 rev. A1 */ ++ ATH79_MACH_DIR_615_C1, /* D-Link DIR-615 rev. C1 */ ++ ATH79_MACH_DIR_615_E1, /* D-Link DIR-615 rev. E1 */ ++ ATH79_MACH_DIR_615_E4, /* D-Link DIR-615 rev. E4 */ ++ ATH79_MACH_DIR_615_I1, /* D-Link DIR-615 rev. I1 */ ++ ATH79_MACH_DIR_825_B1, /* D-Link DIR-825 rev. B1 */ ++ ATH79_MACH_DIR_825_C1, /* D-Link DIR-825 rev. C1 */ ++ ATH79_MACH_DIR_835_A1, /* D-Link DIR-835 rev. A1 */ ++ ATH79_MACH_DIR_869_A1, /* D-Link DIR-869 rev. A1 */ ++ ATH79_MACH_DLAN_HOTSPOT, /* devolo dLAN Hotspot */ ++ ATH79_MACH_DLAN_PRO_1200_AC, /* devolo dLAN pro 1200+ WiFi ac*/ ++ ATH79_MACH_DLAN_PRO_500_WP, /* devolo dLAN pro 500 Wireless+ */ ++ ATH79_MACH_DOMYWIFI_DW33D, /* DomyWifi DW33D */ ++ ATH79_MACH_DR342, /* Wallys DR342 */ ++ ATH79_MACH_DR344, /* Wallys DR344 */ ++ ATH79_MACH_DR531, /* Wallys DR531 */ ++ ATH79_MACH_DRAGINO2, /* Dragino Version 2 */ ++ ATH79_MACH_E1700AC_V2, /* Qxwlan E1700AC v2 */ ++ ATH79_MACH_E558_V2, /* Qxwlan E558 v2 */ ++ ATH79_MACH_E600G_V2, /* Qxwlan E600G v2 */ ++ ATH79_MACH_E600GAC_V2, /* Qxwlan E600GAC v2 */ ++ ATH79_MACH_E750A_V4, /* Qxwlan E750A v4 */ ++ ATH79_MACH_E750G_V8, /* Qxwlan E750G v8 */ ++ ATH79_MACH_EAP120, /* TP-LINK EAP120 */ ++ ATH79_MACH_EAP300V2, /* EnGenius EAP300 v2 */ ++ ATH79_MACH_EAP7660D, /* Senao EAP7660D */ ++ ATH79_MACH_EBR_2310_C1, /* D-link EBR-2310 rev. C1 */ ++ ATH79_MACH_EL_M150, /* EasyLink EL-M150 */ ++ ATH79_MACH_EL_MINI, /* EasyLink EL-MINI */ ++ ATH79_MACH_ENS202EXT, /* EnGenius ENS202EXT */ ++ ATH79_MACH_EPG5000, /* EnGenius EPG5000 */ ++ ATH79_MACH_ESR1750, /* EnGenius ESR1750 */ ++ ATH79_MACH_ESR900, /* EnGenius ESR900 */ ++ ATH79_MACH_EW_BALIN, /* embedded wireless Balin Platform */ ++ ATH79_MACH_EW_DORIN, /* embedded wireless Dorin Platform */ ++ ATH79_MACH_EW_DORIN_ROUTER, /* embedded wireless Dorin Router Platform */ ++ ATH79_MACH_F9K1115V2, /* Belkin AC1750DB */ ++ ATH79_MACH_FRITZ300E, /* AVM FRITZ!WLAN Repeater 300E */ ++ ATH79_MACH_FRITZ4020, /* AVM FRITZ!Box 4020 */ ++ ATH79_MACH_FRITZ450E, /* AVM FRITZ!WLAN Repeater 450E */ ++ ATH79_MACH_GL_AR150, /* GL-AR150 support */ ++ ATH79_MACH_GL_AR300, /* GL-AR300 */ ++ ATH79_MACH_GL_AR300M, /* GL-AR300M */ ++ ATH79_MACH_GL_AR750, /* GL.iNet GL-AR750 */ ++ ATH79_MACH_GL_AR750S, /* GL.iNet GL-AR750S */ ++ ATH79_MACH_GL_DOMINO, /* Domino */ ++ ATH79_MACH_GL_INET, /* GL-CONNECT GL-INET */ ++ ATH79_MACH_GL_MIFI, /* GL-MIFI support */ ++ ATH79_MACH_GL_USB150, /* GL.iNet GL-USB150 */ ++ ATH79_MACH_GS_MINIBOX_V1, /* GainStrong MiniBox V1.0 */ ++ ATH79_MACH_GS_MINIBOX_V32, /* Gainstrong MiniBox V3.2 */ ++ ATH79_MACH_GS_OOLITE_V1, /* GainStrong Oolite V1.0 */ ++ ATH79_MACH_GS_OOLITE_V5_2, /* GainStrong Oolite V5.2 */ ++ ATH79_MACH_GS_OOLITE_V5_2_DEV, /* GainStrong Oolite V5.2-Dev */ ++ ATH79_MACH_HIVEAP_121, /* Aerohive HiveAP-121*/ ++ ATH79_MACH_HIWIFI_HC6361, /* HiWiFi HC6361 */ ++ ATH79_MACH_HORNET_UB, /* ALFA Networks Hornet-UB */ ++ ATH79_MACH_JA76PF, /* jjPlus JA76PF */ ++ ATH79_MACH_JA76PF2, /* jjPlus JA76PF2 */ ++ ATH79_MACH_JWAP003, /* jjPlus JWAP003 */ ++ ATH79_MACH_JWAP230, /* jjPlus JWAP230 */ ++ ATH79_MACH_KOALA, /* OCEDO Koala */ ++ ATH79_MACH_LAN_TURTLE, /* Hak5 LAN Turtle */ ++ ATH79_MACH_LIMA, /* 8devices Lima */ ++ ATH79_MACH_MC_MAC1200R, /* MERCURY MAC1200R */ ++ ATH79_MACH_MR12, /* Cisco Meraki MR12 */ ++ ATH79_MACH_MR16, /* Cisco Meraki MR16 */ ++ ATH79_MACH_MR1750, /* OpenMesh MR1750 */ ++ ATH79_MACH_MR1750V2, /* OpenMesh MR1750v2 */ ++ ATH79_MACH_MR18, /* Cisco Meraki MR18 */ ++ ATH79_MACH_MR600, /* OpenMesh MR600 */ ++ ATH79_MACH_MR600V2, /* OpenMesh MR600v2 */ ++ ATH79_MACH_MR900, /* OpenMesh MR900 */ ++ ATH79_MACH_MR900v2, /* OpenMesh MR900v2 */ ++ ATH79_MACH_MYNET_N600, /* WD My Net N600 */ ++ ATH79_MACH_MYNET_N750, /* WD My Net N750 */ ++ ATH79_MACH_MYNET_REXT, /* WD My Net Wi-Fi Range Extender */ ++ ATH79_MACH_MZK_W04NU, /* Planex MZK-W04NU */ ++ ATH79_MACH_MZK_W300NH, /* Planex MZK-W300NH */ ++ ATH79_MACH_N5Q, /* ALFA Network N5Q */ ++ ATH79_MACH_NBG460N, /* Zyxel NBG460N/550N/550NH */ ++ ATH79_MACH_NBG6616, /* Zyxel NBG6616 */ ++ ATH79_MACH_NBG6716, /* Zyxel NBG6716 */ ++ ATH79_MACH_OM2P, /* OpenMesh OM2P */ ++ ATH79_MACH_OM2Pv2, /* OpenMesh OM2Pv2 */ ++ ATH79_MACH_OM2Pv4, /* OpenMesh OM2Pv4 */ ++ ATH79_MACH_OM2P_HS, /* OpenMesh OM2P-HS */ ++ ATH79_MACH_OM2P_HSv2, /* OpenMesh OM2P-HSv2 */ ++ ATH79_MACH_OM2P_HSv3, /* OpenMesh OM2P-HSv3 */ ++ ATH79_MACH_OM2P_HSv4, /* OpenMesh OM2P-HSv4 */ ++ ATH79_MACH_OM2P_LC, /* OpenMesh OM2P-LC */ ++ ATH79_MACH_OM5P, /* OpenMesh OM5P */ ++ ATH79_MACH_OM5P_AC, /* OpenMesh OM5P-AC */ ++ ATH79_MACH_OM5P_ACv2, /* OpenMesh OM5P-ACv2 */ ++ ATH79_MACH_OM5P_AN, /* OpenMesh OM5P-AN */ ++ ATH79_MACH_OMY_G1, /* OMYlink OMY-G1 */ ++ ATH79_MACH_OMY_X1, /* OMYlink OMY-X1 */ ++ ATH79_MACH_ONION_OMEGA, /* ONION OMEGA */ ++ ATH79_MACH_PACKET_SQUIRREL, /* Hak5 Packet Squirrel */ ++ ATH79_MACH_PB42, /* Atheros PB42 */ ++ ATH79_MACH_PB44, /* Atheros PB44 reference board */ ++ ATH79_MACH_PQI_AIR_PEN, /* PQI Air Pen */ ++ ATH79_MACH_QIHOO_C301, /* Qihoo 360 C301 */ ++ ATH79_MACH_R36A, /* ALFA Network R36A */ ++ ATH79_MACH_R602N, /* P&W R602N */ ++ ATH79_MACH_R6100, /* NETGEAR R6100 */ ++ ATH79_MACH_RAMBUTAN, /* 8devices Rambutan */ ++ ATH79_MACH_RB_2011G, /* Mikrotik RouterBOARD 2011UAS-2HnD */ ++ ATH79_MACH_RB_2011L, /* Mikrotik RouterBOARD 2011L */ ++ ATH79_MACH_RB_2011R5, /* Mikrotik RouterBOARD 2011UiAS(-2Hnd) */ ++ ATH79_MACH_RB_2011US, /* Mikrotik RouterBOARD 2011UAS */ ++ ATH79_MACH_RB_411, /* MikroTik RouterBOARD 411/411A/411AH */ ++ ATH79_MACH_RB_411U, /* MikroTik RouterBOARD 411U */ ++ ATH79_MACH_RB_433, /* MikroTik RouterBOARD 433/433AH */ ++ ATH79_MACH_RB_433U, /* MikroTik RouterBOARD 433UAH */ ++ ATH79_MACH_RB_435G, /* MikroTik RouterBOARD 435G */ ++ ATH79_MACH_RB_450, /* MikroTik RouterBOARD 450 */ ++ ATH79_MACH_RB_450G, /* MikroTik RouterBOARD 450G */ ++ ATH79_MACH_RB_493, /* Mikrotik RouterBOARD 493/493AH */ ++ ATH79_MACH_RB_493G, /* Mikrotik RouterBOARD 493G */ ++ ATH79_MACH_RB_711GR100, /* Mikrotik RouterBOARD 911/912 boards */ ++ ATH79_MACH_RB_750, /* MikroTik RouterBOARD 750 */ ++ ATH79_MACH_RB_750G_R3, /* MikroTik RouterBOARD 750GL */ ++ ATH79_MACH_RB_750UPR2, /* MikroTik RouterBOARD 750UP r2 */ ++ ATH79_MACH_RB_751, /* MikroTik RouterBOARD 751 */ ++ ATH79_MACH_RB_751G, /* Mikrotik RouterBOARD 751G */ ++ ATH79_MACH_RB_911L, /* Mikrotik RouterBOARD 911-2Hn/911-5Hn boards */ ++ ATH79_MACH_RB_922GS, /* Mikrotik RouterBOARD 911/922GS boards */ ++ ATH79_MACH_RB_931, /* MikroTik RouterBOARD 931-2nD */ ++ ATH79_MACH_RB_941, /* MikroTik RouterBOARD 941-2nD */ ++ ATH79_MACH_RB_951G, /* Mikrotik RouterBOARD 951G */ ++ ATH79_MACH_RB_951U, /* Mikrotik RouterBOARD 951Ui-2HnD */ ++ ATH79_MACH_RB_952, /* MikroTik RouterBOARD 951Ui-2nD / 952Ui-5ac2nD */ ++ ATH79_MACH_RB_962, /* MikroTik RouterBOARD 962UiGS-5HacT2HnT */ ++ ATH79_MACH_RB_CAP, /* Mikrotik RouterBOARD cAP2nD */ ++ ATH79_MACH_RB_LHG5, /* Mikrotik RouterBOARD LHG5 */ ++ ATH79_MACH_RB_MAP, /* Mikrotik RouterBOARD mAP2nD */ ++ ATH79_MACH_RB_MAPL, /* Mikrotik RouterBOARD mAP L-2nD */ ++ ATH79_MACH_RB_WAP, /* Mikrotik RouterBOARD wAP2nD */ ++ ATH79_MACH_RB_WAPR, /* Mikrotik RouterBOARD wAPR2nD */ ++ ATH79_MACH_RB_WAPAC, /* Mikrotik RouterBOARD wAPG-5HacT2HnD */ ++ ATH79_MACH_RB_SXTLITE2ND, /* Mikrotik RouterBOARD SXT Lite 2nD */ ++ ATH79_MACH_RB_SXTLITE5ND, /* Mikrotik RouterBOARD SXT Lite 5nD */ ++ ATH79_MACH_RE355, /* TP-LINK RE355 */ ++ ATH79_MACH_RE450, /* TP-LINK RE450 */ ++ ATH79_MACH_RME_EG200, /* eTactica EG200 */ ++ ATH79_MACH_RUT9XX, /* Teltonika RUT900 series */ ++ ATH79_MACH_RW2458N, /* Redwave RW2458N */ ++ ATH79_MACH_SC1750, /* Abicom SC1750 */ ++ ATH79_MACH_SC300M, /* Abicom SC300M */ ++ ATH79_MACH_SC450, /* Abicom SC450 */ ++ ATH79_MACH_SMART_300, /* NC-LINK SMART-300 */ ++ ATH79_MACH_SOM9331, /* OpenEmbed SOM9331 */ ++ ATH79_MACH_SR3200, /* YunCore SR3200 */ ++ ATH79_MACH_T830, /* YunCore T830 */ ++ ATH79_MACH_TELLSTICK_ZNET_LITE, /* TellStick ZNet Lite */ ++ ATH79_MACH_TEW_632BRP, /* TRENDnet TEW-632BRP */ ++ ATH79_MACH_TEW_673GRU, /* TRENDnet TEW-673GRU */ ++ ATH79_MACH_TEW_712BR, /* TRENDnet TEW-712BR */ ++ ATH79_MACH_TEW_732BR, /* TRENDnet TEW-732BR */ ++ ATH79_MACH_TEW_823DRU, /* TRENDnet TEW-823DRU */ ++ ATH79_MACH_TL_MR10U, /* TP-LINK TL-MR10U */ ++ ATH79_MACH_TL_MR11U, /* TP-LINK TL-MR11U */ ++ ATH79_MACH_TL_MR13U, /* TP-LINK TL-MR13U */ ++ ATH79_MACH_TL_MR3020, /* TP-LINK TL-MR3020 */ ++ ATH79_MACH_TL_MR3040, /* TP-LINK TL-MR3040 */ ++ ATH79_MACH_TL_MR3040_V2, /* TP-LINK TL-MR3040 v2 */ ++ ATH79_MACH_TL_MR3220, /* TP-LINK TL-MR3220 */ ++ ATH79_MACH_TL_MR3220_V2, /* TP-LINK TL-MR3220 v2 */ ++ ATH79_MACH_TL_MR3420, /* TP-LINK TL-MR3420 */ ++ ATH79_MACH_TL_MR3420_V2, /* TP-LINK TL-MR3420 v2 */ ++ ATH79_MACH_TL_MR6400, /* TP-LINK TL-MR6400 */ ++ ATH79_MACH_TL_WA701ND_V2, /* TP-LINK TL-WA701ND v2 */ ++ ATH79_MACH_TL_WA7210N_V2, /* TP-LINK TL-WA7210N v2 */ ++ ATH79_MACH_TL_WA750RE, /* TP-LINK TL-WA750RE */ ++ ATH79_MACH_TL_WA7510N_V1, /* TP-LINK TL-WA7510N v1 */ ++ ATH79_MACH_TL_WA801ND_V2, /* TP-LINK TL-WA801ND v2 */ ++ ATH79_MACH_TL_WA801ND_V3, /* TP-LINK TL-WA801ND v3 */ ++ ATH79_MACH_TL_WA830RE_V2, /* TP-LINK TL-WA830RE v2 */ ++ ATH79_MACH_TL_WA850RE, /* TP-LINK TL-WA850RE */ ++ ATH79_MACH_TL_WA850RE_V2, /* TP-LINK TL-WA850RE v2 */ ++ ATH79_MACH_TL_WA855RE_V1, /* TP-LINK TL-WA855RE v1 */ ++ ATH79_MACH_TL_WA860RE, /* TP-LINK TL-WA860RE */ ++ ATH79_MACH_TL_WA901ND, /* TP-LINK TL-WA901ND */ ++ ATH79_MACH_TL_WA901ND_V2, /* TP-LINK TL-WA901ND v2 */ ++ ATH79_MACH_TL_WA901ND_V3, /* TP-LINK TL-WA901ND v3 */ ++ ATH79_MACH_TL_WA901ND_V4, /* TP-LINK TL-WA901ND v4 */ ++ ATH79_MACH_TL_WA901ND_V5, /* TP-LINK TL-WA901ND v5 */ ++ ATH79_MACH_TL_WDR3320_V2, /* TP-LINK TL-WDR3320 v2 */ ++ ATH79_MACH_TL_WDR3500, /* TP-LINK TL-WDR3500 */ ++ ATH79_MACH_TL_WDR4300, /* TP-LINK TL-WDR4300 */ ++ ATH79_MACH_TL_WDR4900_V2, /* TP-LINK TL-WDR4900 v2 */ ++ ATH79_MACH_TL_WDR6500_V2, /* TP-LINK TL-WDR6500 v2 */ ++ ATH79_MACH_TL_WPA8630, /* TP-Link TL-WPA8630 */ ++ ATH79_MACH_TL_WR1041N_V2, /* TP-LINK TL-WR1041N v2 */ ++ ATH79_MACH_TL_WR1043N_V5, /* TP-LINK TL-WR1043N v5 */ ++ ATH79_MACH_TL_WR1043ND, /* TP-LINK TL-WR1043ND */ ++ ATH79_MACH_TL_WR1043ND_V2, /* TP-LINK TL-WR1043ND v2 */ ++ ATH79_MACH_TL_WR1043ND_V4, /* TP-LINK TL-WR1043ND v4 */ ++ ATH79_MACH_TL_WR2543N, /* TP-LINK TL-WR2543N/ND */ ++ ATH79_MACH_TL_WR703N, /* TP-LINK TL-WR703N */ ++ ATH79_MACH_TL_WR710N, /* TP-LINK TL-WR710N */ ++ ATH79_MACH_TL_WR720N_V3, /* TP-LINK TL-WR720N v3/v4 */ ++ ATH79_MACH_TL_WR740N_V6, /* TP-LINK TL-WR740N/ND v6 */ ++ ATH79_MACH_TL_WR741ND, /* TP-LINK TL-WR741ND */ ++ ATH79_MACH_TL_WR741ND_V4, /* TP-LINK TL-WR741ND v4 */ ++ ATH79_MACH_TL_WR802N_V1, /* TP-LINK TL-WR802N v1 */ ++ ATH79_MACH_TL_WR802N_V2, /* TP-LINK TL-WR802N v2 */ ++ ATH79_MACH_TL_WR810N, /* TP-LINK TL-WR810N */ ++ ATH79_MACH_TL_WR810N_V2, /* TP-LINK TL-WR810N v2 */ ++ ATH79_MACH_TL_WR840N_V2, /* TP-LINK TL-WR840N v2 */ ++ ATH79_MACH_TL_WR840N_V3, /* TP-LINK TL-WR840N v3 */ ++ ATH79_MACH_TL_WR841N_V1, /* TP-LINK TL-WR841N v1 */ ++ ATH79_MACH_TL_WR841N_V11, /* TP-LINK TL-WR841N/ND v11 */ ++ ATH79_MACH_TL_WR841N_V7, /* TP-LINK TL-WR841N/ND v7 */ ++ ATH79_MACH_TL_WR841N_V8, /* TP-LINK TL-WR841N/ND v8 */ ++ ATH79_MACH_TL_WR841N_V9, /* TP-LINK TL-WR841N/ND v9 */ ++ ATH79_MACH_TL_WR842N_V2, /* TP-LINK TL-WR842N/ND v2 */ ++ ATH79_MACH_TL_WR842N_V3, /* TP-LINK TL-WR842N/ND v3 */ ++ ATH79_MACH_TL_WR902AC_V1, /* TP-LINK TL-WR902AC v1 */ ++ ATH79_MACH_TL_WR941ND, /* TP-LINK TL-WR941ND */ ++ ATH79_MACH_TL_WR941ND_V5, /* TP-LINK TL-WR941ND v5 */ ++ ATH79_MACH_TL_WR941ND_V6, /* TP-LINK TL-WR941ND v6 */ ++ ATH79_MACH_TL_WR940N_V4, /* TP-LINK TL-WR940N v4 */ ++ ATH79_MACH_TL_WR940N_V6, /* TP-LINK TL-WR940N v6 */ ++ ATH79_MACH_TL_WR942N_V1, /* TP-LINK TL-WR942N v1 */ ++ ATH79_MACH_TS_D084, /* PISEN TS-D084 */ ++ ATH79_MACH_TUBE2H, /* Alfa Network Tube2H */ ++ ATH79_MACH_UBNT_AIRGW, /* Ubiquiti AirGateway */ ++ ATH79_MACH_UBNT_AIRGWP, /* Ubiquiti AirGateway Pro */ ++ ATH79_MACH_UBNT_AIRROUTER, /* Ubiquiti AirRouter */ ++ ATH79_MACH_UBNT_BULLET_M, /* Ubiquiti Bullet M */ ++ ATH79_MACH_UBNT_BULLET_M_XW, /* Ubiquiti Bullet M XW */ ++ ATH79_MACH_UBNT_LBE_M5, /* Ubiquiti Litebeam M5 */ ++ ATH79_MACH_UBNT_LOCO_M_XW, /* Ubiquiti Loco M XW */ ++ ATH79_MACH_UBNT_LSSR71, /* Ubiquiti LS-SR71 */ ++ ATH79_MACH_UBNT_LSX, /* Ubiquiti LSX */ ++ ATH79_MACH_UBNT_NANO_M, /* Ubiquiti NanoStation M */ ++ ATH79_MACH_UBNT_NANO_M_XW, /* Ubiquiti NanoStation M XW */ ++ ATH79_MACH_UBNT_ROCKET_M, /* Ubiquiti Rocket M */ ++ ATH79_MACH_UBNT_ROCKET_M_TI, /* Ubiquiti Rocket M TI */ ++ ATH79_MACH_UBNT_ROCKET_M_XW, /* Ubiquiti Rocket M XW */ ++ ATH79_MACH_UBNT_RS, /* Ubiquiti RouterStation */ ++ ATH79_MACH_UBNT_RSPRO, /* Ubiquiti RouterStation Pro */ ++ ATH79_MACH_UBNT_UAP_PRO, /* Ubiquiti UniFi AP Pro */ ++ ATH79_MACH_UBNT_UNIFI, /* Ubiquiti Unifi */ ++ ATH79_MACH_UBNT_UNIFIAC_LITE, /* Ubiquiti Unifi AC LITE/LR/MESH */ ++ ATH79_MACH_UBNT_UNIFIAC_PRO, /* Ubiquiti Unifi AC PRO/MESH PRO */ ++ ATH79_MACH_UBNT_UNIFI_OUTDOOR, /* Ubiquiti UnifiAP Outdoor */ ++ ATH79_MACH_UBNT_UNIFI_OUTDOOR_PLUS, /* Ubiquiti UnifiAP Outdoor+ */ ++ ATH79_MACH_UBNT_XM, /* Ubiquiti Networks XM board rev 1.0 */ ++ ATH79_MACH_WAM250, /* Samsung WAM250 */ ++ ATH79_MACH_WBS210, /* TP-LINK WBS210 */ ++ ATH79_MACH_WBS510, /* TP-LINK WBS510 */ ++ ATH79_MACH_WEIO, /* WeIO board */ ++ ATH79_MACH_WHR_G301N, /* Buffalo WHR-G301N */ ++ ATH79_MACH_WHR_HP_G300N, /* Buffalo WHR-HP-G300N */ ++ ATH79_MACH_WHR_HP_GN, /* Buffalo WHR-HP-GN */ ++ ATH79_MACH_WIFI_PINEAPPLE_NANO, /* Hak5 WiFi Pineapple NANO */ ++ ATH79_MACH_WLAE_AG300N, /* Buffalo WLAE-AG300N */ ++ ATH79_MACH_WLR8100, /* SITECOM WLR-8100 */ ++ ATH79_MACH_WNDAP360, /* NETGEAR WNDAP360 */ ++ ATH79_MACH_WNDR3700, /* NETGEAR WNDR3700/WNDR3800/WNDRMAC */ ++ ATH79_MACH_WNDR3700_V4, /* NETGEAR WNDR3700v4 */ ++ ATH79_MACH_WNDR4300, /* NETGEAR WNDR4300 */ ++ ATH79_MACH_WNR1000_V2, /* NETGEAR WNR1000 v2 */ ++ ATH79_MACH_WNR2000, /* NETGEAR WNR2000 */ ++ ATH79_MACH_WNR2000_V3, /* NETGEAR WNR2000 v3 */ ++ ATH79_MACH_WNR2000_V4, /* NETGEAR WNR2000 v4 */ ++ ATH79_MACH_WNR2200, /* NETGEAR WNR2200 */ ++ ATH79_MACH_WNR612_V2, /* NETGEAR WNR612 v2 */ ++ ATH79_MACH_WP543, /* Compex WP543 */ ++ ATH79_MACH_WPE72, /* Compex WPE72 */ ++ ATH79_MACH_WPJ342, /* Compex WPJ342 */ ++ ATH79_MACH_WPJ344, /* Compex WPJ344 */ ++ ATH79_MACH_WPJ531, /* Compex WPJ531 */ ++ ATH79_MACH_WPJ558, /* Compex WPJ558 */ ++ ATH79_MACH_WPJ563, /* Compex WPJ563 */ ++ ATH79_MACH_WPN824N, /* NETGEAR WPN824N */ ++ ATH79_MACH_WRT160NL, /* Linksys WRT160NL */ ++ ATH79_MACH_WRT400N, /* Linksys WRT400N */ ++ ATH79_MACH_WRTNODE2Q, /* WRTnode2Q */ ++ ATH79_MACH_WZR_450HP2, /* Buffalo WZR-450HP2 */ ++ ATH79_MACH_WZR_HP_AG300H, /* Buffalo WZR-HP-AG300H */ ++ ATH79_MACH_WZR_HP_G300NH, /* Buffalo WZR-HP-G300NH */ ++ ATH79_MACH_WZR_HP_G300NH2, /* Buffalo WZR-HP-G300NH2 */ ++ ATH79_MACH_WZR_HP_G450H, /* Buffalo WZR-HP-G450H */ ++ ATH79_MACH_XD3200, /* YunCore XD3200 */ ++ ATH79_MACH_Z1, /* Cisco Meraki Z1 */ ++ ATH79_MACH_ZBT_WE1526, /* Zbtlink ZBT-WE1526 */ ++ ATH79_MACH_ZCN_1523H_2, /* Zcomax ZCN-1523H-2-xx */ ++ ATH79_MACH_ZCN_1523H_5, /* Zcomax ZCN-1523H-5-xx */ ++}; ++ ++#endif /* _ATH79_MACHTYPE_H */ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/nvram.c b/target/linux/ar71xx/files/arch/mips/ath79/nvram.c +new file mode 100644 +index 0000000000..a1de55fb19 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/nvram.c +@@ -0,0 +1,85 @@ ++/* ++ * Atheros AR71xx minimal nvram support ++ * ++ * Copyright (C) 2009 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "nvram.h" ++ ++char *ath79_nvram_find_var(const char *name, const char *buf, unsigned buf_len) ++{ ++ unsigned len = strlen(name); ++ char *cur, *last; ++ ++ if (buf_len == 0 || len == 0) ++ return NULL; ++ ++ if (buf_len < len) ++ return NULL; ++ ++ if (len == 1) ++ return memchr(buf, (int) *name, buf_len); ++ ++ last = (char *) buf + buf_len - len; ++ for (cur = (char *) buf; cur <= last; cur++) ++ if (cur[0] == name[0] && memcmp(cur, name, len) == 0) ++ return cur + len; ++ ++ return NULL; ++} ++ ++int ath79_nvram_parse_mac_addr(const char *nvram, unsigned nvram_len, ++ const char *name, char *mac) ++{ ++ char *buf; ++ char *mac_str; ++ int ret; ++ int t; ++ ++ buf = vmalloc(nvram_len); ++ if (!buf) ++ return -ENOMEM; ++ ++ memcpy(buf, nvram, nvram_len); ++ buf[nvram_len - 1] = '\0'; ++ ++ mac_str = ath79_nvram_find_var(name, buf, nvram_len); ++ if (!mac_str) { ++ ret = -EINVAL; ++ goto free; ++ } ++ ++ if (strlen(mac_str) == 19 && mac_str[0] == '"' && mac_str[18] == '"') { ++ mac_str[18] = 0; ++ mac_str++; ++ } ++ ++ t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ ++ if (t != ETH_ALEN) ++ t = sscanf(mac_str, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ ++ if (t != ETH_ALEN) { ++ ret = -EINVAL; ++ goto free; ++ } ++ ++ ret = 0; ++ ++free: ++ vfree(buf); ++ return ret; ++} +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/nvram.h b/target/linux/ar71xx/files/arch/mips/ath79/nvram.h +new file mode 100644 +index 0000000000..75151d4a3c +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/nvram.h +@@ -0,0 +1,19 @@ ++/* ++ * Atheros AR71xx minimal nvram support ++ * ++ * Copyright (C) 2009 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 _ATH79_NVRAM_H ++#define _ATH79_NVRAM_H ++ ++char *ath79_nvram_find_var(const char *name, const char *buf, ++ unsigned buf_len); ++int ath79_nvram_parse_mac_addr(const char *nvram, unsigned nvram_len, ++ const char *name, char *mac); ++ ++#endif /* _ATH79_NVRAM_H */ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.c b/target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.c +new file mode 100644 +index 0000000000..2202351806 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.c +@@ -0,0 +1,126 @@ ++/* ++ * Atheros AP94 reference board PCI initialization ++ * ++ * Copyright (C) 2009-2010 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++ ++struct ath9k_fixup { ++ u16 *cal_data; ++ unsigned slot; ++}; ++ ++static int ath9k_num_fixups; ++static struct ath9k_fixup ath9k_fixups[2]; ++ ++static void ath9k_pci_fixup(struct pci_dev *dev) ++{ ++ void __iomem *mem; ++ u16 *cal_data = NULL; ++ u16 cmd; ++ u32 bar0; ++ u32 val; ++ unsigned i; ++ ++ for (i = 0; i < ath9k_num_fixups; i++) { ++ if (ath9k_fixups[i].cal_data == NULL) ++ continue; ++ ++ if (ath9k_fixups[i].slot != PCI_SLOT(dev->devfn)) ++ continue; ++ ++ cal_data = ath9k_fixups[i].cal_data; ++ break; ++ } ++ ++ if (cal_data == NULL) ++ return; ++ ++ if (*cal_data != 0xa55a) { ++ pr_err("pci %s: invalid calibration data\n", pci_name(dev)); ++ return; ++ } ++ ++ pr_info("pci %s: fixup device configuration\n", pci_name(dev)); ++ ++ mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000); ++ if (!mem) { ++ pr_err("pci %s: ioremap error\n", pci_name(dev)); ++ return; ++ } ++ ++ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); ++ ++ switch (ath79_soc) { ++ case ATH79_SOC_AR7161: ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ++ AR71XX_PCI_MEM_BASE); ++ break; ++ case ATH79_SOC_AR7240: ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffff); ++ break; ++ ++ case ATH79_SOC_AR7241: ++ case ATH79_SOC_AR7242: ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x1000ffff); ++ break; ++ case ATH79_SOC_AR9344: ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x1000ffff); ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ ++ /* set pointer to first reg address */ ++ cal_data += 3; ++ while (*cal_data != 0xffff) { ++ u32 reg; ++ reg = *cal_data++; ++ val = *cal_data++; ++ val |= (*cal_data++) << 16; ++ ++ __raw_writel(val, mem + reg); ++ udelay(100); ++ } ++ ++ pci_read_config_dword(dev, PCI_VENDOR_ID, &val); ++ dev->vendor = val & 0xffff; ++ dev->device = (val >> 16) & 0xffff; ++ ++ pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); ++ dev->revision = val & 0xff; ++ dev->class = val >> 8; /* upper 3 bytes */ ++ ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); ++ ++ iounmap(mem); ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup); ++ ++void __init pci_enable_ath9k_fixup(unsigned slot, u16 *cal_data) ++{ ++ if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups)) ++ return; ++ ++ ath9k_fixups[ath9k_num_fixups].slot = slot; ++ ath9k_fixups[ath9k_num_fixups].cal_data = cal_data; ++ ath9k_num_fixups++; ++} +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.h b/target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.h +new file mode 100644 +index 0000000000..5794941f08 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.h +@@ -0,0 +1,6 @@ ++#ifndef _PCI_ATH9K_FIXUP ++#define _PCI_ATH9K_FIXUP ++ ++void pci_enable_ath9k_fixup(unsigned slot, u16 *cal_data) __init; ++ ++#endif /* _PCI_ATH9K_FIXUP */ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c +new file mode 100644 +index 0000000000..4c0cd1314a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c +@@ -0,0 +1,354 @@ ++/* ++ * RouterBoot helper routines ++ * ++ * Copyright (C) 2012 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. ++ */ ++ ++#define pr_fmt(fmt) "rb: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "routerboot.h" ++ ++#define RB_BLOCK_SIZE 0x1000 ++#define RB_ART_SIZE 0x10000 ++#define RB_MAGIC_ERD 0x00455244 /* extended radio data */ ++ ++static struct rb_info rb_info; ++ ++static u32 get_u32(void *buf) ++{ ++ u8 *p = buf; ++ ++ return ((u32) p[3] + ((u32) p[2] << 8) + ((u32) p[1] << 16) + ++ ((u32) p[0] << 24)); ++} ++ ++static u16 get_u16(void *buf) ++{ ++ u8 *p = buf; ++ ++ return (u16) p[1] + ((u16) p[0] << 8); ++} ++ ++__init int ++routerboot_find_magic(u8 *buf, unsigned int buflen, u32 *offset, bool hard) ++{ ++ u32 magic_ref = hard ? RB_MAGIC_HARD : RB_MAGIC_SOFT; ++ u32 magic; ++ u32 cur = *offset; ++ ++ while (cur < buflen) { ++ magic = get_u32(buf + cur); ++ if (magic == magic_ref) { ++ *offset = cur; ++ return 0; ++ } ++ ++ cur += 0x1000; ++ } ++ ++ return -ENOENT; ++} ++ ++__init int ++routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id, ++ u8 **tag_data, u16 *tag_len) ++{ ++ uint32_t magic; ++ bool align = false; ++ int ret; ++ ++ if (buflen < 4) ++ return -EINVAL; ++ ++ magic = get_u32(buf); ++ switch (magic) { ++ case RB_MAGIC_ERD: ++ align = true; ++ /* fall trough */ ++ case RB_MAGIC_HARD: ++ /* skip magic value */ ++ buf += 4; ++ buflen -= 4; ++ break; ++ ++ case RB_MAGIC_SOFT: ++ if (buflen < 8) ++ return -EINVAL; ++ ++ /* skip magic and CRC value */ ++ buf += 8; ++ buflen -= 8; ++ ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ ret = -ENOENT; ++ while (buflen > 2) { ++ u16 id; ++ u16 len; ++ ++ len = get_u16(buf); ++ buf += 2; ++ buflen -= 2; ++ ++ if (buflen < 2) ++ break; ++ ++ id = get_u16(buf); ++ buf += 2; ++ buflen -= 2; ++ ++ if (id == RB_ID_TERMINATOR) ++ break; ++ ++ if (buflen < len) ++ break; ++ ++ if (id == tag_id) { ++ if (tag_len) ++ *tag_len = len; ++ if (tag_data) ++ *tag_data = buf; ++ ret = 0; ++ break; ++ } ++ ++ if (align) ++ len = (len + 3) / 4; ++ ++ buf += len; ++ buflen -= len; ++ } ++ ++ return ret; ++} ++ ++static inline int ++rb_find_hard_cfg_tag(u16 tag_id, u8 **tag_data, u16 *tag_len) ++{ ++ if (!rb_info.hard_cfg_data || ++ !rb_info.hard_cfg_size) ++ return -ENOENT; ++ ++ return routerboot_find_tag(rb_info.hard_cfg_data, ++ rb_info.hard_cfg_size, ++ tag_id, tag_data, tag_len); ++} ++ ++__init const char * ++rb_get_board_name(void) ++{ ++ u16 tag_len; ++ u8 *tag; ++ int err; ++ ++ err = rb_find_hard_cfg_tag(RB_ID_BOARD_NAME, &tag, &tag_len); ++ if (err) ++ return NULL; ++ ++ return tag; ++} ++ ++__init u32 ++rb_get_hw_options(void) ++{ ++ u16 tag_len; ++ u8 *tag; ++ int err; ++ ++ err = rb_find_hard_cfg_tag(RB_ID_HW_OPTIONS, &tag, &tag_len); ++ if (err) ++ return 0; ++ ++ return get_u32(tag); ++} ++ ++static void * __init ++__rb_get_wlan_data(u16 id) ++{ ++ u16 tag_len; ++ u8 *tag; ++ void *buf; ++ int err; ++ u32 magic; ++ size_t src_done; ++ size_t dst_done; ++ ++ err = rb_find_hard_cfg_tag(RB_ID_WLAN_DATA, &tag, &tag_len); ++ if (err) { ++ pr_err("no calibration data found\n"); ++ goto err; ++ } ++ ++ buf = kmalloc(RB_ART_SIZE, GFP_KERNEL); ++ if (buf == NULL) { ++ pr_err("no memory for calibration data\n"); ++ goto err; ++ } ++ ++ magic = get_u32(tag); ++ if (magic == RB_MAGIC_ERD) { ++ u8 *erd_data; ++ u16 erd_len; ++ ++ err = routerboot_find_tag(tag, tag_len, 0x1, ++ &erd_data, &erd_len); ++ if (err) { ++ pr_err("no ERD data found for id %u\n", id); ++ goto err_free; ++ } ++ ++ dst_done = RB_ART_SIZE; ++ err = lzo1x_decompress_safe(erd_data, erd_len, buf, &dst_done); ++ if (err) { ++ pr_err("unable to decompress calibration data %d\n", ++ err); ++ goto err_free; ++ } ++ } else { ++ err = rle_decode((char *) tag, tag_len, buf, RB_ART_SIZE, ++ &src_done, &dst_done); ++ if (err) { ++ pr_err("unable to decode calibration data\n"); ++ goto err_free; ++ } ++ } ++ ++ return buf; ++ ++err_free: ++ kfree(buf); ++err: ++ return NULL; ++} ++ ++__init void * ++rb_get_wlan_data(void) ++{ ++ return __rb_get_wlan_data(0); ++} ++ ++__init void * ++rb_get_ext_wlan_data(u16 id) ++{ ++ return __rb_get_wlan_data(id); ++} ++ ++__init const struct rb_info * ++rb_init_info(void *data, unsigned int size) ++{ ++ unsigned int offset; ++ ++ if (size == 0 || (size % RB_BLOCK_SIZE) != 0) ++ return NULL; ++ ++ for (offset = 0; offset < size; offset += RB_BLOCK_SIZE) { ++ u32 magic; ++ ++ magic = get_u32(data + offset); ++ switch (magic) { ++ case RB_MAGIC_HARD: ++ rb_info.hard_cfg_offs = offset; ++ break; ++ ++ case RB_MAGIC_SOFT: ++ rb_info.soft_cfg_offs = offset; ++ break; ++ } ++ } ++ ++ if (!rb_info.hard_cfg_offs) { ++ pr_err("could not find a valid RouterBOOT hard config\n"); ++ return NULL; ++ } ++ ++ if (!rb_info.soft_cfg_offs) { ++ pr_err("could not find a valid RouterBOOT soft config\n"); ++ return NULL; ++ } ++ ++ rb_info.hard_cfg_size = RB_BLOCK_SIZE; ++ rb_info.hard_cfg_data = kmemdup(data + rb_info.hard_cfg_offs, ++ RB_BLOCK_SIZE, GFP_KERNEL); ++ if (!rb_info.hard_cfg_data) ++ return NULL; ++ ++ rb_info.board_name = rb_get_board_name(); ++ rb_info.hw_options = rb_get_hw_options(); ++ ++ return &rb_info; ++} ++ ++#if 0 ++static char *rb_ext_wlan_data; ++ ++static ssize_t ++rb_ext_wlan_data_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, char *buf, ++ loff_t off, size_t count) ++{ ++ if (off + count > attr->size) ++ return -EFBIG; ++ ++ memcpy(buf, &rb_ext_wlan_data[off], count); ++ ++ return count; ++} ++ ++static const struct bin_attribute rb_ext_wlan_data_attr = { ++ .attr = { ++ .name = "ext_wlan_data", ++ .mode = S_IRUSR | S_IWUSR, ++ }, ++ .read = rb_ext_wlan_data_read, ++ .size = RB_ART_SIZE, ++}; ++ ++static int __init rb_sysfs_init(void) ++{ ++ struct kobject *rb_kobj; ++ int ret; ++ ++ rb_ext_wlan_data = rb_get_ext_wlan_data(1); ++ if (rb_ext_wlan_data == NULL) ++ return -ENOENT; ++ ++ rb_kobj = kobject_create_and_add("routerboot", firmware_kobj); ++ if (rb_kobj == NULL) { ++ ret = -ENOMEM; ++ pr_err("unable to create sysfs entry\n"); ++ goto err_free_wlan_data; ++ } ++ ++ ret = sysfs_create_bin_file(rb_kobj, &rb_ext_wlan_data_attr); ++ if (ret) { ++ pr_err("unable to create sysfs file, %d\n", ret); ++ goto err_put_kobj; ++ } ++ ++ return 0; ++ ++err_put_kobj: ++ kobject_put(rb_kobj); ++err_free_wlan_data: ++ kfree(rb_ext_wlan_data); ++ return ret; ++} ++ ++late_initcall(rb_sysfs_init); ++#endif +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h +new file mode 100644 +index 0000000000..cf189362d6 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h +@@ -0,0 +1,89 @@ ++/* ++ * RouterBoot definitions ++ * ++ * Copyright (C) 2012 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 _ATH79_ROUTERBOOT_H_ ++#define _ATH79_ROUTERBOOT_H_ ++ ++struct rb_info { ++ unsigned int hard_cfg_offs; ++ unsigned int hard_cfg_size; ++ void *hard_cfg_data; ++ unsigned int soft_cfg_offs; ++ ++ const char *board_name; ++ u32 hw_options; ++}; ++ ++/* Bit definitions for hardware options */ ++#define RB_HW_OPT_UART_ABSENT BIT(0) ++#define RB_HW_OPT_HAS_VOLTAGE BIT(1) ++#define RB_HW_OPT_HAS_USB BIT(2) ++#define RB_HW_OPT_HAS_ATTINY BIT(3) ++#define RB_HW_OPT_NO_NAND BIT(14) ++#define RB_HW_OPT_HAS_LCD BIT(15) ++#define RB_HW_OPT_HAS_POE_OUT BIT(16) ++#define RB_HW_OPT_HAS_uSD BIT(17) ++#define RB_HW_OPT_HAS_SFP BIT(20) ++#define RB_HW_OPT_HAS_WIFI BIT(21) ++#define RB_HW_OPT_HAS_TS_FOR_ADC BIT(22) ++#define RB_HW_OPT_HAS_PLC BIT(29) ++ ++static inline bool ++rb_hw_option_match(const struct rb_info *info, u32 mask, u32 val) ++{ ++ return (info->hw_options & (val | mask)) == val; ++} ++ ++static inline bool ++rb_has_hw_option(const struct rb_info *info, u32 mask) ++{ ++ return rb_hw_option_match(info, mask, mask); ++} ++ ++#ifdef CONFIG_ATH79_ROUTERBOOT ++const struct rb_info *rb_init_info(void *data, unsigned int size); ++void *rb_get_wlan_data(void); ++void *rb_get_ext_wlan_data(u16 id); ++ ++int routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id, ++ u8 **tag_data, u16 *tag_len); ++int routerboot_find_magic(u8 *buf, unsigned int buflen, u32 *offset, bool hard); ++#else ++static inline const struct rb_info * ++rb_init_info(void *data, unsigned int size) ++{ ++ return NULL; ++} ++ ++static inline void *rb_get_wlan_data(void) ++{ ++ return NULL; ++} ++ ++static inline void *rb_get_wlan_data(u16 id) ++{ ++ return NULL; ++} ++ ++static inline int ++routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id, ++ u8 **tag_data, u16 *tag_len) ++{ ++ return -ENOENT; ++} ++ ++static inline int ++routerboot_find_magic(u8 *buf, unsigned int buflen, u32 *offset, bool hard) ++{ ++ return -ENOENT; ++} ++#endif ++ ++#endif /* _ATH79_ROUTERBOOT_H_ */ +diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/fw/myloader/myloader.h b/target/linux/ar71xx/files/arch/mips/include/asm/fw/myloader/myloader.h +new file mode 100644 +index 0000000000..8a99d566d7 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/include/asm/fw/myloader/myloader.h +@@ -0,0 +1,34 @@ ++/* ++ * Compex's MyLoader specific definitions ++ * ++ * Copyright (C) 2006-2008 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 _ASM_MIPS_FW_MYLOADER_H ++#define _ASM_MIPS_FW_MYLOADER_H ++ ++#include ++ ++struct myloader_info { ++ uint32_t vid; ++ uint32_t did; ++ uint32_t svid; ++ uint32_t sdid; ++ uint8_t macs[MYLO_ETHADDR_COUNT][6]; ++}; ++ ++#ifdef CONFIG_MYLOADER ++extern struct myloader_info *myloader_get_info(void) __init; ++#else ++static inline struct myloader_info *myloader_get_info(void) ++{ ++ return NULL; ++} ++#endif /* CONFIG_MYLOADER */ ++ ++#endif /* _ASM_MIPS_FW_MYLOADER_H */ +diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h +new file mode 100644 +index 0000000000..e476d57e45 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h +@@ -0,0 +1,65 @@ ++/* ++ * Atheros AR71xx SoC specific platform data definitions ++ * ++ * Copyright (C) 2008-2012 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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 __ASM_MACH_ATH79_PLATFORM_H ++#define __ASM_MACH_ATH79_PLATFORM_H ++ ++#include ++#include ++#include ++#include ++ ++struct ag71xx_switch_platform_data { ++ u8 phy4_mii_en:1; ++ u8 phy_poll_mask; ++}; ++ ++struct ag71xx_platform_data { ++ phy_interface_t phy_if_mode; ++ u32 phy_mask; ++ int speed; ++ int duplex; ++ u32 reset_bit; ++ u8 mac_addr[ETH_ALEN]; ++ struct device *mii_bus_dev; ++ ++ u8 has_gbit:1; ++ u8 is_ar91xx:1; ++ u8 is_ar7240:1; ++ u8 is_ar724x:1; ++ u8 has_ar8216:1; ++ u8 use_flow_control:1; ++ u8 enable_sgmii_fixup:1; ++ u8 disable_inline_checksum_engine:1; ++ ++ struct ag71xx_switch_platform_data *switch_data; ++ ++ void (*ddr_flush)(void); ++ void (*set_speed)(int speed); ++ void (*update_pll)(u32 pll_10, u32 pll_100, u32 pll_1000); ++ ++ unsigned int max_frame_len; ++ unsigned int desc_pktlen_mask; ++}; ++ ++struct ag71xx_mdio_platform_data { ++ u32 phy_mask; ++ u8 builtin_switch:1; ++ u8 is_ar7240:1; ++ u8 is_ar9330:1; ++ u8 is_ar934x:1; ++ unsigned long mdio_clock; ++ unsigned long ref_clock; ++ ++ void (*reset)(struct mii_bus *bus); ++}; ++ ++#endif /* __ASM_MACH_ATH79_PLATFORM_H */ +diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/mach-rb750.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/mach-rb750.h +new file mode 100644 +index 0000000000..50d5a20974 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/mach-rb750.h +@@ -0,0 +1,84 @@ ++/* ++ * MikroTik RouterBOARD 750 definitions ++ * ++ * Copyright (C) 2010-2012 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 _MACH_RB750_H ++#define _MACH_RB750_H ++ ++#include ++ ++#define RB750_GPIO_LVC573_LE 0 /* Latch enable on LVC573 */ ++#define RB750_GPIO_NAND_IO0 1 /* NAND I/O 0 */ ++#define RB750_GPIO_NAND_IO1 2 /* NAND I/O 1 */ ++#define RB750_GPIO_NAND_IO2 3 /* NAND I/O 2 */ ++#define RB750_GPIO_NAND_IO3 4 /* NAND I/O 3 */ ++#define RB750_GPIO_NAND_IO4 5 /* NAND I/O 4 */ ++#define RB750_GPIO_NAND_IO5 6 /* NAND I/O 5 */ ++#define RB750_GPIO_NAND_IO6 7 /* NAND I/O 6 */ ++#define RB750_GPIO_NAND_IO7 8 /* NAND I/O 7 */ ++#define RB750_GPIO_NAND_NCE 11 /* NAND Chip Enable (active low) */ ++#define RB750_GPIO_NAND_RDY 12 /* NAND Ready */ ++#define RB750_GPIO_NAND_CLE 14 /* NAND Command Latch Enable */ ++#define RB750_GPIO_NAND_ALE 15 /* NAND Address Latch Enable */ ++#define RB750_GPIO_NAND_NRE 16 /* NAND Read Enable (active low) */ ++#define RB750_GPIO_NAND_NWE 17 /* NAND Write Enable (active low) */ ++ ++#define RB750_GPIO_BTN_RESET 1 ++#define RB750_GPIO_SPI_CS0 2 ++#define RB750_GPIO_LED_ACT 12 ++#define RB750_GPIO_LED_PORT1 13 ++#define RB750_GPIO_LED_PORT2 14 ++#define RB750_GPIO_LED_PORT3 15 ++#define RB750_GPIO_LED_PORT4 16 ++#define RB750_GPIO_LED_PORT5 17 ++ ++#define RB750_LED_ACT BIT(RB750_GPIO_LED_ACT) ++#define RB750_LED_PORT1 BIT(RB750_GPIO_LED_PORT1) ++#define RB750_LED_PORT2 BIT(RB750_GPIO_LED_PORT2) ++#define RB750_LED_PORT3 BIT(RB750_GPIO_LED_PORT3) ++#define RB750_LED_PORT4 BIT(RB750_GPIO_LED_PORT4) ++#define RB750_LED_PORT5 BIT(RB750_GPIO_LED_PORT5) ++#define RB750_NAND_NCE BIT(RB750_GPIO_NAND_NCE) ++ ++#define RB750_LVC573_LE BIT(RB750_GPIO_LVC573_LE) ++ ++#define RB750_LED_BITS (RB750_LED_PORT1 | RB750_LED_PORT2 | RB750_LED_PORT3 | \ ++ RB750_LED_PORT4 | RB750_LED_PORT5 | RB750_LED_ACT) ++ ++#define RB7XX_GPIO_NAND_NCE 0 ++#define RB7XX_GPIO_MON 9 ++#define RB7XX_GPIO_LED_ACT 11 ++#define RB7XX_GPIO_USB_POWERON 13 ++ ++#define RB7XX_NAND_NCE BIT(RB7XX_GPIO_NAND_NCE) ++#define RB7XX_LED_ACT BIT(RB7XX_GPIO_LED_ACT) ++#define RB7XX_MONITOR BIT(RB7XX_GPIO_MON) ++#define RB7XX_USB_POWERON BIT(RB7XX_GPIO_USB_POWERON) ++ ++struct rb750_led_data { ++ char *name; ++ char *default_trigger; ++ u32 mask; ++ int active_low; ++}; ++ ++struct rb750_led_platform_data { ++ int num_leds; ++ struct rb750_led_data *leds; ++ void (*latch_change)(u32 clear, u32 set); ++}; ++ ++struct rb7xx_nand_platform_data { ++ u32 nce_line; ++ ++ void (*enable_pins)(void); ++ void (*disable_pins)(void); ++ void (*latch_change)(u32, u32); ++}; ++ ++#endif /* _MACH_RB750_H */ +\ No newline at end of file +diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/rb4xx_cpld.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/rb4xx_cpld.h +new file mode 100644 +index 0000000000..37512ba1a1 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/rb4xx_cpld.h +@@ -0,0 +1,43 @@ ++/* ++ * SPI driver definitions for the CPLD chip on the Mikrotik RB4xx boards ++ * ++ * Copyright (C) 2010 Gabor Juhos ++ * ++ * This file was based on the patches for Linux 2.6.27.39 published by ++ * MikroTik for their RouterBoard 4xx series devices. ++ * ++ * 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. ++ */ ++ ++#define CPLD_GPIO_nLED1 0 ++#define CPLD_GPIO_nLED2 1 ++#define CPLD_GPIO_nLED3 2 ++#define CPLD_GPIO_nLED4 3 ++#define CPLD_GPIO_FAN 4 ++#define CPLD_GPIO_ALE 5 ++#define CPLD_GPIO_CLE 6 ++#define CPLD_GPIO_nCE 7 ++#define CPLD_GPIO_nLED5 8 ++ ++#define CPLD_NUM_GPIOS 9 ++ ++#define CPLD_CFG_nLED1 BIT(CPLD_GPIO_nLED1) ++#define CPLD_CFG_nLED2 BIT(CPLD_GPIO_nLED2) ++#define CPLD_CFG_nLED3 BIT(CPLD_GPIO_nLED3) ++#define CPLD_CFG_nLED4 BIT(CPLD_GPIO_nLED4) ++#define CPLD_CFG_FAN BIT(CPLD_GPIO_FAN) ++#define CPLD_CFG_ALE BIT(CPLD_GPIO_ALE) ++#define CPLD_CFG_CLE BIT(CPLD_GPIO_CLE) ++#define CPLD_CFG_nCE BIT(CPLD_GPIO_nCE) ++#define CPLD_CFG_nLED5 BIT(CPLD_GPIO_nLED5) ++ ++struct rb4xx_cpld_platform_data { ++ unsigned gpio_base; ++}; ++ ++extern int rb4xx_cpld_change_cfg(unsigned mask, unsigned value); ++extern int rb4xx_cpld_read(unsigned char *rx_buf, ++ unsigned cnt); ++extern int rb4xx_cpld_write(const unsigned char *buf, unsigned count); +diff --git a/target/linux/ar71xx/files/drivers/gpio/gpio-latch.c b/target/linux/ar71xx/files/drivers/gpio/gpio-latch.c +new file mode 100644 +index 0000000000..d911f6a2cb +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/gpio/gpio-latch.c +@@ -0,0 +1,220 @@ ++/* ++ * GPIO latch driver ++ * ++ * Copyright (C) 2014 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++struct gpio_latch_chip { ++ struct gpio_chip gc; ++ ++ struct mutex mutex; ++ struct mutex latch_mutex; ++ bool latch_enabled; ++ int le_gpio; ++ bool le_active_low; ++ int *gpios; ++}; ++ ++static inline struct gpio_latch_chip *to_gpio_latch_chip(struct gpio_chip *gc) ++{ ++ return container_of(gc, struct gpio_latch_chip, gc); ++} ++ ++static void gpio_latch_lock(struct gpio_latch_chip *glc, bool enable) ++{ ++ mutex_lock(&glc->mutex); ++ ++ if (enable) ++ glc->latch_enabled = true; ++ ++ if (glc->latch_enabled) ++ mutex_lock(&glc->latch_mutex); ++} ++ ++static void gpio_latch_unlock(struct gpio_latch_chip *glc, bool disable) ++{ ++ if (glc->latch_enabled) ++ mutex_unlock(&glc->latch_mutex); ++ ++ if (disable) ++ glc->latch_enabled = true; ++ ++ mutex_unlock(&glc->mutex); ++} ++ ++static int ++gpio_latch_get(struct gpio_chip *gc, unsigned offset) ++{ ++ struct gpio_latch_chip *glc = to_gpio_latch_chip(gc); ++ int ret; ++ ++ gpio_latch_lock(glc, false); ++ ret = gpio_get_value(glc->gpios[offset]); ++ gpio_latch_unlock(glc, false); ++ ++ return ret; ++} ++ ++static void ++gpio_latch_set(struct gpio_chip *gc, unsigned offset, int value) ++{ ++ struct gpio_latch_chip *glc = to_gpio_latch_chip(gc); ++ bool enable_latch = false; ++ bool disable_latch = false; ++ int gpio; ++ ++ gpio = glc->gpios[offset]; ++ ++ if (gpio == glc->le_gpio) { ++ enable_latch = value ^ glc->le_active_low; ++ disable_latch = !enable_latch; ++ } ++ ++ gpio_latch_lock(glc, enable_latch); ++ gpio_set_value(gpio, value); ++ gpio_latch_unlock(glc, disable_latch); ++} ++ ++static int ++gpio_latch_direction_input(struct gpio_chip *gc, unsigned offset) ++{ ++ struct gpio_latch_chip *glc = to_gpio_latch_chip(gc); ++ int ret; ++ ++ gpio_latch_lock(glc, false); ++ ret = gpio_direction_input(glc->gpios[offset]); ++ gpio_latch_unlock(glc, false); ++ ++ return ret; ++} ++ ++static int ++gpio_latch_direction_output(struct gpio_chip *gc, unsigned offset, int value) ++{ ++ struct gpio_latch_chip *glc = to_gpio_latch_chip(gc); ++ bool enable_latch = false; ++ bool disable_latch = false; ++ int gpio; ++ int ret; ++ ++ gpio = glc->gpios[offset]; ++ ++ if (gpio == glc->le_gpio) { ++ enable_latch = value ^ glc->le_active_low; ++ disable_latch = !enable_latch; ++ } ++ ++ gpio_latch_lock(glc, enable_latch); ++ ret = gpio_direction_output(gpio, value); ++ gpio_latch_unlock(glc, disable_latch); ++ ++ return ret; ++} ++ ++static int gpio_latch_probe(struct platform_device *pdev) ++{ ++ struct gpio_latch_chip *glc; ++ struct gpio_latch_platform_data *pdata; ++ struct gpio_chip *gc; ++ int size; ++ int ret; ++ int i; ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ if (!pdata) ++ return -EINVAL; ++ ++ if (pdata->le_gpio_index >= pdata->num_gpios || ++ !pdata->num_gpios || ++ !pdata->gpios) ++ return -EINVAL; ++ ++ for (i = 0; i < pdata->num_gpios; i++) { ++ int gpio = pdata->gpios[i]; ++ ++ ret = devm_gpio_request(&pdev->dev, gpio, ++ GPIO_LATCH_DRIVER_NAME); ++ if (ret) ++ return ret; ++ } ++ ++ glc = devm_kzalloc(&pdev->dev, sizeof(*glc), GFP_KERNEL); ++ if (!glc) ++ return -ENOMEM; ++ ++ mutex_init(&glc->mutex); ++ mutex_init(&glc->latch_mutex); ++ ++ size = pdata->num_gpios * sizeof(glc->gpios[0]); ++ glc->gpios = devm_kzalloc(&pdev->dev, size , GFP_KERNEL); ++ if (!glc->gpios) ++ return -ENOMEM; ++ ++ memcpy(glc->gpios, pdata->gpios, size); ++ ++ glc->le_gpio = glc->gpios[pdata->le_gpio_index]; ++ glc->le_active_low = pdata->le_active_low; ++ ++ gc = &glc->gc; ++ ++ gc->label = GPIO_LATCH_DRIVER_NAME; ++ gc->base = pdata->base; ++ gc->can_sleep = true; ++ gc->ngpio = pdata->num_gpios; ++ gc->get = gpio_latch_get; ++ gc->set = gpio_latch_set; ++ gc->direction_input = gpio_latch_direction_input, ++ gc->direction_output = gpio_latch_direction_output; ++ ++ platform_set_drvdata(pdev, glc); ++ ++ ret = gpiochip_add(&glc->gc); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int gpio_latch_remove(struct platform_device *pdev) ++{ ++ struct gpio_latch_chip *glc = platform_get_drvdata(pdev); ++ ++ gpiochip_remove(&glc->gc); ++ return 0; ++} ++ ++ ++static struct platform_driver gpio_latch_driver = { ++ .probe = gpio_latch_probe, ++ .remove = gpio_latch_remove, ++ .driver = { ++ .name = GPIO_LATCH_DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init gpio_latch_init(void) ++{ ++ return platform_driver_register(&gpio_latch_driver); ++} ++ ++postcore_initcall(gpio_latch_init); ++ ++MODULE_DESCRIPTION("GPIO latch driver"); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" GPIO_LATCH_DRIVER_NAME); +diff --git a/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c b/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c +new file mode 100644 +index 0000000000..82e6e943ff +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c +@@ -0,0 +1,243 @@ ++/* ++ * NXP 74HC153 - Dual 4-input multiplexer GPIO driver ++ * ++ * Copyright (C) 2010 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define NXP_74HC153_NUM_GPIOS 8 ++#define NXP_74HC153_S0_MASK 0x1 ++#define NXP_74HC153_S1_MASK 0x2 ++#define NXP_74HC153_BANK_MASK 0x4 ++ ++struct nxp_74hc153_chip { ++ struct device *parent; ++ struct gpio_chip gpio_chip; ++ struct mutex lock; ++}; ++ ++static struct nxp_74hc153_chip *gpio_to_nxp(struct gpio_chip *gc) ++{ ++ return container_of(gc, struct nxp_74hc153_chip, gpio_chip); ++} ++ ++static int nxp_74hc153_direction_input(struct gpio_chip *gc, unsigned offset) ++{ ++ return 0; ++} ++ ++static int nxp_74hc153_direction_output(struct gpio_chip *gc, ++ unsigned offset, int val) ++{ ++ return -EINVAL; ++} ++ ++static int nxp_74hc153_get_value(struct gpio_chip *gc, unsigned offset) ++{ ++ struct nxp_74hc153_chip *nxp; ++ struct nxp_74hc153_platform_data *pdata; ++ unsigned s0; ++ unsigned s1; ++ unsigned pin; ++ int ret; ++ ++ nxp = gpio_to_nxp(gc); ++ pdata = nxp->parent->platform_data; ++ ++ s0 = !!(offset & NXP_74HC153_S0_MASK); ++ s1 = !!(offset & NXP_74HC153_S1_MASK); ++ pin = (offset & NXP_74HC153_BANK_MASK) ? pdata->gpio_pin_2y ++ : pdata->gpio_pin_1y; ++ ++ mutex_lock(&nxp->lock); ++ gpio_set_value(pdata->gpio_pin_s0, s0); ++ gpio_set_value(pdata->gpio_pin_s1, s1); ++ ret = gpio_get_value(pin); ++ mutex_unlock(&nxp->lock); ++ ++ return ret; ++} ++ ++static void nxp_74hc153_set_value(struct gpio_chip *gc, ++ unsigned offset, int val) ++{ ++ /* not supported */ ++} ++ ++static int nxp_74hc153_probe(struct platform_device *pdev) ++{ ++ struct nxp_74hc153_platform_data *pdata; ++ struct nxp_74hc153_chip *nxp; ++ struct gpio_chip *gc; ++ int err; ++ ++ pdata = pdev->dev.platform_data; ++ if (pdata == NULL) { ++ dev_dbg(&pdev->dev, "no platform data specified\n"); ++ return -EINVAL; ++ } ++ ++ nxp = kzalloc(sizeof(struct nxp_74hc153_chip), GFP_KERNEL); ++ if (nxp == NULL) { ++ dev_err(&pdev->dev, "no memory for private data\n"); ++ return -ENOMEM; ++ } ++ ++ err = gpio_request(pdata->gpio_pin_s0, dev_name(&pdev->dev)); ++ if (err) { ++ dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n", ++ pdata->gpio_pin_s0, err); ++ goto err_free_nxp; ++ } ++ ++ err = gpio_request(pdata->gpio_pin_s1, dev_name(&pdev->dev)); ++ if (err) { ++ dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n", ++ pdata->gpio_pin_s1, err); ++ goto err_free_s0; ++ } ++ ++ err = gpio_request(pdata->gpio_pin_1y, dev_name(&pdev->dev)); ++ if (err) { ++ dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n", ++ pdata->gpio_pin_1y, err); ++ goto err_free_s1; ++ } ++ ++ err = gpio_request(pdata->gpio_pin_2y, dev_name(&pdev->dev)); ++ if (err) { ++ dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n", ++ pdata->gpio_pin_2y, err); ++ goto err_free_1y; ++ } ++ ++ err = gpio_direction_output(pdata->gpio_pin_s0, 0); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to set direction of gpio %u, err=%d\n", ++ pdata->gpio_pin_s0, err); ++ goto err_free_2y; ++ } ++ ++ err = gpio_direction_output(pdata->gpio_pin_s1, 0); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to set direction of gpio %u, err=%d\n", ++ pdata->gpio_pin_s1, err); ++ goto err_free_2y; ++ } ++ ++ err = gpio_direction_input(pdata->gpio_pin_1y); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to set direction of gpio %u, err=%d\n", ++ pdata->gpio_pin_1y, err); ++ goto err_free_2y; ++ } ++ ++ err = gpio_direction_input(pdata->gpio_pin_2y); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to set direction of gpio %u, err=%d\n", ++ pdata->gpio_pin_2y, err); ++ goto err_free_2y; ++ } ++ ++ nxp->parent = &pdev->dev; ++ mutex_init(&nxp->lock); ++ ++ gc = &nxp->gpio_chip; ++ ++ gc->direction_input = nxp_74hc153_direction_input; ++ gc->direction_output = nxp_74hc153_direction_output; ++ gc->get = nxp_74hc153_get_value; ++ gc->set = nxp_74hc153_set_value; ++ gc->can_sleep = 1; ++ ++ gc->base = pdata->gpio_base; ++ gc->ngpio = NXP_74HC153_NUM_GPIOS; ++ gc->label = dev_name(nxp->parent); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ gc->dev = nxp->parent; ++#else ++ gc->parent = nxp->parent; ++#endif ++ gc->owner = THIS_MODULE; ++ ++ err = gpiochip_add(&nxp->gpio_chip); ++ if (err) { ++ dev_err(&pdev->dev, "unable to add gpio chip, err=%d\n", err); ++ goto err_free_2y; ++ } ++ ++ platform_set_drvdata(pdev, nxp); ++ return 0; ++ ++err_free_2y: ++ gpio_free(pdata->gpio_pin_2y); ++err_free_1y: ++ gpio_free(pdata->gpio_pin_1y); ++err_free_s1: ++ gpio_free(pdata->gpio_pin_s1); ++err_free_s0: ++ gpio_free(pdata->gpio_pin_s0); ++err_free_nxp: ++ kfree(nxp); ++ return err; ++} ++ ++static int nxp_74hc153_remove(struct platform_device *pdev) ++{ ++ struct nxp_74hc153_chip *nxp = platform_get_drvdata(pdev); ++ struct nxp_74hc153_platform_data *pdata = pdev->dev.platform_data; ++ ++ if (nxp) { ++ gpiochip_remove(&nxp->gpio_chip); ++ gpio_free(pdata->gpio_pin_2y); ++ gpio_free(pdata->gpio_pin_1y); ++ gpio_free(pdata->gpio_pin_s1); ++ gpio_free(pdata->gpio_pin_s0); ++ ++ kfree(nxp); ++ platform_set_drvdata(pdev, NULL); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver nxp_74hc153_driver = { ++ .probe = nxp_74hc153_probe, ++ .remove = nxp_74hc153_remove, ++ .driver = { ++ .name = NXP_74HC153_DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init nxp_74hc153_init(void) ++{ ++ return platform_driver_register(&nxp_74hc153_driver); ++} ++subsys_initcall(nxp_74hc153_init); ++ ++static void __exit nxp_74hc153_exit(void) ++{ ++ platform_driver_unregister(&nxp_74hc153_driver); ++} ++module_exit(nxp_74hc153_exit); ++ ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_DESCRIPTION("GPIO expander driver for NXP 74HC153"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" NXP_74HC153_DRIVER_NAME); +diff --git a/target/linux/ar71xx/files/drivers/leds/leds-nu801.c b/target/linux/ar71xx/files/drivers/leds/leds-nu801.c +new file mode 100644 +index 0000000000..11e8927785 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/leds/leds-nu801.c +@@ -0,0 +1,396 @@ ++/* ++ * LED driver for NU801 ++ * ++ * Kevin Paul Herbert ++ * Copyright (c) 2012, Meraki, 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 ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_NAME_LENGTH 24 ++#define NUM_COLORS 3 ++ ++static const char * const led_nu801_colors[] = { "blue", "green", "red" }; ++ ++struct led_nu801_led_data { ++ struct led_classdev cdev; ++ struct led_nu801_data *controller; ++ enum led_brightness level; ++ char name[MAX_NAME_LENGTH]; ++}; ++ ++struct led_nu801_data { ++ unsigned cki; ++ unsigned sdi; ++ int lei; ++ struct delayed_work work; ++ struct led_nu801_led_data *led_chain; ++ int num_leds; ++ const char *device_name; ++ const char *name; ++ u32 ndelay; ++ atomic_t pending; ++}; ++ ++static void led_nu801_work(struct work_struct *work) ++{ ++ struct led_nu801_data *controller = ++ container_of(work, struct led_nu801_data, work.work); ++ struct led_nu801_led_data *led; ++ u16 bit; ++ u16 brightness; ++ int index; ++ ++ for (index = 0; index < controller->num_leds; index++) { ++ led = &controller->led_chain[index]; ++ brightness = led->level << 8; /* To do: gamma correction */ ++ for (bit = 0x8000; bit; bit = bit >> 1) { ++ gpio_set_value(controller->sdi, ++ (brightness & bit) != 0); ++ gpio_set_value(controller->cki, 1); ++ if (unlikely(((index == (controller->num_leds - 1)) && ++ (bit == 1) && ++ (controller->lei < 0)))) { ++ udelay(600); ++ } else { ++ ndelay(controller->ndelay); ++ } ++ gpio_set_value(controller->cki, 0); ++ ndelay(controller->ndelay); ++ } ++ } ++ if (controller->lei >= 0) { ++ gpio_set_value(controller->lei, 1); ++ ndelay(controller->ndelay); ++ gpio_set_value(controller->lei, 0); ++ } ++ atomic_set(&controller->pending, 1); ++} ++ ++static void led_nu801_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ struct led_nu801_led_data *led_dat = ++ container_of(led_cdev, struct led_nu801_led_data, cdev); ++ struct led_nu801_data *controller = led_dat->controller; ++ ++ if (led_dat->level != value) { ++ led_dat->level = value; ++ if (atomic_dec_and_test(&controller->pending)) ++ schedule_delayed_work(&led_dat->controller->work, ++ (HZ/1000) + 1); ++ } ++} ++ ++static int led_nu801_create(struct led_nu801_data *controller, ++ struct device *parent, ++ int index, ++ enum led_brightness brightness, ++#ifdef CONFIG_LEDS_TRIGGERS ++ const char *default_trigger, ++#endif ++ const char *color) ++{ ++ struct led_nu801_led_data *led = &controller->led_chain[index]; ++ int ret; ++ ++ scnprintf(led->name, sizeof(led->name), "%s:%s:%s%d", ++ controller->device_name, color, controller->name, ++ (controller->num_leds - (index + 1)) / NUM_COLORS); ++ led->cdev.name = led->name; ++ led->cdev.brightness_set = led_nu801_set; ++#ifdef CONFIG_LEDS_TRIGGERS ++ led->cdev.default_trigger = default_trigger; ++#endif ++ led->level = brightness; ++ led->controller = controller; ++ ret = led_classdev_register(parent, &led->cdev); ++ if (ret < 0) ++ goto err; ++ ++ return 0; ++ ++err: ++ kfree(led); ++ return ret; ++} ++ ++static int ++led_nu801_create_chain(const struct led_nu801_template *template, ++ struct led_nu801_data *controller, ++ struct device *parent) ++{ ++ int ret; ++ int index; ++ ++ controller->cki = template->cki; ++ controller->sdi = template->sdi; ++ controller->lei = template->lei; ++ controller->num_leds = template->num_leds * 3; ++ controller->device_name = template->device_name; ++ controller->name = template->name; ++ controller->ndelay = template->ndelay; ++ atomic_set(&controller->pending, 1); ++ ++ controller->led_chain = kzalloc(sizeof(struct led_nu801_led_data) * ++ controller->num_leds, GFP_KERNEL); ++ ++ if (!controller->led_chain) ++ return -ENOMEM; ++ ++ ret = gpio_request(controller->cki, template->name); ++ if (ret < 0) ++ goto err_free_chain; ++ ++ ret = gpio_request(controller->sdi, template->name); ++ if (ret < 0) ++ goto err_ret_cki; ++ ++ if (controller->lei >= 0) { ++ ret = gpio_request(controller->lei, template->name); ++ if (ret < 0) ++ goto err_ret_sdi; ++ ret = gpio_direction_output(controller->lei, 0); ++ if (ret < 0) ++ goto err_ret_lei; ++ } ++ ++ ret = gpio_direction_output(controller->cki, 0); ++ if (ret < 0) ++ goto err_ret_lei; ++ ++ ret = gpio_direction_output(controller->sdi, 0); ++ if (ret < 0) ++ goto err_ret_lei; ++ ++ for (index = 0; index < controller->num_leds; index++) { ++ ret = led_nu801_create(controller, parent, index, ++ template->init_brightness ++ [index % NUM_COLORS], ++#ifdef CONFIG_LEDS_TRIGGERS ++ template->default_trigger, ++#endif ++ template->led_colors[index % NUM_COLORS] ? ++ template->led_colors[index % NUM_COLORS] : ++ led_nu801_colors[index % NUM_COLORS]); ++ if (ret < 0) ++ goto err_ret_sdi; ++ } ++ ++ INIT_DELAYED_WORK(&controller->work, led_nu801_work); ++ schedule_delayed_work(&controller->work, 0); ++ ++ return 0; ++ ++err_ret_lei: ++ if (controller->lei >= 0) ++ gpio_free(controller->lei); ++err_ret_sdi: ++ gpio_free(controller->sdi); ++err_ret_cki: ++ gpio_free(controller->cki); ++err_free_chain: ++ kfree(controller->led_chain); ++ ++ return ret; ++} ++ ++static void led_nu801_delete_chain(struct led_nu801_data *controller) ++{ ++ struct led_nu801_led_data *led_chain; ++ struct led_nu801_led_data *led; ++ int index; ++ int num_leds; ++ ++ led_chain = controller->led_chain; ++ controller->led_chain = 0; ++ num_leds = controller->num_leds; ++ controller->num_leds = 0; ++ cancel_delayed_work_sync(&controller->work); ++ ++ for (index = 0; index < num_leds; index++) { ++ led = &led_chain[index]; ++ led_classdev_unregister(&led->cdev); ++ } ++ ++ gpio_free(controller->cki); ++ gpio_free(controller->sdi); ++ if (controller->lei >= 0) ++ gpio_free(controller->lei); ++ ++ kfree(led_chain); ++} ++ ++static struct led_nu801_data * ++leds_nu801_create_of(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node, *child; ++ struct led_nu801_data *controllers; ++ int count = 0, ret; ++ int i = 0; ++ ++ for_each_child_of_node(np, child) ++ count++; ++ if (!count) ++ return NULL; ++ ++ controllers = kzalloc(sizeof(struct led_nu801_data) * count, ++ GFP_KERNEL); ++ if (!controllers) ++ return NULL; ++ ++ for_each_child_of_node(np, child) { ++ const char *state; ++ struct led_nu801_template template = {}; ++ struct device_node *colors; ++ int jj; ++ ++ template.cki = of_get_named_gpio_flags(child, "cki", 0, NULL); ++ template.sdi = of_get_named_gpio_flags(child, "sdi", 0, NULL); ++ if (of_find_property(child, "lei", NULL)) { ++ template.lei = of_get_named_gpio_flags(child, "lei", ++ 0, NULL); ++ } else { ++ template.lei = -1; ++ } ++ of_property_read_u32(child, "ndelay", &template.ndelay); ++ of_property_read_u32(child, "num_leds", &template.num_leds); ++ template.name = of_get_property(child, "label", NULL) ? : ++ child->name; ++ template.default_trigger = of_get_property(child, ++ "default-trigger", NULL); ++ ++ jj = 0; ++ for_each_child_of_node(child, colors) { ++ template.led_colors[jj] = of_get_property(colors, ++ "label", NULL); ++ state = of_get_property(colors, "state", NULL); ++ if (!strncmp(state, "off", 3)) ++ template.init_brightness[jj] = LED_OFF; ++ else if (!strncmp(state, "half", 4)) ++ template.init_brightness[jj] = LED_HALF; ++ else if (!strncmp(state, "full", 4)) ++ template.init_brightness[jj] = LED_FULL; ++ jj++; ++ } ++ ++ ret = led_nu801_create_chain(&template, ++ &controllers[i], ++ &pdev->dev); ++ if (ret < 0) ++ goto err; ++ i++; ++ } ++ ++ return controllers; ++ ++err: ++ for (i = i - 1; i >= 0; i--) ++ led_nu801_delete_chain(&controllers[i]); ++ kfree(controllers); ++ return NULL; ++} ++ ++static int led_nu801_probe(struct platform_device *pdev) ++{ ++ struct led_nu801_platform_data *pdata = pdev->dev.platform_data; ++ struct led_nu801_data *controllers; ++ int i, ret = 0; ++ ++ if (!(pdata && pdata->num_controllers)) { ++ controllers = leds_nu801_create_of(pdev); ++ if (!controllers) ++ return -ENODEV; ++ } ++ ++ controllers = kzalloc(sizeof(struct led_nu801_data) * ++ pdata->num_controllers, GFP_KERNEL); ++ if (!controllers) ++ return -ENOMEM; ++ ++ for (i = 0; i < pdata->num_controllers; i++) { ++ ret = led_nu801_create_chain(&pdata->template[i], ++ &controllers[i], ++ &pdev->dev); ++ if (ret < 0) ++ goto err; ++ } ++ ++ platform_set_drvdata(pdev, controllers); ++ ++ return 0; ++ ++err: ++ for (i = i - 1; i >= 0; i--) ++ led_nu801_delete_chain(&controllers[i]); ++ ++ kfree(controllers); ++ ++ return ret; ++} ++ ++static int led_nu801_remove(struct platform_device *pdev) ++{ ++ int i; ++ struct led_nu801_platform_data *pdata = pdev->dev.platform_data; ++ struct led_nu801_data *controllers; ++ ++ controllers = platform_get_drvdata(pdev); ++ ++ for (i = 0; i < pdata->num_controllers; i++) ++ led_nu801_delete_chain(&controllers[i]); ++ ++ kfree(controllers); ++ ++ return 0; ++} ++ ++static const struct of_device_id of_numen_leds_match[] = { ++ { .compatible = "numen,leds-nu801", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, of_pwm_leds_match); ++ ++static struct platform_driver led_nu801_driver = { ++ .probe = led_nu801_probe, ++ .remove = led_nu801_remove, ++ .driver = { ++ .name = "leds-nu801", ++ .owner = THIS_MODULE, ++ .of_match_table = of_numen_leds_match, ++ }, ++}; ++ ++static int __init led_nu801_init(void) ++{ ++ return platform_driver_register(&led_nu801_driver); ++} ++ ++static void __exit led_nu801_exit(void) ++{ ++ platform_driver_unregister(&led_nu801_driver); ++} ++ ++module_init(led_nu801_init); ++module_exit(led_nu801_exit); ++ ++MODULE_AUTHOR("Kevin Paul Herbert "); ++MODULE_DESCRIPTION("NU801 LED driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:leds-nu801"); +diff --git a/target/linux/ar71xx/files/drivers/leds/leds-rb750.c b/target/linux/ar71xx/files/drivers/leds/leds-rb750.c +new file mode 100644 +index 0000000000..79e98b4882 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/leds/leds-rb750.c +@@ -0,0 +1,144 @@ ++/* ++ * LED driver for the RouterBOARD 750 ++ * ++ * Copyright (C) 2010 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. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define DRV_NAME "leds-rb750" ++ ++struct rb750_led_dev { ++ struct led_classdev cdev; ++ u32 mask; ++ int active_low; ++ void (*latch_change)(u32 clear, u32 set); ++}; ++ ++struct rb750_led_drvdata { ++ struct rb750_led_dev *led_devs; ++ int num_leds; ++}; ++ ++static inline struct rb750_led_dev *to_rbled(struct led_classdev *led_cdev) ++{ ++ return (struct rb750_led_dev *)container_of(led_cdev, ++ struct rb750_led_dev, cdev); ++} ++ ++static void rb750_led_brightness_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ struct rb750_led_dev *rbled = to_rbled(led_cdev); ++ int level; ++ ++ level = (value == LED_OFF) ? 0 : 1; ++ level ^= rbled->active_low; ++ ++ if (level) ++ rbled->latch_change(0, rbled->mask); ++ else ++ rbled->latch_change(rbled->mask, 0); ++} ++ ++static int rb750_led_probe(struct platform_device *pdev) ++{ ++ struct rb750_led_platform_data *pdata; ++ struct rb750_led_drvdata *drvdata; ++ int ret = 0; ++ int i; ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) ++ return -EINVAL; ++ ++ drvdata = kzalloc(sizeof(struct rb750_led_drvdata) + ++ sizeof(struct rb750_led_dev) * pdata->num_leds, ++ GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ drvdata->num_leds = pdata->num_leds; ++ drvdata->led_devs = (struct rb750_led_dev *) &drvdata[1]; ++ ++ for (i = 0; i < drvdata->num_leds; i++) { ++ struct rb750_led_dev *rbled = &drvdata->led_devs[i]; ++ struct rb750_led_data *led_data = &pdata->leds[i]; ++ ++ rbled->cdev.name = led_data->name; ++ rbled->cdev.default_trigger = led_data->default_trigger; ++ rbled->cdev.brightness_set = rb750_led_brightness_set; ++ rbled->cdev.brightness = LED_OFF; ++ ++ rbled->mask = led_data->mask; ++ rbled->active_low = !!led_data->active_low; ++ rbled->latch_change = pdata->latch_change; ++ ++ ret = led_classdev_register(&pdev->dev, &rbled->cdev); ++ if (ret) ++ goto err; ++ } ++ ++ platform_set_drvdata(pdev, drvdata); ++ return 0; ++ ++err: ++ for (i = i - 1; i >= 0; i--) ++ led_classdev_unregister(&drvdata->led_devs[i].cdev); ++ ++ kfree(drvdata); ++ return ret; ++} ++ ++static int rb750_led_remove(struct platform_device *pdev) ++{ ++ struct rb750_led_drvdata *drvdata; ++ int i; ++ ++ drvdata = platform_get_drvdata(pdev); ++ for (i = 0; i < drvdata->num_leds; i++) ++ led_classdev_unregister(&drvdata->led_devs[i].cdev); ++ ++ kfree(drvdata); ++ return 0; ++} ++ ++static struct platform_driver rb750_led_driver = { ++ .probe = rb750_led_probe, ++ .remove = rb750_led_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_ALIAS("platform:leds-rb750"); ++ ++static int __init rb750_led_init(void) ++{ ++ return platform_driver_register(&rb750_led_driver); ++} ++ ++static void __exit rb750_led_exit(void) ++{ ++ platform_driver_unregister(&rb750_led_driver); ++} ++ ++module_init(rb750_led_init); ++module_exit(rb750_led_exit); ++ ++MODULE_DESCRIPTION(DRV_NAME); ++MODULE_DESCRIPTION("LED driver for the RouterBOARD 750"); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c b/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c +new file mode 100644 +index 0000000000..6425b055da +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c +@@ -0,0 +1,76 @@ ++/* ++ * USB LED driver for the NETGEAR WNDR3700 ++ * ++ * Copyright (C) 2009 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. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define DRIVER_NAME "wndr3700-led-usb" ++ ++static void wndr3700_usb_led_set(struct led_classdev *cdev, ++ enum led_brightness brightness) ++{ ++ if (brightness) ++ ath79_device_reset_clear(AR71XX_RESET_GE1_PHY); ++ else ++ ath79_device_reset_set(AR71XX_RESET_GE1_PHY); ++} ++ ++static enum led_brightness wndr3700_usb_led_get(struct led_classdev *cdev) ++{ ++ return ath79_device_reset_get(AR71XX_RESET_GE1_PHY) ? LED_OFF : LED_FULL; ++} ++ ++static struct led_classdev wndr3700_usb_led = { ++ .name = "netgear:green:usb", ++ .brightness_set = wndr3700_usb_led_set, ++ .brightness_get = wndr3700_usb_led_get, ++}; ++ ++static int wndr3700_usb_led_probe(struct platform_device *pdev) ++{ ++ return led_classdev_register(&pdev->dev, &wndr3700_usb_led); ++} ++ ++static int wndr3700_usb_led_remove(struct platform_device *pdev) ++{ ++ led_classdev_unregister(&wndr3700_usb_led); ++ return 0; ++} ++ ++static struct platform_driver wndr3700_usb_led_driver = { ++ .probe = wndr3700_usb_led_probe, ++ .remove = wndr3700_usb_led_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init wndr3700_usb_led_init(void) ++{ ++ return platform_driver_register(&wndr3700_usb_led_driver); ++} ++ ++static void __exit wndr3700_usb_led_exit(void) ++{ ++ platform_driver_unregister(&wndr3700_usb_led_driver); ++} ++ ++module_init(wndr3700_usb_led_init); ++module_exit(wndr3700_usb_led_exit); ++ ++MODULE_DESCRIPTION("USB LED driver for the NETGEAR WNDR3700"); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRIVER_NAME); +diff --git a/target/linux/ar71xx/files/drivers/mtd/cybertan_part.c b/target/linux/ar71xx/files/drivers/mtd/cybertan_part.c +new file mode 100644 +index 0000000000..4d33c19b7e +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/mtd/cybertan_part.c +@@ -0,0 +1,206 @@ ++/* ++ * Copyright (C) 2009 Christian Daniel ++ * Copyright (C) 2009 Gabor Juhos ++ * ++ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ * TRX flash partition table. ++ * Based on ar7 map by Felix Fietkau ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++struct cybertan_header { ++ char magic[4]; ++ u8 res1[4]; ++ char fw_date[3]; ++ char fw_ver[3]; ++ char id[4]; ++ char hw_ver; ++ char unused; ++ u8 flags[2]; ++ u8 res2[10]; ++}; ++ ++#define TRX_PARTS 6 ++#define TRX_MAGIC 0x30524448 ++#define TRX_MAX_OFFSET 3 ++ ++struct trx_header { ++ uint32_t magic; /* "HDR0" */ ++ uint32_t len; /* Length of file including header */ ++ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ ++ uint32_t flag_version; /* 0:15 flags, 16:31 version */ ++ uint32_t offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ ++}; ++ ++#define IH_MAGIC 0x27051956 /* Image Magic Number */ ++#define IH_NMLEN 32 /* Image Name Length */ ++ ++struct uimage_header { ++ uint32_t ih_magic; /* Image Header Magic Number */ ++ uint32_t ih_hcrc; /* Image Header CRC Checksum */ ++ uint32_t ih_time; /* Image Creation Timestamp */ ++ uint32_t ih_size; /* Image Data Size */ ++ uint32_t ih_load; /* Data» Load Address */ ++ uint32_t ih_ep; /* Entry Point Address */ ++ uint32_t ih_dcrc; /* Image Data CRC Checksum */ ++ uint8_t ih_os; /* Operating System */ ++ uint8_t ih_arch; /* CPU architecture */ ++ uint8_t ih_type; /* Image Type */ ++ uint8_t ih_comp; /* Compression Type */ ++ uint8_t ih_name[IH_NMLEN]; /* Image Name */ ++}; ++ ++struct firmware_header { ++ struct cybertan_header cybertan; ++ struct trx_header trx; ++ struct uimage_header uimage; ++} __packed; ++ ++#define UBOOT_LEN 0x40000 ++#define ART_LEN 0x10000 ++#define NVRAM_LEN 0x10000 ++ ++static int cybertan_parse_partitions(struct mtd_info *master, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ struct mtd_partition **pparts, ++#else ++ const struct mtd_partition **pparts, ++#endif ++ struct mtd_part_parser_data *data) ++{ ++ struct firmware_header *header; ++ struct trx_header *theader; ++ struct uimage_header *uheader; ++ struct mtd_partition *trx_parts; ++ size_t retlen; ++ unsigned int kernel_len; ++ unsigned int uboot_len; ++ unsigned int nvram_len; ++ unsigned int art_len; ++ int ret; ++ ++ uboot_len = max_t(unsigned int, master->erasesize, UBOOT_LEN); ++ nvram_len = max_t(unsigned int, master->erasesize, NVRAM_LEN); ++ art_len = max_t(unsigned int, master->erasesize, ART_LEN); ++ ++ trx_parts = kzalloc(TRX_PARTS * sizeof(struct mtd_partition), ++ GFP_KERNEL); ++ if (!trx_parts) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ header = vmalloc(sizeof(*header)); ++ if (!header) { ++ return -ENOMEM; ++ goto free_parts; ++ } ++ ++ ret = mtd_read(master, uboot_len, sizeof(*header), ++ &retlen, (void *) header); ++ if (ret) ++ goto free_hdr; ++ ++ if (retlen != sizeof(*header)) { ++ ret = -EIO; ++ goto free_hdr; ++ } ++ ++ theader = &header->trx; ++ if (le32_to_cpu(theader->magic) != TRX_MAGIC) { ++ printk(KERN_NOTICE "%s: no TRX header found\n", master->name); ++ goto free_hdr; ++ } ++ ++ uheader = &header->uimage; ++ if (uheader->ih_magic != IH_MAGIC) { ++ printk(KERN_NOTICE "%s: no uImage found\n", master->name); ++ goto free_hdr; ++ } ++ ++ kernel_len = le32_to_cpu(theader->offsets[1]) + ++ sizeof(struct cybertan_header); ++ ++ trx_parts[0].name = "u-boot"; ++ trx_parts[0].offset = 0; ++ trx_parts[0].size = uboot_len; ++ trx_parts[0].mask_flags = MTD_WRITEABLE; ++ ++ trx_parts[1].name = "kernel"; ++ trx_parts[1].offset = trx_parts[0].offset + trx_parts[0].size; ++ trx_parts[1].size = kernel_len; ++ trx_parts[1].mask_flags = 0; ++ ++ trx_parts[2].name = "rootfs"; ++ trx_parts[2].offset = trx_parts[1].offset + trx_parts[1].size; ++ trx_parts[2].size = master->size - uboot_len - nvram_len - art_len - ++ trx_parts[1].size; ++ trx_parts[2].mask_flags = 0; ++ ++ trx_parts[3].name = "nvram"; ++ trx_parts[3].offset = master->size - nvram_len - art_len; ++ trx_parts[3].size = nvram_len; ++ trx_parts[3].mask_flags = MTD_WRITEABLE; ++ ++ trx_parts[4].name = "art"; ++ trx_parts[4].offset = master->size - art_len; ++ trx_parts[4].size = art_len; ++ trx_parts[4].mask_flags = MTD_WRITEABLE; ++ ++ trx_parts[5].name = "firmware"; ++ trx_parts[5].offset = uboot_len; ++ trx_parts[5].size = master->size - uboot_len - nvram_len - art_len; ++ trx_parts[5].mask_flags = 0; ++ ++ vfree(header); ++ ++ *pparts = trx_parts; ++ return TRX_PARTS; ++ ++free_hdr: ++ vfree(header); ++free_parts: ++ kfree(trx_parts); ++out: ++ return ret; ++} ++ ++static struct mtd_part_parser cybertan_parser = { ++ .owner = THIS_MODULE, ++ .parse_fn = cybertan_parse_partitions, ++ .name = "cybertan", ++}; ++ ++static int __init cybertan_parser_init(void) ++{ ++ register_mtd_parser(&cybertan_parser); ++ ++ return 0; ++} ++ ++module_init(cybertan_parser_init); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Christian Daniel "); +diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c b/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c +new file mode 100644 +index 0000000000..2e25c6b885 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c +@@ -0,0 +1,1591 @@ ++/* ++ * Driver for the built-in NAND controller of the Atheros AR934x SoCs ++ * ++ * Copyright (C) 2011-2013 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define AR934X_NFC_REG_CMD 0x00 ++#define AR934X_NFC_REG_CTRL 0x04 ++#define AR934X_NFC_REG_STATUS 0x08 ++#define AR934X_NFC_REG_INT_MASK 0x0c ++#define AR934X_NFC_REG_INT_STATUS 0x10 ++#define AR934X_NFC_REG_ECC_CTRL 0x14 ++#define AR934X_NFC_REG_ECC_OFFSET 0x18 ++#define AR934X_NFC_REG_ADDR0_0 0x1c ++#define AR934X_NFC_REG_ADDR0_1 0x24 ++#define AR934X_NFC_REG_ADDR1_0 0x20 ++#define AR934X_NFC_REG_ADDR1_1 0x28 ++#define AR934X_NFC_REG_SPARE_SIZE 0x30 ++#define AR934X_NFC_REG_PROTECT 0x38 ++#define AR934X_NFC_REG_LOOKUP_EN 0x40 ++#define AR934X_NFC_REG_LOOKUP(_x) (0x44 + (_i) * 4) ++#define AR934X_NFC_REG_DMA_ADDR 0x64 ++#define AR934X_NFC_REG_DMA_COUNT 0x68 ++#define AR934X_NFC_REG_DMA_CTRL 0x6c ++#define AR934X_NFC_REG_MEM_CTRL 0x80 ++#define AR934X_NFC_REG_DATA_SIZE 0x84 ++#define AR934X_NFC_REG_READ_STATUS 0x88 ++#define AR934X_NFC_REG_TIME_SEQ 0x8c ++#define AR934X_NFC_REG_TIMINGS_ASYN 0x90 ++#define AR934X_NFC_REG_TIMINGS_SYN 0x94 ++#define AR934X_NFC_REG_FIFO_DATA 0x98 ++#define AR934X_NFC_REG_TIME_MODE 0x9c ++#define AR934X_NFC_REG_DMA_ADDR_OFFS 0xa0 ++#define AR934X_NFC_REG_FIFO_INIT 0xb0 ++#define AR934X_NFC_REG_GEN_SEQ_CTRL 0xb4 ++ ++#define AR934X_NFC_CMD_CMD_SEQ_S 0 ++#define AR934X_NFC_CMD_CMD_SEQ_M 0x3f ++#define AR934X_NFC_CMD_SEQ_1C 0x00 ++#define AR934X_NFC_CMD_SEQ_ERASE 0x0e ++#define AR934X_NFC_CMD_SEQ_12 0x0c ++#define AR934X_NFC_CMD_SEQ_1C1AXR 0x21 ++#define AR934X_NFC_CMD_SEQ_S 0x24 ++#define AR934X_NFC_CMD_SEQ_1C3AXR 0x27 ++#define AR934X_NFC_CMD_SEQ_1C5A1CXR 0x2a ++#define AR934X_NFC_CMD_SEQ_18 0x32 ++#define AR934X_NFC_CMD_INPUT_SEL_SIU 0 ++#define AR934X_NFC_CMD_INPUT_SEL_DMA BIT(6) ++#define AR934X_NFC_CMD_ADDR_SEL_0 0 ++#define AR934X_NFC_CMD_ADDR_SEL_1 BIT(7) ++#define AR934X_NFC_CMD_CMD0_S 8 ++#define AR934X_NFC_CMD_CMD0_M 0xff ++#define AR934X_NFC_CMD_CMD1_S 16 ++#define AR934X_NFC_CMD_CMD1_M 0xff ++#define AR934X_NFC_CMD_CMD2_S 24 ++#define AR934X_NFC_CMD_CMD2_M 0xff ++ ++#define AR934X_NFC_CTRL_ADDR_CYCLE0_M 0x7 ++#define AR934X_NFC_CTRL_ADDR_CYCLE0_S 0 ++#define AR934X_NFC_CTRL_SPARE_EN BIT(3) ++#define AR934X_NFC_CTRL_INT_EN BIT(4) ++#define AR934X_NFC_CTRL_ECC_EN BIT(5) ++#define AR934X_NFC_CTRL_BLOCK_SIZE_S 6 ++#define AR934X_NFC_CTRL_BLOCK_SIZE_M 0x3 ++#define AR934X_NFC_CTRL_BLOCK_SIZE_32 0 ++#define AR934X_NFC_CTRL_BLOCK_SIZE_64 1 ++#define AR934X_NFC_CTRL_BLOCK_SIZE_128 2 ++#define AR934X_NFC_CTRL_BLOCK_SIZE_256 3 ++#define AR934X_NFC_CTRL_PAGE_SIZE_S 8 ++#define AR934X_NFC_CTRL_PAGE_SIZE_M 0x7 ++#define AR934X_NFC_CTRL_PAGE_SIZE_256 0 ++#define AR934X_NFC_CTRL_PAGE_SIZE_512 1 ++#define AR934X_NFC_CTRL_PAGE_SIZE_1024 2 ++#define AR934X_NFC_CTRL_PAGE_SIZE_2048 3 ++#define AR934X_NFC_CTRL_PAGE_SIZE_4096 4 ++#define AR934X_NFC_CTRL_PAGE_SIZE_8192 5 ++#define AR934X_NFC_CTRL_PAGE_SIZE_16384 6 ++#define AR934X_NFC_CTRL_CUSTOM_SIZE_EN BIT(11) ++#define AR934X_NFC_CTRL_IO_WIDTH_8BITS 0 ++#define AR934X_NFC_CTRL_IO_WIDTH_16BITS BIT(12) ++#define AR934X_NFC_CTRL_LOOKUP_EN BIT(13) ++#define AR934X_NFC_CTRL_PROT_EN BIT(14) ++#define AR934X_NFC_CTRL_WORK_MODE_ASYNC 0 ++#define AR934X_NFC_CTRL_WORK_MODE_SYNC BIT(15) ++#define AR934X_NFC_CTRL_ADDR0_AUTO_INC BIT(16) ++#define AR934X_NFC_CTRL_ADDR1_AUTO_INC BIT(17) ++#define AR934X_NFC_CTRL_ADDR_CYCLE1_M 0x7 ++#define AR934X_NFC_CTRL_ADDR_CYCLE1_S 18 ++#define AR934X_NFC_CTRL_SMALL_PAGE BIT(21) ++ ++#define AR934X_NFC_DMA_CTRL_DMA_START BIT(7) ++#define AR934X_NFC_DMA_CTRL_DMA_DIR_WRITE 0 ++#define AR934X_NFC_DMA_CTRL_DMA_DIR_READ BIT(6) ++#define AR934X_NFC_DMA_CTRL_DMA_MODE_SG BIT(5) ++#define AR934X_NFC_DMA_CTRL_DMA_BURST_S 2 ++#define AR934X_NFC_DMA_CTRL_DMA_BURST_0 0 ++#define AR934X_NFC_DMA_CTRL_DMA_BURST_1 1 ++#define AR934X_NFC_DMA_CTRL_DMA_BURST_2 2 ++#define AR934X_NFC_DMA_CTRL_DMA_BURST_3 3 ++#define AR934X_NFC_DMA_CTRL_DMA_BURST_4 4 ++#define AR934X_NFC_DMA_CTRL_DMA_BURST_5 5 ++#define AR934X_NFC_DMA_CTRL_ERR_FLAG BIT(1) ++#define AR934X_NFC_DMA_CTRL_DMA_READY BIT(0) ++ ++#define AR934X_NFC_INT_DEV_RDY(_x) BIT(4 + (_x)) ++#define AR934X_NFC_INT_CMD_END BIT(1) ++ ++#define AR934X_NFC_ECC_CTRL_ERR_THRES_S 8 ++#define AR934X_NFC_ECC_CTRL_ERR_THRES_M 0x1f ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_S 5 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_M 0x7 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_2 0 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_4 1 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_6 2 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_8 3 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_10 4 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_12 5 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_14 6 ++#define AR934X_NFC_ECC_CTRL_ECC_CAP_16 7 ++#define AR934X_NFC_ECC_CTRL_ERR_OVER BIT(2) ++#define AR934X_NFC_ECC_CTRL_ERR_UNCORRECT BIT(1) ++#define AR934X_NFC_ECC_CTRL_ERR_CORRECT BIT(0) ++ ++#define AR934X_NFC_ECC_OFFS_OFSET_M 0xffff ++ ++/* default timing values */ ++#define AR934X_NFC_TIME_SEQ_DEFAULT 0x7fff ++#define AR934X_NFC_TIMINGS_ASYN_DEFAULT 0x22 ++#define AR934X_NFC_TIMINGS_SYN_DEFAULT 0xf ++ ++#define AR934X_NFC_ID_BUF_SIZE 8 ++#define AR934X_NFC_DEV_READY_TIMEOUT 25 /* msecs */ ++#define AR934X_NFC_DMA_READY_TIMEOUT 25 /* msecs */ ++#define AR934X_NFC_DONE_TIMEOUT 1000 ++#define AR934X_NFC_DMA_RETRIES 20 ++ ++#define AR934X_NFC_USE_IRQ true ++#define AR934X_NFC_IRQ_MASK AR934X_NFC_INT_DEV_RDY(0) ++ ++#define AR934X_NFC_GENSEQ_SMALL_PAGE_READ 0x30043 ++ ++#undef AR934X_NFC_DEBUG_DATA ++#undef AR934X_NFC_DEBUG ++ ++struct ar934x_nfc; ++ ++static inline __attribute__ ((format (printf, 2, 3))) ++void _nfc_dbg(struct ar934x_nfc *nfc, const char *fmt, ...) ++{ ++} ++ ++#ifdef AR934X_NFC_DEBUG ++#define nfc_dbg(_nfc, fmt, ...) \ ++ dev_info((_nfc)->parent, fmt, ##__VA_ARGS__) ++#else ++#define nfc_dbg(_nfc, fmt, ...) \ ++ _nfc_dbg((_nfc), fmt, ##__VA_ARGS__) ++#endif /* AR934X_NFC_DEBUG */ ++ ++#ifdef AR934X_NFC_DEBUG_DATA ++static void ++nfc_debug_data(const char *label, void *data, int len) ++{ ++ print_hex_dump(KERN_WARNING, label, DUMP_PREFIX_OFFSET, 16, 1, ++ data, len, 0); ++} ++#else ++static inline void ++nfc_debug_data(const char *label, void *data, int len) {} ++#endif /* AR934X_NFC_DEBUG_DATA */ ++ ++struct ar934x_nfc { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct mtd_info mtd; ++#endif ++ struct nand_chip nand_chip; ++ struct device *parent; ++ void __iomem *base; ++ void (*select_chip)(int chip_no); ++ bool swap_dma; ++ int irq; ++ wait_queue_head_t irq_waitq; ++ ++ bool spurious_irq_expected; ++ u32 irq_status; ++ ++ u32 ctrl_reg; ++ u32 ecc_ctrl_reg; ++ u32 ecc_offset_reg; ++ u32 ecc_thres; ++ u32 ecc_oob_pos; ++ ++ bool small_page; ++ unsigned int addr_count0; ++ unsigned int addr_count1; ++ ++ u8 *buf; ++ dma_addr_t buf_dma; ++ unsigned int buf_size; ++ int buf_index; ++ ++ bool read_id; ++ ++ int erase1_page_addr; ++ ++ int rndout_page_addr; ++ int rndout_read_cmd; ++ ++ int seqin_page_addr; ++ int seqin_column; ++ int seqin_read_cmd; ++}; ++ ++static void ar934x_nfc_restart(struct ar934x_nfc *nfc); ++ ++static inline bool ++is_all_ff(u8 *buf, int len) ++{ ++ while (len--) ++ if (buf[len] != 0xff) ++ return false; ++ ++ return true; ++} ++ ++static inline void ++ar934x_nfc_wr(struct ar934x_nfc *nfc, unsigned reg, u32 val) ++{ ++ __raw_writel(val, nfc->base + reg); ++} ++ ++static inline u32 ++ar934x_nfc_rr(struct ar934x_nfc *nfc, unsigned reg) ++{ ++ return __raw_readl(nfc->base + reg); ++} ++ ++static inline struct ar934x_nfc_platform_data * ++ar934x_nfc_get_platform_data(struct ar934x_nfc *nfc) ++{ ++ return nfc->parent->platform_data; ++} ++ ++static inline struct ++ar934x_nfc *mtd_to_ar934x_nfc(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ return container_of(mtd, struct ar934x_nfc, mtd); ++#else ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ ++ return container_of(chip, struct ar934x_nfc, nand_chip); ++#endif ++} ++ ++static struct mtd_info *ar934x_nfc_to_mtd(struct ar934x_nfc *nfc) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ return &nfc->mtd; ++#else ++ return nand_to_mtd(&nfc->nand_chip); ++#endif ++} ++ ++static inline bool ar934x_nfc_use_irq(struct ar934x_nfc *nfc) ++{ ++ return AR934X_NFC_USE_IRQ; ++} ++ ++static inline void ar934x_nfc_write_cmd_reg(struct ar934x_nfc *nfc, u32 cmd_reg) ++{ ++ wmb(); ++ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_CMD, cmd_reg); ++ /* flush write */ ++ ar934x_nfc_rr(nfc, AR934X_NFC_REG_CMD); ++} ++ ++static bool ++__ar934x_nfc_dev_ready(struct ar934x_nfc *nfc) ++{ ++ u32 status; ++ ++ status = ar934x_nfc_rr(nfc, AR934X_NFC_REG_STATUS); ++ return (status & 0xff) == 0xff; ++} ++ ++static inline bool ++__ar934x_nfc_is_dma_ready(struct ar934x_nfc *nfc) ++{ ++ u32 status; ++ ++ status = ar934x_nfc_rr(nfc, AR934X_NFC_REG_DMA_CTRL); ++ return (status & AR934X_NFC_DMA_CTRL_DMA_READY) != 0; ++} ++ ++static int ++ar934x_nfc_wait_dev_ready(struct ar934x_nfc *nfc) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies + msecs_to_jiffies(AR934X_NFC_DEV_READY_TIMEOUT); ++ do { ++ if (__ar934x_nfc_dev_ready(nfc)) ++ return 0; ++ } while time_before(jiffies, timeout); ++ ++ nfc_dbg(nfc, "timeout waiting for device ready, status:%08x int:%08x\n", ++ ar934x_nfc_rr(nfc, AR934X_NFC_REG_STATUS), ++ ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_STATUS)); ++ return -ETIMEDOUT; ++} ++ ++static int ++ar934x_nfc_wait_dma_ready(struct ar934x_nfc *nfc) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies + msecs_to_jiffies(AR934X_NFC_DMA_READY_TIMEOUT); ++ do { ++ if (__ar934x_nfc_is_dma_ready(nfc)) ++ return 0; ++ } while time_before(jiffies, timeout); ++ ++ nfc_dbg(nfc, "timeout waiting for DMA ready, dma_ctrl:%08x\n", ++ ar934x_nfc_rr(nfc, AR934X_NFC_REG_DMA_CTRL)); ++ return -ETIMEDOUT; ++} ++ ++static int ++ar934x_nfc_wait_irq(struct ar934x_nfc *nfc) ++{ ++ long timeout; ++ int ret; ++ ++ timeout = wait_event_timeout(nfc->irq_waitq, ++ (nfc->irq_status & AR934X_NFC_IRQ_MASK) != 0, ++ msecs_to_jiffies(AR934X_NFC_DEV_READY_TIMEOUT)); ++ ++ ret = 0; ++ if (!timeout) { ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_MASK, 0); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); ++ /* flush write */ ++ ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_STATUS); ++ ++ nfc_dbg(nfc, ++ "timeout waiting for interrupt, status:%08x\n", ++ nfc->irq_status); ++ ret = -ETIMEDOUT; ++ } ++ ++ nfc->irq_status = 0; ++ return ret; ++} ++ ++static int ++ar934x_nfc_wait_done(struct ar934x_nfc *nfc) ++{ ++ int ret; ++ ++ if (ar934x_nfc_use_irq(nfc)) ++ ret = ar934x_nfc_wait_irq(nfc); ++ else ++ ret = ar934x_nfc_wait_dev_ready(nfc); ++ ++ if (ret) ++ return ret; ++ ++ return ar934x_nfc_wait_dma_ready(nfc); ++} ++ ++static int ++ar934x_nfc_alloc_buf(struct ar934x_nfc *nfc, unsigned size) ++{ ++ nfc->buf = dma_alloc_coherent(nfc->parent, size, ++ &nfc->buf_dma, GFP_KERNEL); ++ if (nfc->buf == NULL) { ++ dev_err(nfc->parent, "no memory for DMA buffer\n"); ++ return -ENOMEM; ++ } ++ ++ nfc->buf_size = size; ++ nfc_dbg(nfc, "buf:%p size:%u\n", nfc->buf, nfc->buf_size); ++ ++ return 0; ++} ++ ++static void ++ar934x_nfc_free_buf(struct ar934x_nfc *nfc) ++{ ++ dma_free_coherent(nfc->parent, nfc->buf_size, nfc->buf, nfc->buf_dma); ++} ++ ++static void ++ar934x_nfc_get_addr(struct ar934x_nfc *nfc, int column, int page_addr, ++ u32 *addr0, u32 *addr1) ++{ ++ u32 a0, a1; ++ ++ a0 = 0; ++ a1 = 0; ++ ++ if (column == -1) { ++ /* ERASE1 */ ++ a0 = (page_addr & 0xffff) << 16; ++ a1 = (page_addr >> 16) & 0xf; ++ } else if (page_addr != -1) { ++ /* SEQIN, READ0, etc.. */ ++ ++ /* TODO: handle 16bit bus width */ ++ if (nfc->small_page) { ++ a0 = column & 0xff; ++ a0 |= (page_addr & 0xff) << 8; ++ a0 |= ((page_addr >> 8) & 0xff) << 16; ++ a0 |= ((page_addr >> 16) & 0xff) << 24; ++ } else { ++ a0 = column & 0x0FFF; ++ a0 |= (page_addr & 0xffff) << 16; ++ ++ if (nfc->addr_count0 > 4) ++ a1 = (page_addr >> 16) & 0xf; ++ } ++ } ++ ++ *addr0 = a0; ++ *addr1 = a1; ++} ++ ++static void ++ar934x_nfc_send_cmd(struct ar934x_nfc *nfc, unsigned command) ++{ ++ u32 cmd_reg; ++ ++ cmd_reg = AR934X_NFC_CMD_INPUT_SEL_SIU | AR934X_NFC_CMD_ADDR_SEL_0 | ++ AR934X_NFC_CMD_SEQ_1C; ++ cmd_reg |= (command & AR934X_NFC_CMD_CMD0_M) << AR934X_NFC_CMD_CMD0_S; ++ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, nfc->ctrl_reg); ++ ++ ar934x_nfc_write_cmd_reg(nfc, cmd_reg); ++ ar934x_nfc_wait_dev_ready(nfc); ++} ++ ++static int ++ar934x_nfc_do_rw_command(struct ar934x_nfc *nfc, int column, int page_addr, ++ int len, u32 cmd_reg, u32 ctrl_reg, bool write) ++{ ++ u32 addr0, addr1; ++ u32 dma_ctrl; ++ int dir; ++ int err; ++ int retries = 0; ++ ++ WARN_ON(len & 3); ++ ++ if (WARN_ON(len > nfc->buf_size)) ++ dev_err(nfc->parent, "len=%d > buf_size=%d", len, nfc->buf_size); ++ ++ if (write) { ++ dma_ctrl = AR934X_NFC_DMA_CTRL_DMA_DIR_WRITE; ++ dir = DMA_TO_DEVICE; ++ } else { ++ dma_ctrl = AR934X_NFC_DMA_CTRL_DMA_DIR_READ; ++ dir = DMA_FROM_DEVICE; ++ } ++ ++ ar934x_nfc_get_addr(nfc, column, page_addr, &addr0, &addr1); ++ ++ dma_ctrl |= AR934X_NFC_DMA_CTRL_DMA_START | ++ (AR934X_NFC_DMA_CTRL_DMA_BURST_3 << ++ AR934X_NFC_DMA_CTRL_DMA_BURST_S); ++ ++ cmd_reg |= AR934X_NFC_CMD_INPUT_SEL_DMA | AR934X_NFC_CMD_ADDR_SEL_0; ++ ctrl_reg |= AR934X_NFC_CTRL_INT_EN; ++ ++ nfc_dbg(nfc, "%s a0:%08x a1:%08x len:%x cmd:%08x dma:%08x ctrl:%08x\n", ++ (write) ? "write" : "read", ++ addr0, addr1, len, cmd_reg, dma_ctrl, ctrl_reg); ++ ++retry: ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_ADDR0_0, addr0); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_ADDR0_1, addr1); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_DMA_ADDR, nfc->buf_dma); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_DMA_COUNT, len); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_DATA_SIZE, len); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, ctrl_reg); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_DMA_CTRL, dma_ctrl); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_ECC_CTRL, nfc->ecc_ctrl_reg); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_ECC_OFFSET, nfc->ecc_offset_reg); ++ ++ if (ar934x_nfc_use_irq(nfc)) { ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_MASK, AR934X_NFC_IRQ_MASK); ++ /* flush write */ ++ ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_MASK); ++ } ++ ++ ar934x_nfc_write_cmd_reg(nfc, cmd_reg); ++ err = ar934x_nfc_wait_done(nfc); ++ if (err) { ++ dev_dbg(nfc->parent, "%s operation stuck at page %d\n", ++ (write) ? "write" : "read", page_addr); ++ ++ ar934x_nfc_restart(nfc); ++ if (retries++ < AR934X_NFC_DMA_RETRIES) ++ goto retry; ++ ++ dev_err(nfc->parent, "%s operation failed on page %d\n", ++ (write) ? "write" : "read", page_addr); ++ } ++ ++ return err; ++} ++ ++static int ++ar934x_nfc_send_readid(struct ar934x_nfc *nfc, unsigned command) ++{ ++ u32 cmd_reg; ++ int err; ++ ++ nfc_dbg(nfc, "readid, cmd:%02x\n", command); ++ ++ cmd_reg = AR934X_NFC_CMD_SEQ_1C1AXR; ++ cmd_reg |= (command & AR934X_NFC_CMD_CMD0_M) << AR934X_NFC_CMD_CMD0_S; ++ ++ err = ar934x_nfc_do_rw_command(nfc, -1, -1, AR934X_NFC_ID_BUF_SIZE, ++ cmd_reg, nfc->ctrl_reg, false); ++ ++ nfc_debug_data("[id] ", nfc->buf, AR934X_NFC_ID_BUF_SIZE); ++ ++ return err; ++} ++ ++static int ++ar934x_nfc_send_read(struct ar934x_nfc *nfc, unsigned command, int column, ++ int page_addr, int len) ++{ ++ u32 cmd_reg; ++ int err; ++ ++ nfc_dbg(nfc, "read, column=%d page=%d len=%d\n", ++ column, page_addr, len); ++ ++ cmd_reg = (command & AR934X_NFC_CMD_CMD0_M) << AR934X_NFC_CMD_CMD0_S; ++ ++ if (nfc->small_page) { ++ cmd_reg |= AR934X_NFC_CMD_SEQ_18; ++ } else { ++ cmd_reg |= NAND_CMD_READSTART << AR934X_NFC_CMD_CMD1_S; ++ cmd_reg |= AR934X_NFC_CMD_SEQ_1C5A1CXR; ++ } ++ ++ err = ar934x_nfc_do_rw_command(nfc, column, page_addr, len, ++ cmd_reg, nfc->ctrl_reg, false); ++ ++ nfc_debug_data("[data] ", nfc->buf, len); ++ ++ return err; ++} ++ ++static void ++ar934x_nfc_send_erase(struct ar934x_nfc *nfc, unsigned command, int column, ++ int page_addr) ++{ ++ u32 addr0, addr1; ++ u32 ctrl_reg; ++ u32 cmd_reg; ++ ++ ar934x_nfc_get_addr(nfc, column, page_addr, &addr0, &addr1); ++ ++ ctrl_reg = nfc->ctrl_reg; ++ if (nfc->small_page) { ++ /* override number of address cycles for the erase command */ ++ ctrl_reg &= ~(AR934X_NFC_CTRL_ADDR_CYCLE0_M << ++ AR934X_NFC_CTRL_ADDR_CYCLE0_S); ++ ctrl_reg &= ~(AR934X_NFC_CTRL_ADDR_CYCLE1_M << ++ AR934X_NFC_CTRL_ADDR_CYCLE1_S); ++ ctrl_reg &= ~(AR934X_NFC_CTRL_SMALL_PAGE); ++ ctrl_reg |= (nfc->addr_count0 + 1) << ++ AR934X_NFC_CTRL_ADDR_CYCLE0_S; ++ } ++ ++ cmd_reg = NAND_CMD_ERASE1 << AR934X_NFC_CMD_CMD0_S; ++ cmd_reg |= command << AR934X_NFC_CMD_CMD1_S; ++ cmd_reg |= AR934X_NFC_CMD_SEQ_ERASE; ++ ++ nfc_dbg(nfc, "erase page %d, a0:%08x a1:%08x cmd:%08x ctrl:%08x\n", ++ page_addr, addr0, addr1, cmd_reg, ctrl_reg); ++ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, ctrl_reg); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_ADDR0_0, addr0); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_ADDR0_1, addr1); ++ ++ ar934x_nfc_write_cmd_reg(nfc, cmd_reg); ++ ar934x_nfc_wait_dev_ready(nfc); ++} ++ ++static int ++ar934x_nfc_send_write(struct ar934x_nfc *nfc, unsigned command, int column, ++ int page_addr, int len) ++{ ++ u32 cmd_reg; ++ ++ nfc_dbg(nfc, "write, column=%d page=%d len=%d\n", ++ column, page_addr, len); ++ ++ nfc_debug_data("[data] ", nfc->buf, len); ++ ++ cmd_reg = NAND_CMD_SEQIN << AR934X_NFC_CMD_CMD0_S; ++ cmd_reg |= command << AR934X_NFC_CMD_CMD1_S; ++ cmd_reg |= AR934X_NFC_CMD_SEQ_12; ++ ++ return ar934x_nfc_do_rw_command(nfc, column, page_addr, len, ++ cmd_reg, nfc->ctrl_reg, true); ++} ++ ++static void ++ar934x_nfc_read_status(struct ar934x_nfc *nfc) ++{ ++ u32 cmd_reg; ++ u32 status; ++ ++ cmd_reg = NAND_CMD_STATUS << AR934X_NFC_CMD_CMD0_S; ++ cmd_reg |= AR934X_NFC_CMD_SEQ_S; ++ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, nfc->ctrl_reg); ++ ++ ar934x_nfc_write_cmd_reg(nfc, cmd_reg); ++ ar934x_nfc_wait_dev_ready(nfc); ++ ++ status = ar934x_nfc_rr(nfc, AR934X_NFC_REG_READ_STATUS); ++ ++ nfc_dbg(nfc, "read status, cmd:%08x status:%02x\n", ++ cmd_reg, (status & 0xff)); ++ ++ if (nfc->swap_dma) ++ nfc->buf[0 ^ 3] = status; ++ else ++ nfc->buf[0] = status; ++} ++ ++static void ++ar934x_nfc_cmdfunc(struct mtd_info *mtd, unsigned int command, int column, ++ int page_addr) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ struct nand_chip *nand = &nfc->nand_chip; ++ ++ nfc->read_id = false; ++ if (command != NAND_CMD_PAGEPROG) ++ nfc->buf_index = 0; ++ ++ switch (command) { ++ case NAND_CMD_RESET: ++ ar934x_nfc_send_cmd(nfc, command); ++ break; ++ ++ case NAND_CMD_READID: ++ nfc->read_id = true; ++ ar934x_nfc_send_readid(nfc, command); ++ break; ++ ++ case NAND_CMD_READ0: ++ case NAND_CMD_READ1: ++ if (nfc->small_page) { ++ ar934x_nfc_send_read(nfc, command, column, page_addr, ++ mtd->writesize + mtd->oobsize); ++ } else { ++ ar934x_nfc_send_read(nfc, command, 0, page_addr, ++ mtd->writesize + mtd->oobsize); ++ nfc->buf_index = column; ++ nfc->rndout_page_addr = page_addr; ++ nfc->rndout_read_cmd = command; ++ } ++ break; ++ ++ case NAND_CMD_READOOB: ++ if (nfc->small_page) ++ ar934x_nfc_send_read(nfc, NAND_CMD_READOOB, ++ column, page_addr, ++ mtd->oobsize); ++ else ++ ar934x_nfc_send_read(nfc, NAND_CMD_READ0, ++ mtd->writesize, page_addr, ++ mtd->oobsize); ++ break; ++ ++ case NAND_CMD_RNDOUT: ++ if (WARN_ON(nfc->small_page)) ++ break; ++ ++ /* emulate subpage read */ ++ ar934x_nfc_send_read(nfc, nfc->rndout_read_cmd, 0, ++ nfc->rndout_page_addr, ++ mtd->writesize + mtd->oobsize); ++ nfc->buf_index = column; ++ break; ++ ++ case NAND_CMD_ERASE1: ++ nfc->erase1_page_addr = page_addr; ++ break; ++ ++ case NAND_CMD_ERASE2: ++ ar934x_nfc_send_erase(nfc, command, -1, nfc->erase1_page_addr); ++ break; ++ ++ case NAND_CMD_STATUS: ++ ar934x_nfc_read_status(nfc); ++ break; ++ ++ case NAND_CMD_SEQIN: ++ if (nfc->small_page) { ++ /* output read command */ ++ if (column >= mtd->writesize) { ++ column -= mtd->writesize; ++ nfc->seqin_read_cmd = NAND_CMD_READOOB; ++ } else if (column < 256) { ++ nfc->seqin_read_cmd = NAND_CMD_READ0; ++ } else { ++ column -= 256; ++ nfc->seqin_read_cmd = NAND_CMD_READ1; ++ } ++ } else { ++ nfc->seqin_read_cmd = NAND_CMD_READ0; ++ } ++ nfc->seqin_column = column; ++ nfc->seqin_page_addr = page_addr; ++ break; ++ ++ case NAND_CMD_PAGEPROG: ++ if (nand->ecc.mode == NAND_ECC_HW) { ++ /* the data is already written */ ++ break; ++ } ++ ++ if (nfc->small_page) ++ ar934x_nfc_send_cmd(nfc, nfc->seqin_read_cmd); ++ ++ ar934x_nfc_send_write(nfc, command, nfc->seqin_column, ++ nfc->seqin_page_addr, ++ nfc->buf_index); ++ break; ++ ++ default: ++ dev_err(nfc->parent, ++ "unsupported command: %x, column:%d page_addr=%d\n", ++ command, column, page_addr); ++ break; ++ } ++} ++ ++static int ++ar934x_nfc_dev_ready(struct mtd_info *mtd) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ ++ return __ar934x_nfc_dev_ready(nfc); ++} ++ ++static void ++ar934x_nfc_select_chip(struct mtd_info *mtd, int chip_no) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ ++ if (nfc->select_chip) ++ nfc->select_chip(chip_no); ++} ++ ++static u8 ++ar934x_nfc_read_byte(struct mtd_info *mtd) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ u8 data; ++ ++ WARN_ON(nfc->buf_index >= nfc->buf_size); ++ ++ if (nfc->swap_dma || nfc->read_id) ++ data = nfc->buf[nfc->buf_index ^ 3]; ++ else ++ data = nfc->buf[nfc->buf_index]; ++ ++ nfc->buf_index++; ++ ++ return data; ++} ++ ++static void ++ar934x_nfc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ int i; ++ ++ WARN_ON(nfc->buf_index + len > nfc->buf_size); ++ ++ if (nfc->swap_dma) { ++ for (i = 0; i < len; i++) { ++ nfc->buf[nfc->buf_index ^ 3] = buf[i]; ++ nfc->buf_index++; ++ } ++ } else { ++ for (i = 0; i < len; i++) { ++ nfc->buf[nfc->buf_index] = buf[i]; ++ nfc->buf_index++; ++ } ++ } ++} ++ ++static void ++ar934x_nfc_read_buf(struct mtd_info *mtd, u8 *buf, int len) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ int buf_index; ++ int i; ++ ++ WARN_ON(nfc->buf_index + len > nfc->buf_size); ++ ++ buf_index = nfc->buf_index; ++ ++ if (nfc->swap_dma || nfc->read_id) { ++ for (i = 0; i < len; i++) { ++ buf[i] = nfc->buf[buf_index ^ 3]; ++ buf_index++; ++ } ++ } else { ++ for (i = 0; i < len; i++) { ++ buf[i] = nfc->buf[buf_index]; ++ buf_index++; ++ } ++ } ++ ++ nfc->buf_index = buf_index; ++} ++ ++static inline void ++ar934x_nfc_enable_hwecc(struct ar934x_nfc *nfc) ++{ ++ nfc->ctrl_reg |= AR934X_NFC_CTRL_ECC_EN; ++ nfc->ctrl_reg &= ~AR934X_NFC_CTRL_CUSTOM_SIZE_EN; ++} ++ ++static inline void ++ar934x_nfc_disable_hwecc(struct ar934x_nfc *nfc) ++{ ++ nfc->ctrl_reg &= ~AR934X_NFC_CTRL_ECC_EN; ++ nfc->ctrl_reg |= AR934X_NFC_CTRL_CUSTOM_SIZE_EN; ++} ++ ++static int ++ar934x_nfc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, ++ int page) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ int err; ++ ++ nfc_dbg(nfc, "read_oob: page:%d\n", page); ++ ++ err = ar934x_nfc_send_read(nfc, NAND_CMD_READ0, mtd->writesize, page, ++ mtd->oobsize); ++ if (err) ++ return err; ++ ++ memcpy(chip->oob_poi, nfc->buf, mtd->oobsize); ++ ++ return 0; ++} ++ ++static int ++ar934x_nfc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, ++ int page) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ ++ nfc_dbg(nfc, "write_oob: page:%d\n", page); ++ ++ memcpy(nfc->buf, chip->oob_poi, mtd->oobsize); ++ ++ return ar934x_nfc_send_write(nfc, NAND_CMD_PAGEPROG, mtd->writesize, ++ page, mtd->oobsize); ++} ++ ++static int ++ar934x_nfc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, ++ u8 *buf, int oob_required, int page) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ int len; ++ int err; ++ ++ nfc_dbg(nfc, "read_page_raw: page:%d oob:%d\n", page, oob_required); ++ ++ len = mtd->writesize; ++ if (oob_required) ++ len += mtd->oobsize; ++ ++ err = ar934x_nfc_send_read(nfc, NAND_CMD_READ0, 0, page, len); ++ if (err) ++ return err; ++ ++ memcpy(buf, nfc->buf, mtd->writesize); ++ ++ if (oob_required) ++ memcpy(chip->oob_poi, &nfc->buf[mtd->writesize], mtd->oobsize); ++ ++ return 0; ++} ++ ++static int ++ar934x_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip, ++ u8 *buf, int oob_required, int page) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ u32 ecc_ctrl; ++ int max_bitflips = 0; ++ bool ecc_failed; ++ bool ecc_corrected; ++ int err; ++ ++ nfc_dbg(nfc, "read_page: page:%d oob:%d\n", page, oob_required); ++ ++ ar934x_nfc_enable_hwecc(nfc); ++ err = ar934x_nfc_send_read(nfc, NAND_CMD_READ0, 0, page, ++ mtd->writesize); ++ ar934x_nfc_disable_hwecc(nfc); ++ ++ if (err) ++ return err; ++ ++ /* TODO: optimize to avoid memcpy */ ++ memcpy(buf, nfc->buf, mtd->writesize); ++ ++ /* read the ECC status */ ++ ecc_ctrl = ar934x_nfc_rr(nfc, AR934X_NFC_REG_ECC_CTRL); ++ ecc_failed = ecc_ctrl & AR934X_NFC_ECC_CTRL_ERR_UNCORRECT; ++ ecc_corrected = ecc_ctrl & AR934X_NFC_ECC_CTRL_ERR_CORRECT; ++ ++ if (oob_required || ecc_failed) { ++ err = ar934x_nfc_send_read(nfc, NAND_CMD_READ0, mtd->writesize, ++ page, mtd->oobsize); ++ if (err) ++ return err; ++ ++ if (oob_required) ++ memcpy(chip->oob_poi, nfc->buf, mtd->oobsize); ++ } ++ ++ if (ecc_failed) { ++ /* ++ * The hardware ECC engine reports uncorrectable errors ++ * on empty pages. Check the ECC bytes and the data. If ++ * both contains 0xff bytes only, dont report a failure. ++ * ++ * TODO: prebuild a buffer with 0xff bytes and use memcmp ++ * for better performance? ++ */ ++ if (!is_all_ff(&nfc->buf[nfc->ecc_oob_pos], chip->ecc.total) || ++ !is_all_ff(buf, mtd->writesize)) ++ mtd->ecc_stats.failed++; ++ } else if (ecc_corrected) { ++ /* ++ * The hardware does not report the exact count of the ++ * corrected bitflips, use assumptions based on the ++ * threshold. ++ */ ++ if (ecc_ctrl & AR934X_NFC_ECC_CTRL_ERR_OVER) { ++ /* ++ * The number of corrected bitflips exceeds the ++ * threshold. Assume the maximum. ++ */ ++ max_bitflips = chip->ecc.strength * chip->ecc.steps; ++ } else { ++ max_bitflips = nfc->ecc_thres * chip->ecc.steps; ++ } ++ ++ mtd->ecc_stats.corrected += max_bitflips; ++ } ++ ++ return max_bitflips; ++} ++ ++static int ++ar934x_nfc_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, ++ const u8 *buf, int oob_required, int page) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ int len; ++ ++ nfc_dbg(nfc, "write_page_raw: page:%d oob:%d\n", page, oob_required); ++ ++ memcpy(nfc->buf, buf, mtd->writesize); ++ len = mtd->writesize; ++ ++ if (oob_required) { ++ memcpy(&nfc->buf[mtd->writesize], chip->oob_poi, mtd->oobsize); ++ len += mtd->oobsize; ++ } ++ ++ return ar934x_nfc_send_write(nfc, NAND_CMD_PAGEPROG, 0, page, len); ++} ++ ++static int ++ar934x_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip, ++ const u8 *buf, int oob_required, int page) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ int err; ++ ++ nfc_dbg(nfc, "write_page: page:%d oob:%d\n", page, oob_required); ++ ++ /* write OOB first */ ++ if (oob_required && ++ !is_all_ff(chip->oob_poi, mtd->oobsize)) { ++ err = ar934x_nfc_write_oob(mtd, chip, page); ++ if (err) ++ return err; ++ } ++ ++ /* TODO: optimize to avoid memcopy */ ++ memcpy(nfc->buf, buf, mtd->writesize); ++ ++ ar934x_nfc_enable_hwecc(nfc); ++ err = ar934x_nfc_send_write(nfc, NAND_CMD_PAGEPROG, 0, page, ++ mtd->writesize); ++ ar934x_nfc_disable_hwecc(nfc); ++ ++ return err; ++} ++ ++static void ++ar934x_nfc_hw_init(struct ar934x_nfc *nfc) ++{ ++ struct ar934x_nfc_platform_data *pdata; ++ ++ pdata = ar934x_nfc_get_platform_data(nfc); ++ if (pdata->hw_reset) { ++ pdata->hw_reset(true); ++ pdata->hw_reset(false); ++ } ++ ++ /* ++ * setup timings ++ * TODO: make it configurable via platform data ++ */ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_TIME_SEQ, ++ AR934X_NFC_TIME_SEQ_DEFAULT); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_TIMINGS_ASYN, ++ AR934X_NFC_TIMINGS_ASYN_DEFAULT); ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_TIMINGS_SYN, ++ AR934X_NFC_TIMINGS_SYN_DEFAULT); ++ ++ /* disable WP on all chips, and select chip 0 */ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_MEM_CTRL, 0xff00); ++ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_DMA_ADDR_OFFS, 0); ++ ++ /* initialize Control register */ ++ nfc->ctrl_reg = AR934X_NFC_CTRL_CUSTOM_SIZE_EN; ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, nfc->ctrl_reg); ++ ++ if (nfc->small_page) { ++ /* Setup generic sequence register for small page reads. */ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_GEN_SEQ_CTRL, ++ AR934X_NFC_GENSEQ_SMALL_PAGE_READ); ++ } ++} ++ ++static void ++ar934x_nfc_restart(struct ar934x_nfc *nfc) ++{ ++ u32 ctrl_reg; ++ ++ if (nfc->select_chip) ++ nfc->select_chip(-1); ++ ++ ctrl_reg = nfc->ctrl_reg; ++ ar934x_nfc_hw_init(nfc); ++ nfc->ctrl_reg = ctrl_reg; ++ ++ if (nfc->select_chip) ++ nfc->select_chip(0); ++ ++ ar934x_nfc_send_cmd(nfc, NAND_CMD_RESET); ++} ++ ++static irqreturn_t ++ar934x_nfc_irq_handler(int irq, void *data) ++{ ++ struct ar934x_nfc *nfc = data; ++ u32 status; ++ ++ status = ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_STATUS); ++ ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_INT_STATUS, 0); ++ /* flush write */ ++ ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_STATUS); ++ ++ status &= ar934x_nfc_rr(nfc, AR934X_NFC_REG_INT_MASK); ++ if (status) { ++ nfc_dbg(nfc, "got IRQ, status:%08x\n", status); ++ ++ nfc->irq_status = status; ++ nfc->spurious_irq_expected = true; ++ wake_up(&nfc->irq_waitq); ++ } else { ++ if (nfc->spurious_irq_expected) { ++ nfc->spurious_irq_expected = false; ++ } else { ++ dev_warn(nfc->parent, "spurious interrupt\n"); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int ++ar934x_nfc_init_tail(struct mtd_info *mtd) ++{ ++ struct ar934x_nfc *nfc = mtd_to_ar934x_nfc(mtd); ++ struct nand_chip *chip = &nfc->nand_chip; ++ u32 ctrl; ++ u32 t; ++ int err; ++ ++ switch (mtd->oobsize) { ++ case 16: ++ case 64: ++ case 128: ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_SPARE_SIZE, mtd->oobsize); ++ break; ++ ++ default: ++ dev_err(nfc->parent, "unsupported OOB size: %d bytes\n", ++ mtd->oobsize); ++ return -ENXIO; ++ } ++ ++ ctrl = AR934X_NFC_CTRL_CUSTOM_SIZE_EN; ++ ++ switch (mtd->erasesize / mtd->writesize) { ++ case 32: ++ t = AR934X_NFC_CTRL_BLOCK_SIZE_32; ++ break; ++ ++ case 64: ++ t = AR934X_NFC_CTRL_BLOCK_SIZE_64; ++ break; ++ ++ case 128: ++ t = AR934X_NFC_CTRL_BLOCK_SIZE_128; ++ break; ++ ++ case 256: ++ t = AR934X_NFC_CTRL_BLOCK_SIZE_256; ++ break; ++ ++ default: ++ dev_err(nfc->parent, "unsupported block size: %u\n", ++ mtd->erasesize / mtd->writesize); ++ return -ENXIO; ++ } ++ ++ ctrl |= t << AR934X_NFC_CTRL_BLOCK_SIZE_S; ++ ++ switch (mtd->writesize) { ++ case 256: ++ nfc->small_page = 1; ++ t = AR934X_NFC_CTRL_PAGE_SIZE_256; ++ break; ++ ++ case 512: ++ nfc->small_page = 1; ++ t = AR934X_NFC_CTRL_PAGE_SIZE_512; ++ break; ++ ++ case 1024: ++ t = AR934X_NFC_CTRL_PAGE_SIZE_1024; ++ break; ++ ++ case 2048: ++ t = AR934X_NFC_CTRL_PAGE_SIZE_2048; ++ break; ++ ++ case 4096: ++ t = AR934X_NFC_CTRL_PAGE_SIZE_4096; ++ break; ++ ++ case 8192: ++ t = AR934X_NFC_CTRL_PAGE_SIZE_8192; ++ break; ++ ++ case 16384: ++ t = AR934X_NFC_CTRL_PAGE_SIZE_16384; ++ break; ++ ++ default: ++ dev_err(nfc->parent, "unsupported write size: %d bytes\n", ++ mtd->writesize); ++ return -ENXIO; ++ } ++ ++ ctrl |= t << AR934X_NFC_CTRL_PAGE_SIZE_S; ++ ++ if (nfc->small_page) { ++ ctrl |= AR934X_NFC_CTRL_SMALL_PAGE; ++ ++ if (chip->chipsize > (32 << 20)) { ++ nfc->addr_count0 = 4; ++ nfc->addr_count1 = 3; ++ } else if (chip->chipsize > (2 << 16)) { ++ nfc->addr_count0 = 3; ++ nfc->addr_count1 = 2; ++ } else { ++ nfc->addr_count0 = 2; ++ nfc->addr_count1 = 1; ++ } ++ } else { ++ if (chip->chipsize > (128 << 20)) { ++ nfc->addr_count0 = 5; ++ nfc->addr_count1 = 3; ++ } else if (chip->chipsize > (8 << 16)) { ++ nfc->addr_count0 = 4; ++ nfc->addr_count1 = 2; ++ } else { ++ nfc->addr_count0 = 3; ++ nfc->addr_count1 = 1; ++ } ++ } ++ ++ ctrl |= nfc->addr_count0 << AR934X_NFC_CTRL_ADDR_CYCLE0_S; ++ ctrl |= nfc->addr_count1 << AR934X_NFC_CTRL_ADDR_CYCLE1_S; ++ ++ nfc->ctrl_reg = ctrl; ++ ar934x_nfc_wr(nfc, AR934X_NFC_REG_CTRL, nfc->ctrl_reg); ++ ++ ar934x_nfc_free_buf(nfc); ++ err = ar934x_nfc_alloc_buf(nfc, mtd->writesize + mtd->oobsize); ++ ++ return err; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++static struct nand_ecclayout ar934x_nfc_oob_64_hwecc = { ++ .eccbytes = 28, ++ .eccpos = { ++ 20, 21, 22, 23, 24, 25, 26, ++ 27, 28, 29, 30, 31, 32, 33, ++ 34, 35, 36, 37, 38, 39, 40, ++ 41, 42, 43, 44, 45, 46, 47, ++ }, ++ .oobfree = { ++ { ++ .offset = 4, ++ .length = 16, ++ }, ++ { ++ .offset = 48, ++ .length = 16, ++ }, ++ }, ++}; ++ ++#else ++ ++static int ar934x_nfc_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->offset = 20; ++ oobregion->length = 28; ++ ++ return 0; ++} ++ ++static int ar934x_nfc_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 4; ++ oobregion->length = 16; ++ return 0; ++ case 1: ++ oobregion->offset = 48; ++ oobregion->length = 16; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops ar934x_nfc_ecclayout_ops = { ++ .ecc = ar934x_nfc_ooblayout_ecc, ++ .free = ar934x_nfc_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static int ++ar934x_nfc_setup_hwecc(struct ar934x_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand_chip; ++ struct mtd_info *mtd = ar934x_nfc_to_mtd(nfc); ++ u32 ecc_cap; ++ u32 ecc_thres; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) ++ struct mtd_oob_region oobregion; ++#endif ++ ++ if (!IS_ENABLED(CONFIG_MTD_NAND_AR934X_HW_ECC)) { ++ dev_err(nfc->parent, "hardware ECC support is disabled\n"); ++ return -EINVAL; ++ } ++ ++ switch (mtd->writesize) { ++ case 2048: ++ /* ++ * Writing a subpage separately is not supported, because ++ * the controller only does ECC on full-page accesses. ++ */ ++ nand->options = NAND_NO_SUBPAGE_WRITE; ++ ++ nand->ecc.size = 512; ++ nand->ecc.bytes = 7; ++ nand->ecc.strength = 4; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ nand->ecc.layout = &ar934x_nfc_oob_64_hwecc; ++#else ++ mtd_set_ooblayout(mtd, &ar934x_nfc_ecclayout_ops); ++#endif ++ break; ++ ++ default: ++ dev_err(nfc->parent, ++ "hardware ECC is not available for %d byte pages\n", ++ mtd->writesize); ++ return -EINVAL; ++ } ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ BUG_ON(!nand->ecc.layout); ++#else ++ BUG_ON(!mtd->ooblayout->ecc); ++#endif ++ ++ switch (nand->ecc.strength) { ++ case 4: ++ ecc_cap = AR934X_NFC_ECC_CTRL_ECC_CAP_4; ++ ecc_thres = 4; ++ break; ++ ++ default: ++ dev_err(nfc->parent, "unsupported ECC strength %u\n", ++ nand->ecc.strength); ++ return -EINVAL; ++ } ++ ++ nfc->ecc_thres = ecc_thres; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ nfc->ecc_oob_pos = nand->ecc.layout->eccpos[0]; ++#else ++ mtd->ooblayout->ecc(mtd, 0, &oobregion); ++ nfc->ecc_oob_pos = oobregion.offset; ++#endif ++ ++ nfc->ecc_ctrl_reg = ecc_cap << AR934X_NFC_ECC_CTRL_ECC_CAP_S; ++ nfc->ecc_ctrl_reg |= ecc_thres << AR934X_NFC_ECC_CTRL_ERR_THRES_S; ++ ++ nfc->ecc_offset_reg = mtd->writesize + nfc->ecc_oob_pos; ++ ++ nand->ecc.mode = NAND_ECC_HW; ++ nand->ecc.read_page = ar934x_nfc_read_page; ++ nand->ecc.read_page_raw = ar934x_nfc_read_page_raw; ++ nand->ecc.write_page = ar934x_nfc_write_page; ++ nand->ecc.write_page_raw = ar934x_nfc_write_page_raw; ++ nand->ecc.read_oob = ar934x_nfc_read_oob; ++ nand->ecc.write_oob = ar934x_nfc_write_oob; ++ ++ return 0; ++} ++ ++static int ++ar934x_nfc_probe(struct platform_device *pdev) ++{ ++ static const char *part_probes[] = { "cmdlinepart", NULL, }; ++ struct ar934x_nfc_platform_data *pdata; ++ struct ar934x_nfc *nfc; ++ struct resource *res; ++ struct mtd_info *mtd; ++ struct nand_chip *nand; ++ struct mtd_part_parser_data ppdata; ++ int ret; ++ ++ pdata = pdev->dev.platform_data; ++ if (pdata == NULL) { ++ dev_err(&pdev->dev, "no platform data defined\n"); ++ return -EINVAL; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "failed to get I/O memory\n"); ++ return -EINVAL; ++ } ++ ++ nfc = devm_kzalloc(&pdev->dev, sizeof(struct ar934x_nfc), GFP_KERNEL); ++ if (!nfc) { ++ dev_err(&pdev->dev, "failed to allocate driver data\n"); ++ return -ENOMEM; ++ } ++ ++ nfc->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(nfc->base)) { ++ dev_err(&pdev->dev, "failed to remap I/O memory\n"); ++ return PTR_ERR(nfc->base); ++ } ++ ++ nfc->irq = platform_get_irq(pdev, 0); ++ if (nfc->irq < 0) { ++ dev_err(&pdev->dev, "no IRQ resource specified\n"); ++ return -EINVAL; ++ } ++ ++ init_waitqueue_head(&nfc->irq_waitq); ++ ret = request_irq(nfc->irq, ar934x_nfc_irq_handler, 0, ++ dev_name(&pdev->dev), nfc); ++ if (ret) { ++ dev_err(&pdev->dev, "requast_irq failed, err:%d\n", ret); ++ return ret; ++ } ++ ++ nfc->parent = &pdev->dev; ++ nfc->select_chip = pdata->select_chip; ++ nfc->swap_dma = pdata->swap_dma; ++ ++ nand = &nfc->nand_chip; ++ mtd = ar934x_nfc_to_mtd(nfc); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ mtd->priv = nand; ++#endif ++ mtd->owner = THIS_MODULE; ++ if (pdata->name) ++ mtd->name = pdata->name; ++ else ++ mtd->name = dev_name(&pdev->dev); ++ ++ nand->chip_delay = 25; ++ ++ nand->dev_ready = ar934x_nfc_dev_ready; ++ nand->cmdfunc = ar934x_nfc_cmdfunc; ++ nand->read_byte = ar934x_nfc_read_byte; ++ nand->write_buf = ar934x_nfc_write_buf; ++ nand->read_buf = ar934x_nfc_read_buf; ++ nand->select_chip = ar934x_nfc_select_chip; ++ ++ ret = ar934x_nfc_alloc_buf(nfc, AR934X_NFC_ID_BUF_SIZE); ++ if (ret) ++ goto err_free_irq; ++ ++ platform_set_drvdata(pdev, nfc); ++ ++ ar934x_nfc_hw_init(nfc); ++ ++ ret = nand_scan_ident(mtd, 1, NULL); ++ if (ret) { ++ dev_err(&pdev->dev, "nand_scan_ident failed, err:%d\n", ret); ++ goto err_free_buf; ++ } ++ ++ ret = ar934x_nfc_init_tail(mtd); ++ if (ret) { ++ dev_err(&pdev->dev, "init tail failed, err:%d\n", ret); ++ goto err_free_buf; ++ } ++ ++ if (pdata->scan_fixup) { ++ ret = pdata->scan_fixup(mtd); ++ if (ret) ++ goto err_free_buf; ++ } ++ ++ switch (pdata->ecc_mode) { ++ case AR934X_NFC_ECC_SOFT: ++ nand->ecc.mode = NAND_ECC_SOFT; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) ++ nand->ecc.algo = NAND_ECC_HAMMING; ++#endif ++ break; ++ ++ case AR934X_NFC_ECC_SOFT_BCH: ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ nand->ecc.mode = NAND_ECC_SOFT_BCH; ++#else ++ nand->ecc.mode = NAND_ECC_SOFT; ++ nand->ecc.algo = NAND_ECC_BCH; ++#endif ++ break; ++ ++ case AR934X_NFC_ECC_HW: ++ ret = ar934x_nfc_setup_hwecc(nfc); ++ if (ret) ++ goto err_free_buf; ++ ++ break; ++ ++ default: ++ dev_err(nfc->parent, "unknown ECC mode %d\n", pdata->ecc_mode); ++ return -EINVAL; ++ } ++ ++ ret = nand_scan_tail(mtd); ++ if (ret) { ++ dev_err(&pdev->dev, "scan tail failed, err:%d\n", ret); ++ goto err_free_buf; ++ } ++ ++ memset(&ppdata, '\0', sizeof(ppdata)); ++ ret = mtd_device_parse_register(mtd, part_probes, &ppdata, ++ pdata->parts, pdata->nr_parts); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to register mtd, err:%d\n", ret); ++ goto err_free_buf; ++ } ++ ++ return 0; ++ ++err_free_buf: ++ ar934x_nfc_free_buf(nfc); ++err_free_irq: ++ free_irq(nfc->irq, nfc); ++ return ret; ++} ++ ++static int ++ar934x_nfc_remove(struct platform_device *pdev) ++{ ++ struct ar934x_nfc *nfc; ++ struct mtd_info *mtd; ++ ++ nfc = platform_get_drvdata(pdev); ++ if (nfc) { ++ mtd = ar934x_nfc_to_mtd(nfc); ++ nand_release(&nfc->nand_chip); ++ ar934x_nfc_free_buf(nfc); ++ free_irq(nfc->irq, nfc); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver ar934x_nfc_driver = { ++ .probe = ar934x_nfc_probe, ++ .remove = ar934x_nfc_remove, ++ .driver = { ++ .name = AR934X_NFC_DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++module_platform_driver(ar934x_nfc_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_DESCRIPTION("Atheros AR934x NAND Flash Controller driver"); ++MODULE_ALIAS("platform:" AR934X_NFC_DRIVER_NAME); +diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c b/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c +new file mode 100644 +index 0000000000..7dde613131 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c +@@ -0,0 +1,396 @@ ++/* ++ * NAND flash driver for the MikroTik RouterBoard 4xx series ++ * ++ * Copyright (C) 2008-2011 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * This file was based on the driver for Linux 2.6.22 published by ++ * MikroTik for their RouterBoard 4xx series devices. ++ * ++ * 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 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define DRV_NAME "rb4xx-nand" ++#define DRV_VERSION "0.2.0" ++#define DRV_DESC "NAND flash driver for RouterBoard 4xx series" ++ ++#define RB4XX_NAND_GPIO_READY 5 ++#define RB4XX_NAND_GPIO_ALE 37 ++#define RB4XX_NAND_GPIO_CLE 38 ++#define RB4XX_NAND_GPIO_NCE 39 ++ ++struct rb4xx_nand_info { ++ struct nand_chip chip; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct mtd_info mtd; ++#endif ++}; ++ ++static inline struct rb4xx_nand_info *mtd_to_rbinfo(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ return container_of(mtd, struct rb4xx_nand_info, mtd); ++#else ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ ++ return container_of(chip, struct rb4xx_nand_info, chip); ++#endif ++} ++ ++static struct mtd_info *rbinfo_to_mtd(struct rb4xx_nand_info *nfc) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ return &nfc->mtd; ++#else ++ return nand_to_mtd(&nfc->chip); ++#endif ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++/* ++ * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader ++ * will not be able to find the kernel that we load. ++ */ ++static struct nand_ecclayout rb4xx_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++#else ++ ++static int rb4xx_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 8; ++ oobregion->length = 3; ++ return 0; ++ case 1: ++ oobregion->offset = 13; ++ oobregion->length = 3; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static int rb4xx_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = 4; ++ return 0; ++ case 1: ++ oobregion->offset = 4; ++ oobregion->length = 1; ++ return 0; ++ case 2: ++ oobregion->offset = 6; ++ oobregion->length = 2; ++ return 0; ++ case 3: ++ oobregion->offset = 11; ++ oobregion->length = 2; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops rb4xx_nand_ecclayout_ops = { ++ .ecc = rb4xx_ooblayout_ecc, ++ .free = rb4xx_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static struct mtd_partition rb4xx_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, ++ { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, ++ { ++ .name = "ubi", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static int rb4xx_nand_dev_ready(struct mtd_info *mtd) ++{ ++ return gpio_get_value_cansleep(RB4XX_NAND_GPIO_READY); ++} ++ ++static void rb4xx_nand_write_cmd(unsigned char cmd) ++{ ++ unsigned char data = cmd; ++ int err; ++ ++ err = rb4xx_cpld_write(&data, 1); ++ if (err) ++ pr_err("rb4xx_nand: write cmd failed, err=%d\n", err); ++} ++ ++static void rb4xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, ++ unsigned int ctrl) ++{ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ gpio_set_value_cansleep(RB4XX_NAND_GPIO_CLE, ++ (ctrl & NAND_CLE) ? 1 : 0); ++ gpio_set_value_cansleep(RB4XX_NAND_GPIO_ALE, ++ (ctrl & NAND_ALE) ? 1 : 0); ++ gpio_set_value_cansleep(RB4XX_NAND_GPIO_NCE, ++ (ctrl & NAND_NCE) ? 0 : 1); ++ } ++ ++ if (cmd != NAND_CMD_NONE) ++ rb4xx_nand_write_cmd(cmd); ++} ++ ++static unsigned char rb4xx_nand_read_byte(struct mtd_info *mtd) ++{ ++ unsigned char data = 0; ++ int err; ++ ++ err = rb4xx_cpld_read(&data, 1); ++ if (err) { ++ pr_err("rb4xx_nand: read data failed, err=%d\n", err); ++ data = 0xff; ++ } ++ ++ return data; ++} ++ ++static void rb4xx_nand_write_buf(struct mtd_info *mtd, const unsigned char *buf, ++ int len) ++{ ++ int err; ++ ++ err = rb4xx_cpld_write(buf, len); ++ if (err) ++ pr_err("rb4xx_nand: write buf failed, err=%d\n", err); ++} ++ ++static void rb4xx_nand_read_buf(struct mtd_info *mtd, unsigned char *buf, ++ int len) ++{ ++ int err; ++ ++ err = rb4xx_cpld_read(buf, len); ++ if (err) ++ pr_err("rb4xx_nand: read buf failed, err=%d\n", err); ++} ++ ++static int rb4xx_nand_probe(struct platform_device *pdev) ++{ ++ struct rb4xx_nand_info *info; ++ struct mtd_info *mtd; ++ int ret; ++ ++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); ++ ++ ret = gpio_request(RB4XX_NAND_GPIO_READY, "NAND RDY"); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to request gpio %d\n", ++ RB4XX_NAND_GPIO_READY); ++ goto err; ++ } ++ ++ ret = gpio_direction_input(RB4XX_NAND_GPIO_READY); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to set input mode on gpio %d\n", ++ RB4XX_NAND_GPIO_READY); ++ goto err_free_gpio_ready; ++ } ++ ++ ret = gpio_request(RB4XX_NAND_GPIO_ALE, "NAND ALE"); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to request gpio %d\n", ++ RB4XX_NAND_GPIO_ALE); ++ goto err_free_gpio_ready; ++ } ++ ++ ret = gpio_direction_output(RB4XX_NAND_GPIO_ALE, 0); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to set output mode on gpio %d\n", ++ RB4XX_NAND_GPIO_ALE); ++ goto err_free_gpio_ale; ++ } ++ ++ ret = gpio_request(RB4XX_NAND_GPIO_CLE, "NAND CLE"); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to request gpio %d\n", ++ RB4XX_NAND_GPIO_CLE); ++ goto err_free_gpio_ale; ++ } ++ ++ ret = gpio_direction_output(RB4XX_NAND_GPIO_CLE, 0); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to set output mode on gpio %d\n", ++ RB4XX_NAND_GPIO_CLE); ++ goto err_free_gpio_cle; ++ } ++ ++ ret = gpio_request(RB4XX_NAND_GPIO_NCE, "NAND NCE"); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to request gpio %d\n", ++ RB4XX_NAND_GPIO_NCE); ++ goto err_free_gpio_cle; ++ } ++ ++ ret = gpio_direction_output(RB4XX_NAND_GPIO_NCE, 1); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to set output mode on gpio %d\n", ++ RB4XX_NAND_GPIO_ALE); ++ goto err_free_gpio_nce; ++ } ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) { ++ dev_err(&pdev->dev, "rb4xx-nand: no memory for private data\n"); ++ ret = -ENOMEM; ++ goto err_free_gpio_nce; ++ } ++ ++ info->chip.priv = &info; ++ mtd = rbinfo_to_mtd(info); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ mtd->priv = &info->chip; ++#endif ++ mtd->owner = THIS_MODULE; ++ ++ info->chip.cmd_ctrl = rb4xx_nand_cmd_ctrl; ++ info->chip.dev_ready = rb4xx_nand_dev_ready; ++ info->chip.read_byte = rb4xx_nand_read_byte; ++ info->chip.write_buf = rb4xx_nand_write_buf; ++ info->chip.read_buf = rb4xx_nand_read_buf; ++ ++ info->chip.chip_delay = 25; ++ info->chip.ecc.mode = NAND_ECC_SOFT; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) ++ info->chip.ecc.algo = NAND_ECC_HAMMING; ++#endif ++ info->chip.options = NAND_NO_SUBPAGE_WRITE; ++ ++ platform_set_drvdata(pdev, info); ++ ++ ret = nand_scan_ident(mtd, 1, NULL); ++ if (ret) { ++ ret = -ENXIO; ++ goto err_free_info; ++ } ++ ++ if (mtd->writesize == 512) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ info->chip.ecc.layout = &rb4xx_nand_ecclayout; ++#else ++ mtd_set_ooblayout(mtd, &rb4xx_nand_ecclayout_ops); ++#endif ++ ++ ret = nand_scan_tail(mtd); ++ if (ret) { ++ return -ENXIO; ++ goto err_set_drvdata; ++ } ++ ++ mtd_device_register(mtd, rb4xx_nand_partitions, ++ ARRAY_SIZE(rb4xx_nand_partitions)); ++ if (ret) ++ goto err_release_nand; ++ ++ return 0; ++ ++err_release_nand: ++ nand_release(&info->chip); ++err_set_drvdata: ++ platform_set_drvdata(pdev, NULL); ++err_free_info: ++ kfree(info); ++err_free_gpio_nce: ++ gpio_free(RB4XX_NAND_GPIO_NCE); ++err_free_gpio_cle: ++ gpio_free(RB4XX_NAND_GPIO_CLE); ++err_free_gpio_ale: ++ gpio_free(RB4XX_NAND_GPIO_ALE); ++err_free_gpio_ready: ++ gpio_free(RB4XX_NAND_GPIO_READY); ++err: ++ return ret; ++} ++ ++static int rb4xx_nand_remove(struct platform_device *pdev) ++{ ++ struct rb4xx_nand_info *info = platform_get_drvdata(pdev); ++ ++ nand_release(&info->chip); ++ platform_set_drvdata(pdev, NULL); ++ kfree(info); ++ gpio_free(RB4XX_NAND_GPIO_NCE); ++ gpio_free(RB4XX_NAND_GPIO_CLE); ++ gpio_free(RB4XX_NAND_GPIO_ALE); ++ gpio_free(RB4XX_NAND_GPIO_READY); ++ ++ return 0; ++} ++ ++static struct platform_driver rb4xx_nand_driver = { ++ .probe = rb4xx_nand_probe, ++ .remove = rb4xx_nand_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init rb4xx_nand_init(void) ++{ ++ return platform_driver_register(&rb4xx_nand_driver); ++} ++ ++static void __exit rb4xx_nand_exit(void) ++{ ++ platform_driver_unregister(&rb4xx_nand_driver); ++} ++ ++module_init(rb4xx_nand_init); ++module_exit(rb4xx_nand_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_AUTHOR("Imre Kaloz "); ++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c b/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c +new file mode 100644 +index 0000000000..a578c54ad3 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c +@@ -0,0 +1,440 @@ ++/* ++ * NAND flash driver for the MikroTik RouterBOARD 750 ++ * ++ * Copyright (C) 2010-2012 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. ++ */ ++ ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define DRV_NAME "rb750-nand" ++#define DRV_VERSION "0.1.0" ++#define DRV_DESC "NAND flash driver for the RouterBOARD 750" ++ ++#define RB750_NAND_IO0 BIT(RB750_GPIO_NAND_IO0) ++#define RB750_NAND_ALE BIT(RB750_GPIO_NAND_ALE) ++#define RB750_NAND_CLE BIT(RB750_GPIO_NAND_CLE) ++#define RB750_NAND_NRE BIT(RB750_GPIO_NAND_NRE) ++#define RB750_NAND_NWE BIT(RB750_GPIO_NAND_NWE) ++#define RB750_NAND_RDY BIT(RB750_GPIO_NAND_RDY) ++ ++#define RB750_NAND_DATA_SHIFT 1 ++#define RB750_NAND_DATA_BITS (0xff << RB750_NAND_DATA_SHIFT) ++#define RB750_NAND_INPUT_BITS (RB750_NAND_DATA_BITS | RB750_NAND_RDY) ++#define RB750_NAND_OUTPUT_BITS (RB750_NAND_ALE | RB750_NAND_CLE | \ ++ RB750_NAND_NRE | RB750_NAND_NWE) ++ ++struct rb750_nand_info { ++ struct nand_chip chip; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct mtd_info mtd; ++#endif ++ struct rb7xx_nand_platform_data *pdata; ++}; ++ ++static inline struct rb750_nand_info *mtd_to_rbinfo(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ return container_of(mtd, struct rb750_nand_info, mtd); ++#else ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ ++ return container_of(chip, struct rb750_nand_info, chip); ++#endif ++} ++ ++static struct mtd_info *rbinfo_to_mtd(struct rb750_nand_info *nfc) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ return &nfc->mtd; ++#else ++ return nand_to_mtd(&nfc->chip); ++#endif ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++/* ++ * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader ++ * will not be able to find the kernel that we load. ++ */ ++static struct nand_ecclayout rb750_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++#else ++ ++static int rb750_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 8; ++ oobregion->length = 3; ++ return 0; ++ case 1: ++ oobregion->offset = 13; ++ oobregion->length = 3; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static int rb750_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = 4; ++ return 0; ++ case 1: ++ oobregion->offset = 4; ++ oobregion->length = 1; ++ return 0; ++ case 2: ++ oobregion->offset = 6; ++ oobregion->length = 2; ++ return 0; ++ case 3: ++ oobregion->offset = 11; ++ oobregion->length = 2; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops rb750_nand_ecclayout_ops = { ++ .ecc = rb750_ooblayout_ecc, ++ .free = rb750_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static struct mtd_partition rb750_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, { ++ .name = "ubi", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static void rb750_nand_write(const u8 *buf, unsigned len) ++{ ++ void __iomem *base = ath79_gpio_base; ++ u32 out; ++ u32 t; ++ unsigned i; ++ ++ /* set data lines to output mode */ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ __raw_writel(t | RB750_NAND_DATA_BITS, base + AR71XX_GPIO_REG_OE); ++ ++ out = __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ out &= ~(RB750_NAND_DATA_BITS | RB750_NAND_NWE); ++ for (i = 0; i != len; i++) { ++ u32 data; ++ ++ data = buf[i]; ++ data <<= RB750_NAND_DATA_SHIFT; ++ data |= out; ++ __raw_writel(data, base + AR71XX_GPIO_REG_OUT); ++ ++ __raw_writel(data | RB750_NAND_NWE, base + AR71XX_GPIO_REG_OUT); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ } ++ ++ /* set data lines to input mode */ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ __raw_writel(t & ~RB750_NAND_DATA_BITS, base + AR71XX_GPIO_REG_OE); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_OE); ++} ++ ++static void rb750_nand_read(u8 *read_buf, unsigned len) ++{ ++ void __iomem *base = ath79_gpio_base; ++ unsigned i; ++ ++ for (i = 0; i < len; i++) { ++ u8 data; ++ ++ /* activate RE line */ ++ __raw_writel(RB750_NAND_NRE, base + AR71XX_GPIO_REG_CLEAR); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_CLEAR); ++ ++ /* read input lines */ ++ data = __raw_readl(base + AR71XX_GPIO_REG_IN) >> ++ RB750_NAND_DATA_SHIFT; ++ ++ /* deactivate RE line */ ++ __raw_writel(RB750_NAND_NRE, base + AR71XX_GPIO_REG_SET); ++ ++ read_buf[i] = data; ++ } ++} ++ ++static void rb750_nand_select_chip(struct mtd_info *mtd, int chip) ++{ ++ struct rb750_nand_info *rbinfo = mtd_to_rbinfo(mtd); ++ void __iomem *base = ath79_gpio_base; ++ u32 t; ++ ++ if (chip >= 0) { ++ rbinfo->pdata->enable_pins(); ++ ++ /* set input mode for data lines */ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ __raw_writel(t & ~RB750_NAND_INPUT_BITS, ++ base + AR71XX_GPIO_REG_OE); ++ ++ /* deactivate RE and WE lines */ ++ __raw_writel(RB750_NAND_NRE | RB750_NAND_NWE, ++ base + AR71XX_GPIO_REG_SET); ++ /* flush write */ ++ (void) __raw_readl(base + AR71XX_GPIO_REG_SET); ++ ++ /* activate CE line */ ++ __raw_writel(rbinfo->pdata->nce_line, ++ base + AR71XX_GPIO_REG_CLEAR); ++ } else { ++ /* deactivate CE line */ ++ __raw_writel(rbinfo->pdata->nce_line, ++ base + AR71XX_GPIO_REG_SET); ++ /* flush write */ ++ (void) __raw_readl(base + AR71XX_GPIO_REG_SET); ++ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ __raw_writel(t | RB750_NAND_IO0 | RB750_NAND_RDY, ++ base + AR71XX_GPIO_REG_OE); ++ ++ rbinfo->pdata->disable_pins(); ++ } ++} ++ ++static int rb750_nand_dev_ready(struct mtd_info *mtd) ++{ ++ void __iomem *base = ath79_gpio_base; ++ ++ return !!(__raw_readl(base + AR71XX_GPIO_REG_IN) & RB750_NAND_RDY); ++} ++ ++static void rb750_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, ++ unsigned int ctrl) ++{ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ void __iomem *base = ath79_gpio_base; ++ u32 t; ++ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ ++ t &= ~(RB750_NAND_CLE | RB750_NAND_ALE); ++ t |= (ctrl & NAND_CLE) ? RB750_NAND_CLE : 0; ++ t |= (ctrl & NAND_ALE) ? RB750_NAND_ALE : 0; ++ ++ __raw_writel(t, base + AR71XX_GPIO_REG_OUT); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ } ++ ++ if (cmd != NAND_CMD_NONE) { ++ u8 t = cmd; ++ rb750_nand_write(&t, 1); ++ } ++} ++ ++static u8 rb750_nand_read_byte(struct mtd_info *mtd) ++{ ++ u8 data = 0; ++ rb750_nand_read(&data, 1); ++ return data; ++} ++ ++static void rb750_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) ++{ ++ rb750_nand_read(buf, len); ++} ++ ++static void rb750_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) ++{ ++ rb750_nand_write(buf, len); ++} ++ ++static void __init rb750_nand_gpio_init(struct rb750_nand_info *info) ++{ ++ void __iomem *base = ath79_gpio_base; ++ u32 out; ++ u32 t; ++ ++ out = __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ ++ /* setup output levels */ ++ __raw_writel(RB750_NAND_NCE | RB750_NAND_NRE | RB750_NAND_NWE, ++ base + AR71XX_GPIO_REG_SET); ++ ++ __raw_writel(RB750_NAND_ALE | RB750_NAND_CLE, ++ base + AR71XX_GPIO_REG_CLEAR); ++ ++ /* setup input lines */ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ __raw_writel(t & ~(RB750_NAND_INPUT_BITS), base + AR71XX_GPIO_REG_OE); ++ ++ /* setup output lines */ ++ t = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ t |= RB750_NAND_OUTPUT_BITS; ++ t |= info->pdata->nce_line; ++ __raw_writel(t, base + AR71XX_GPIO_REG_OE); ++ ++ info->pdata->latch_change(~out & RB750_NAND_IO0, out & RB750_NAND_IO0); ++} ++ ++static int rb750_nand_probe(struct platform_device *pdev) ++{ ++ struct rb750_nand_info *info; ++ struct rb7xx_nand_platform_data *pdata; ++ struct mtd_info *mtd; ++ int ret; ++ ++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) ++ return -EINVAL; ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->chip.priv = &info; ++ ++ mtd = rbinfo_to_mtd(info); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ mtd->priv = &info->chip; ++#endif ++ mtd->owner = THIS_MODULE; ++ ++ info->chip.select_chip = rb750_nand_select_chip; ++ info->chip.cmd_ctrl = rb750_nand_cmd_ctrl; ++ info->chip.dev_ready = rb750_nand_dev_ready; ++ info->chip.read_byte = rb750_nand_read_byte; ++ info->chip.write_buf = rb750_nand_write_buf; ++ info->chip.read_buf = rb750_nand_read_buf; ++ ++ info->chip.chip_delay = 25; ++ info->chip.ecc.mode = NAND_ECC_SOFT; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) ++ info->chip.ecc.algo = NAND_ECC_HAMMING; ++#endif ++ info->chip.options = NAND_NO_SUBPAGE_WRITE; ++ ++ info->pdata = pdata; ++ ++ platform_set_drvdata(pdev, info); ++ ++ rb750_nand_gpio_init(info); ++ ++ ret = nand_scan_ident(mtd, 1, NULL); ++ if (ret) { ++ ret = -ENXIO; ++ goto err_free_info; ++ } ++ ++ if (mtd->writesize == 512) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ info->chip.ecc.layout = &rb750_nand_ecclayout; ++#else ++ mtd_set_ooblayout(mtd, &rb750_nand_ecclayout_ops); ++#endif ++ ++ ret = nand_scan_tail(mtd); ++ if (ret) { ++ return -ENXIO; ++ goto err_set_drvdata; ++ } ++ ++ ret = mtd_device_register(mtd, rb750_nand_partitions, ++ ARRAY_SIZE(rb750_nand_partitions)); ++ if (ret) ++ goto err_release_nand; ++ ++ return 0; ++ ++err_release_nand: ++ nand_release(&info->chip); ++err_set_drvdata: ++ platform_set_drvdata(pdev, NULL); ++err_free_info: ++ kfree(info); ++ return ret; ++} ++ ++static int rb750_nand_remove(struct platform_device *pdev) ++{ ++ struct rb750_nand_info *info = platform_get_drvdata(pdev); ++ ++ nand_release(&info->chip); ++ platform_set_drvdata(pdev, NULL); ++ kfree(info); ++ ++ return 0; ++} ++ ++static struct platform_driver rb750_nand_driver = { ++ .probe = rb750_nand_probe, ++ .remove = rb750_nand_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init rb750_nand_init(void) ++{ ++ return platform_driver_register(&rb750_nand_driver); ++} ++ ++static void __exit rb750_nand_exit(void) ++{ ++ platform_driver_unregister(&rb750_nand_driver); ++} ++ ++module_init(rb750_nand_init); ++module_exit(rb750_nand_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/rb91x_nand.c b/target/linux/ar71xx/files/drivers/mtd/nand/rb91x_nand.c +new file mode 100644 +index 0000000000..94e709b7e4 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/mtd/nand/rb91x_nand.c +@@ -0,0 +1,464 @@ ++/* ++ * NAND flash driver for the MikroTik RouterBOARD 91x series ++ * ++ * Copyright (C) 2013-2014 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define DRV_DESC "NAND flash driver for the RouterBOARD 91x series" ++ ++#define RB91X_NAND_NRWE BIT(12) ++ ++#define RB91X_NAND_DATA_BITS (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) |\ ++ BIT(13) | BIT(14) | BIT(15)) ++ ++#define RB91X_NAND_INPUT_BITS (RB91X_NAND_DATA_BITS | RB91X_NAND_RDY) ++#define RB91X_NAND_OUTPUT_BITS (RB91X_NAND_DATA_BITS | RB91X_NAND_NRWE) ++ ++#define RB91X_NAND_LOW_DATA_MASK 0x1f ++#define RB91X_NAND_HIGH_DATA_MASK 0xe0 ++#define RB91X_NAND_HIGH_DATA_SHIFT 8 ++ ++struct rb91x_nand_info { ++ struct nand_chip chip; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ struct mtd_info mtd; ++#endif ++ struct device *dev; ++ ++ int gpio_nce; ++ int gpio_ale; ++ int gpio_cle; ++ int gpio_rdy; ++ int gpio_read; ++ int gpio_nrw; ++ int gpio_nle; ++}; ++ ++static inline struct rb91x_nand_info *mtd_to_rbinfo(struct mtd_info *mtd) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ return container_of(mtd, struct rb91x_nand_info, mtd); ++#else ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ ++ return container_of(chip, struct rb91x_nand_info, chip); ++#endif ++} ++ ++static struct mtd_info *rbinfo_to_mtd(struct rb91x_nand_info *nfc) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ return &nfc->mtd; ++#else ++ return nand_to_mtd(&nfc->chip); ++#endif ++} ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++/* ++ * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader ++ * will not be able to find the kernel that we load. ++ */ ++static struct nand_ecclayout rb91x_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++#else ++ ++static int rb91x_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 8; ++ oobregion->length = 3; ++ return 0; ++ case 1: ++ oobregion->offset = 13; ++ oobregion->length = 3; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static int rb91x_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = 4; ++ return 0; ++ case 1: ++ oobregion->offset = 4; ++ oobregion->length = 1; ++ return 0; ++ case 2: ++ oobregion->offset = 6; ++ oobregion->length = 2; ++ return 0; ++ case 3: ++ oobregion->offset = 11; ++ oobregion->length = 2; ++ return 0; ++ default: ++ return -ERANGE; ++ } ++} ++ ++static const struct mtd_ooblayout_ops rb91x_nand_ecclayout_ops = { ++ .ecc = rb91x_ooblayout_ecc, ++ .free = rb91x_ooblayout_free, ++}; ++#endif /* < 4.6 */ ++ ++static struct mtd_partition rb91x_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, { ++ .name = "ubi", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static void rb91x_nand_write(struct rb91x_nand_info *rbni, ++ const u8 *buf, ++ unsigned len) ++{ ++ void __iomem *base = ath79_gpio_base; ++ u32 oe_reg; ++ u32 out_reg; ++ u32 out; ++ unsigned i; ++ ++ /* enable the latch */ ++ gpio_set_value_cansleep(rbni->gpio_nle, 0); ++ ++ oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ out_reg = __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ ++ /* set data lines to output mode */ ++ __raw_writel(oe_reg & ~(RB91X_NAND_DATA_BITS | RB91X_NAND_NRWE), ++ base + AR71XX_GPIO_REG_OE); ++ ++ out = out_reg & ~(RB91X_NAND_DATA_BITS | RB91X_NAND_NRWE); ++ for (i = 0; i != len; i++) { ++ u32 data; ++ ++ data = (buf[i] & RB91X_NAND_HIGH_DATA_MASK) << ++ RB91X_NAND_HIGH_DATA_SHIFT; ++ data |= buf[i] & RB91X_NAND_LOW_DATA_MASK; ++ data |= out; ++ __raw_writel(data, base + AR71XX_GPIO_REG_OUT); ++ ++ /* deactivate WE line */ ++ data |= RB91X_NAND_NRWE; ++ __raw_writel(data, base + AR71XX_GPIO_REG_OUT); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ } ++ ++ /* restore registers */ ++ __raw_writel(out_reg, base + AR71XX_GPIO_REG_OUT); ++ __raw_writel(oe_reg, base + AR71XX_GPIO_REG_OE); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ ++ /* disable the latch */ ++ gpio_set_value_cansleep(rbni->gpio_nle, 1); ++} ++ ++static void rb91x_nand_read(struct rb91x_nand_info *rbni, ++ u8 *read_buf, ++ unsigned len) ++{ ++ void __iomem *base = ath79_gpio_base; ++ u32 oe_reg; ++ u32 out_reg; ++ unsigned i; ++ ++ /* enable read mode */ ++ gpio_set_value_cansleep(rbni->gpio_read, 1); ++ ++ /* enable latch */ ++ gpio_set_value_cansleep(rbni->gpio_nle, 0); ++ ++ /* save registers */ ++ oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); ++ out_reg = __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ ++ /* set data lines to input mode */ ++ __raw_writel(oe_reg | RB91X_NAND_DATA_BITS, ++ base + AR71XX_GPIO_REG_OE); ++ ++ for (i = 0; i < len; i++) { ++ u32 in; ++ u8 data; ++ ++ /* activate RE line */ ++ __raw_writel(RB91X_NAND_NRWE, base + AR71XX_GPIO_REG_CLEAR); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_CLEAR); ++ ++ /* read input lines */ ++ in = __raw_readl(base + AR71XX_GPIO_REG_IN); ++ ++ /* deactivate RE line */ ++ __raw_writel(RB91X_NAND_NRWE, base + AR71XX_GPIO_REG_SET); ++ ++ data = (in & RB91X_NAND_LOW_DATA_MASK); ++ data |= (in >> RB91X_NAND_HIGH_DATA_SHIFT) & ++ RB91X_NAND_HIGH_DATA_MASK; ++ ++ read_buf[i] = data; ++ } ++ ++ /* restore registers */ ++ __raw_writel(out_reg, base + AR71XX_GPIO_REG_OUT); ++ __raw_writel(oe_reg, base + AR71XX_GPIO_REG_OE); ++ /* flush write */ ++ __raw_readl(base + AR71XX_GPIO_REG_OUT); ++ ++ /* disable latch */ ++ gpio_set_value_cansleep(rbni->gpio_nle, 1); ++ ++ /* disable read mode */ ++ gpio_set_value_cansleep(rbni->gpio_read, 0); ++} ++ ++static int rb91x_nand_dev_ready(struct mtd_info *mtd) ++{ ++ struct rb91x_nand_info *rbni = mtd_to_rbinfo(mtd); ++ ++ return gpio_get_value_cansleep(rbni->gpio_rdy); ++} ++ ++static void rb91x_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, ++ unsigned int ctrl) ++{ ++ struct rb91x_nand_info *rbni = mtd_to_rbinfo(mtd); ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ gpio_set_value_cansleep(rbni->gpio_cle, ++ (ctrl & NAND_CLE) ? 1 : 0); ++ gpio_set_value_cansleep(rbni->gpio_ale, ++ (ctrl & NAND_ALE) ? 1 : 0); ++ gpio_set_value_cansleep(rbni->gpio_nce, ++ (ctrl & NAND_NCE) ? 0 : 1); ++ } ++ ++ if (cmd != NAND_CMD_NONE) { ++ u8 t = cmd; ++ ++ rb91x_nand_write(rbni, &t, 1); ++ } ++} ++ ++static u8 rb91x_nand_read_byte(struct mtd_info *mtd) ++{ ++ struct rb91x_nand_info *rbni = mtd_to_rbinfo(mtd); ++ u8 data = 0xff; ++ ++ rb91x_nand_read(rbni, &data, 1); ++ ++ return data; ++} ++ ++static void rb91x_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) ++{ ++ struct rb91x_nand_info *rbni = mtd_to_rbinfo(mtd); ++ ++ rb91x_nand_read(rbni, buf, len); ++} ++ ++static void rb91x_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) ++{ ++ struct rb91x_nand_info *rbni = mtd_to_rbinfo(mtd); ++ ++ rb91x_nand_write(rbni, buf, len); ++} ++ ++static int rb91x_nand_gpio_init(struct rb91x_nand_info *info) ++{ ++ int ret; ++ ++ /* ++ * Ensure that the LATCH is disabled before initializing ++ * control lines. ++ */ ++ ret = devm_gpio_request_one(info->dev, info->gpio_nle, ++ GPIOF_OUT_INIT_HIGH, "LATCH enable"); ++ if (ret) ++ return ret; ++ ++ ret = devm_gpio_request_one(info->dev, info->gpio_nce, ++ GPIOF_OUT_INIT_HIGH, "NAND nCE"); ++ if (ret) ++ return ret; ++ ++ ret = devm_gpio_request_one(info->dev, info->gpio_nrw, ++ GPIOF_OUT_INIT_HIGH, "NAND nRW"); ++ if (ret) ++ return ret; ++ ++ ret = devm_gpio_request_one(info->dev, info->gpio_cle, ++ GPIOF_OUT_INIT_LOW, "NAND CLE"); ++ if (ret) ++ return ret; ++ ++ ret = devm_gpio_request_one(info->dev, info->gpio_ale, ++ GPIOF_OUT_INIT_LOW, "NAND ALE"); ++ if (ret) ++ return ret; ++ ++ ret = devm_gpio_request_one(info->dev, info->gpio_read, ++ GPIOF_OUT_INIT_LOW, "NAND READ"); ++ if (ret) ++ return ret; ++ ++ ret = devm_gpio_request_one(info->dev, info->gpio_rdy, ++ GPIOF_IN, "NAND RDY"); ++ return ret; ++} ++ ++static int rb91x_nand_probe(struct platform_device *pdev) ++{ ++ struct rb91x_nand_info *rbni; ++ struct rb91x_nand_platform_data *pdata; ++ struct mtd_info *mtd; ++ int ret; ++ ++ pr_info(DRV_DESC "\n"); ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ if (!pdata) ++ return -EINVAL; ++ ++ rbni = devm_kzalloc(&pdev->dev, sizeof(*rbni), GFP_KERNEL); ++ if (!rbni) ++ return -ENOMEM; ++ ++ rbni->dev = &pdev->dev; ++ rbni->gpio_nce = pdata->gpio_nce; ++ rbni->gpio_ale = pdata->gpio_ale; ++ rbni->gpio_cle = pdata->gpio_cle; ++ rbni->gpio_read = pdata->gpio_read; ++ rbni->gpio_nrw = pdata->gpio_nrw; ++ rbni->gpio_rdy = pdata->gpio_rdy; ++ rbni->gpio_nle = pdata->gpio_nle; ++ ++ rbni->chip.priv = &rbni; ++ mtd = rbinfo_to_mtd(rbni); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ mtd->priv = &rbni->chip; ++#endif ++ mtd->owner = THIS_MODULE; ++ ++ rbni->chip.cmd_ctrl = rb91x_nand_cmd_ctrl; ++ rbni->chip.dev_ready = rb91x_nand_dev_ready; ++ rbni->chip.read_byte = rb91x_nand_read_byte; ++ rbni->chip.write_buf = rb91x_nand_write_buf; ++ rbni->chip.read_buf = rb91x_nand_read_buf; ++ ++ rbni->chip.chip_delay = 25; ++ rbni->chip.ecc.mode = NAND_ECC_SOFT; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) ++ rbni->chip.ecc.algo = NAND_ECC_HAMMING; ++#endif ++ rbni->chip.options = NAND_NO_SUBPAGE_WRITE; ++ ++ platform_set_drvdata(pdev, rbni); ++ ++ ret = rb91x_nand_gpio_init(rbni); ++ if (ret) ++ return ret; ++ ++ ret = nand_scan_ident(mtd, 1, NULL); ++ if (ret) ++ return ret; ++ ++ if (mtd->writesize == 512) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) ++ rbni->chip.ecc.layout = &rb91x_nand_ecclayout; ++#else ++ mtd_set_ooblayout(mtd, &rb91x_nand_ecclayout_ops); ++#endif ++ ++ ret = nand_scan_tail(mtd); ++ if (ret) ++ return ret; ++ ++ ret = mtd_device_register(mtd, rb91x_nand_partitions, ++ ARRAY_SIZE(rb91x_nand_partitions)); ++ if (ret) ++ goto err_release_nand; ++ ++ return 0; ++ ++err_release_nand: ++ nand_release(&rbni->chip); ++ return ret; ++} ++ ++static int rb91x_nand_remove(struct platform_device *pdev) ++{ ++ struct rb91x_nand_info *info = platform_get_drvdata(pdev); ++ ++ nand_release(&info->chip); ++ ++ return 0; ++} ++ ++static struct platform_driver rb91x_nand_driver = { ++ .probe = rb91x_nand_probe, ++ .remove = rb91x_nand_remove, ++ .driver = { ++ .name = RB91X_NAND_DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++module_platform_driver(rb91x_nand_driver); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c b/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c +new file mode 100644 +index 0000000000..1b94163b83 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c +@@ -0,0 +1,235 @@ ++/* ++ * 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define TPLINK_NUM_PARTS 5 ++#define TPLINK_HEADER_V1 0x01000000 ++#define TPLINK_HEADER_V2 0x02000000 ++#define MD5SUM_LEN 16 ++ ++#define TPLINK_ART_LEN 0x10000 ++#define TPLINK_KERNEL_OFFS 0x20000 ++#define TPLINK_64K_KERNEL_OFFS 0x10000 ++ ++struct tplink_fw_header { ++ uint32_t version; /* header version */ ++ char vendor_name[24]; ++ char fw_version[36]; ++ uint32_t hw_id; /* hardware id */ ++ uint32_t hw_rev; /* hardware revision */ ++ uint32_t unk1; ++ uint8_t md5sum1[MD5SUM_LEN]; ++ uint32_t unk2; ++ uint8_t md5sum2[MD5SUM_LEN]; ++ uint32_t unk3; ++ uint32_t kernel_la; /* kernel load address */ ++ uint32_t kernel_ep; /* kernel entry point */ ++ uint32_t fw_length; /* total length of the firmware */ ++ uint32_t kernel_ofs; /* kernel data offset */ ++ uint32_t kernel_len; /* kernel data length */ ++ uint32_t rootfs_ofs; /* rootfs data offset */ ++ uint32_t rootfs_len; /* rootfs data length */ ++ uint32_t boot_ofs; /* bootloader data offset */ ++ uint32_t boot_len; /* bootloader data length */ ++ uint8_t pad[360]; ++} __attribute__ ((packed)); ++ ++static struct tplink_fw_header * ++tplink_read_header(struct mtd_info *mtd, size_t offset) ++{ ++ struct tplink_fw_header *header; ++ size_t header_len; ++ size_t retlen; ++ int ret; ++ u32 t; ++ ++ header = vmalloc(sizeof(*header)); ++ if (!header) ++ goto err; ++ ++ header_len = sizeof(struct tplink_fw_header); ++ ret = mtd_read(mtd, offset, header_len, &retlen, ++ (unsigned char *) header); ++ if (ret) ++ goto err_free_header; ++ ++ if (retlen != header_len) ++ goto err_free_header; ++ ++ /* sanity checks */ ++ t = be32_to_cpu(header->version); ++ if ((t != TPLINK_HEADER_V1) && (t != TPLINK_HEADER_V2)) ++ goto err_free_header; ++ ++ t = be32_to_cpu(header->kernel_ofs); ++ if (t != header_len) ++ goto err_free_header; ++ ++ return header; ++ ++err_free_header: ++ vfree(header); ++err: ++ return NULL; ++} ++ ++static int tplink_check_rootfs_magic(struct mtd_info *mtd, size_t offset) ++{ ++ u32 magic; ++ size_t retlen; ++ int ret; ++ ++ ret = mtd_read(mtd, offset, sizeof(magic), &retlen, ++ (unsigned char *) &magic); ++ if (ret) ++ return ret; ++ ++ if (retlen != sizeof(magic)) ++ return -EIO; ++ ++ if (le32_to_cpu(magic) != SQUASHFS_MAGIC && ++ magic != 0x19852003) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int tplink_parse_partitions_offset(struct mtd_info *master, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ struct mtd_partition **pparts, ++#else ++ const struct mtd_partition **pparts, ++#endif ++ struct mtd_part_parser_data *data, ++ size_t offset) ++{ ++ struct mtd_partition *parts; ++ struct tplink_fw_header *header; ++ int nr_parts; ++ size_t art_offset; ++ size_t rootfs_offset; ++ size_t squashfs_offset; ++ int ret; ++ ++ nr_parts = TPLINK_NUM_PARTS; ++ parts = kzalloc(nr_parts * sizeof(struct mtd_partition), GFP_KERNEL); ++ if (!parts) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ header = tplink_read_header(master, offset); ++ if (!header) { ++ pr_notice("%s: no TP-Link header found\n", master->name); ++ ret = -ENODEV; ++ goto err_free_parts; ++ } ++ ++ squashfs_offset = offset + sizeof(struct tplink_fw_header) + ++ be32_to_cpu(header->kernel_len); ++ ++ ret = tplink_check_rootfs_magic(master, squashfs_offset); ++ if (ret == 0) ++ rootfs_offset = squashfs_offset; ++ else ++ rootfs_offset = offset + be32_to_cpu(header->rootfs_ofs); ++ ++ art_offset = master->size - TPLINK_ART_LEN; ++ ++ parts[0].name = "u-boot"; ++ parts[0].offset = 0; ++ parts[0].size = offset; ++ parts[0].mask_flags = MTD_WRITEABLE; ++ ++ parts[1].name = "kernel"; ++ parts[1].offset = offset; ++ parts[1].size = rootfs_offset - offset; ++ ++ parts[2].name = "rootfs"; ++ parts[2].offset = rootfs_offset; ++ parts[2].size = art_offset - rootfs_offset; ++ ++ parts[3].name = "art"; ++ parts[3].offset = art_offset; ++ parts[3].size = TPLINK_ART_LEN; ++ parts[3].mask_flags = MTD_WRITEABLE; ++ ++ parts[4].name = "firmware"; ++ parts[4].offset = offset; ++ parts[4].size = art_offset - offset; ++ ++ vfree(header); ++ ++ *pparts = parts; ++ return nr_parts; ++ ++err_free_parts: ++ kfree(parts); ++err: ++ *pparts = NULL; ++ return ret; ++} ++ ++static int tplink_parse_partitions(struct mtd_info *master, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ struct mtd_partition **pparts, ++#else ++ const struct mtd_partition **pparts, ++#endif ++ struct mtd_part_parser_data *data) ++{ ++ return tplink_parse_partitions_offset(master, pparts, data, ++ TPLINK_KERNEL_OFFS); ++} ++ ++static int tplink_parse_64k_partitions(struct mtd_info *master, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ struct mtd_partition **pparts, ++#else ++ const struct mtd_partition **pparts, ++#endif ++ struct mtd_part_parser_data *data) ++{ ++ return tplink_parse_partitions_offset(master, pparts, data, ++ TPLINK_64K_KERNEL_OFFS); ++} ++ ++static struct mtd_part_parser tplink_parser = { ++ .owner = THIS_MODULE, ++ .parse_fn = tplink_parse_partitions, ++ .name = "tp-link", ++}; ++ ++static struct mtd_part_parser tplink_64k_parser = { ++ .owner = THIS_MODULE, ++ .parse_fn = tplink_parse_64k_partitions, ++ .name = "tp-link-64k", ++}; ++ ++static int __init tplink_parser_init(void) ++{ ++ register_mtd_parser(&tplink_parser); ++ register_mtd_parser(&tplink_64k_parser); ++ ++ return 0; ++} ++ ++module_init(tplink_parser_init); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Gabor Juhos "); +diff --git a/target/linux/ar71xx/files/drivers/net/dsa/mv88e6063.c b/target/linux/ar71xx/files/drivers/net/dsa/mv88e6063.c +new file mode 100644 +index 0000000000..71ecd61c80 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/dsa/mv88e6063.c +@@ -0,0 +1,307 @@ ++/* ++ * net/dsa/mv88e6063.c - Driver for Marvell 88e6063 switch chips ++ * Copyright (c) 2009 Gabor Juhos ++ * ++ * This driver was base on: net/dsa/mv88e6060.c ++ * net/dsa/mv88e6063.c - Driver for Marvell 88e6060 switch chips ++ * Copyright (c) 2008-2009 Marvell Semiconductor ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define REG_BASE 0x10 ++#define REG_PHY(p) (REG_BASE + (p)) ++#define REG_PORT(p) (REG_BASE + 8 + (p)) ++#define REG_GLOBAL (REG_BASE + 0x0f) ++#define NUM_PORTS 7 ++ ++static int reg_read(struct dsa_switch *ds, int addr, int reg) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); ++ return mdiobus_read(bus, addr, reg); ++#else ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->dev); ++ return mdiobus_read(bus, addr, reg); ++#endif ++} ++ ++#define REG_READ(addr, reg) \ ++ ({ \ ++ int __ret; \ ++ \ ++ __ret = reg_read(ds, addr, reg); \ ++ if (__ret < 0) \ ++ return __ret; \ ++ __ret; \ ++ }) ++ ++ ++static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); ++ return mdiobus_write(bus, addr, reg, val); ++#else ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->dev); ++ return mdiobus_write(bus, addr, reg, val); ++#endif ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0) ++static enum dsa_tag_protocol mv88e6063_get_tag_protocol(struct dsa_switch *ds) ++{ ++ return DSA_TAG_PROTO_TRAILER; ++} ++#endif ++ ++#define REG_WRITE(addr, reg, val) \ ++ ({ \ ++ int __ret; \ ++ \ ++ __ret = reg_write(ds, addr, reg, val); \ ++ if (__ret < 0) \ ++ return __ret; \ ++ }) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) ++static char *mv88e6063_drv_probe(struct device *host_dev, int sw_addr) ++#else ++static const char *mv88e6063_drv_probe(struct device *dsa_dev, ++ struct device *host_dev, int sw_addr, ++ void **_priv) ++#endif ++{ ++ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); ++ int ret; ++ ++ if (!bus) ++ return NULL; ++ ++ ret = mdiobus_read(bus, REG_PORT(0), 0x03); ++ if (ret >= 0) { ++ ret &= 0xfff0; ++ if (ret == 0x1530) ++ return "Marvell 88E6063"; ++ } ++ ++ return NULL; ++} ++ ++static int mv88e6063_switch_reset(struct dsa_switch *ds) ++{ ++ int i; ++ int ret; ++ ++ /* ++ * Set all ports to the disabled state. ++ */ ++ for (i = 0; i < NUM_PORTS; i++) { ++ ret = REG_READ(REG_PORT(i), 0x04); ++ REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); ++ } ++ ++ /* ++ * Wait for transmit queues to drain. ++ */ ++ msleep(2); ++ ++ /* ++ * Reset the switch. ++ */ ++ REG_WRITE(REG_GLOBAL, 0x0a, 0xa130); ++ ++ /* ++ * Wait up to one second for reset to complete. ++ */ ++ for (i = 0; i < 1000; i++) { ++ ret = REG_READ(REG_GLOBAL, 0x00); ++ if ((ret & 0x8000) == 0x0000) ++ break; ++ ++ msleep(1); ++ } ++ if (i == 1000) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++static int mv88e6063_setup_global(struct dsa_switch *ds) ++{ ++ /* ++ * Disable discarding of frames with excessive collisions, ++ * set the maximum frame size to 1536 bytes, and mask all ++ * interrupt sources. ++ */ ++ REG_WRITE(REG_GLOBAL, 0x04, 0x0800); ++ ++ /* ++ * Enable automatic address learning, set the address ++ * database size to 1024 entries, and set the default aging ++ * time to 5 minutes. ++ */ ++ REG_WRITE(REG_GLOBAL, 0x0a, 0x2130); ++ ++ return 0; ++} ++ ++static int mv88e6063_setup_port(struct dsa_switch *ds, int p) ++{ ++ int addr = REG_PORT(p); ++ ++ /* ++ * Do not force flow control, disable Ingress and Egress ++ * Header tagging, disable VLAN tunneling, and set the port ++ * state to Forwarding. Additionally, if this is the CPU ++ * port, enable Ingress and Egress Trailer tagging mode. ++ */ ++ REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ? 0x4103 : 0x0003); ++ ++ /* ++ * Port based VLAN map: give each port its own address ++ * database, allow the CPU port to talk to each of the 'real' ++ * ports, and allow each of the 'real' ports to only talk to ++ * the CPU port. ++ */ ++ REG_WRITE(addr, 0x06, ++ ((p & 0xf) << 12) | ++ (dsa_is_cpu_port(ds, p) ? ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) ++ ds->phys_port_mask : ++#else ++ ds->enabled_port_mask : ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++ (1 << ds->dst->cpu_port))); ++#else ++ (1 << ds->dst->cpu_dp->index))); ++#endif ++ ++ /* ++ * Port Association Vector: when learning source addresses ++ * of packets, add the address to the address database using ++ * a port bitmap that has only the bit for this port set and ++ * the other bits clear. ++ */ ++ REG_WRITE(addr, 0x0b, 1 << p); ++ ++ return 0; ++} ++ ++static int mv88e6063_setup(struct dsa_switch *ds) ++{ ++ int i; ++ int ret; ++ ++ ret = mv88e6063_switch_reset(ds); ++ if (ret < 0) ++ return ret; ++ ++ /* @@@ initialise atu */ ++ ++ ret = mv88e6063_setup_global(ds); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < NUM_PORTS; i++) { ++ ret = mv88e6063_setup_port(ds, i); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mv88e6063_set_addr(struct dsa_switch *ds, u8 *addr) ++{ ++ REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]); ++ REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]); ++ REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]); ++ ++ return 0; ++} ++ ++static int mv88e6063_port_to_phy_addr(int port) ++{ ++ if (port >= 0 && port <= NUM_PORTS) ++ return REG_PHY(port); ++ return -1; ++} ++ ++static int mv88e6063_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ int addr; ++ ++ addr = mv88e6063_port_to_phy_addr(port); ++ if (addr == -1) ++ return 0xffff; ++ ++ return reg_read(ds, addr, regnum); ++} ++ ++static int ++mv88e6063_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) ++{ ++ int addr; ++ ++ addr = mv88e6063_port_to_phy_addr(port); ++ if (addr == -1) ++ return 0xffff; ++ ++ return reg_write(ds, addr, regnum, val); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) ++static struct dsa_switch_driver mv88e6063_switch_ops = { ++#else ++static struct dsa_switch_ops mv88e6063_switch_ops = { ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) ++ .tag_protocol = htons(ETH_P_TRAILER), ++#else ++ .get_tag_protocol = mv88e6063_get_tag_protocol, ++#endif ++ .probe = mv88e6063_drv_probe, ++ .setup = mv88e6063_setup, ++ .set_addr = mv88e6063_set_addr, ++ .phy_read = mv88e6063_phy_read, ++ .phy_write = mv88e6063_phy_write, ++}; ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(4,13,0) ++static struct dsa_switch_driver mv88e6063_switch_drv = { ++ .ops = &mv88e6063_switch_ops, ++}; ++#endif ++ ++static int __init mv88e6063_init(void) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++ register_switch_driver(&mv88e6063_switch_ops); ++#else ++ register_switch_driver(&mv88e6063_switch_drv); ++#endif ++ return 0; ++} ++module_init(mv88e6063_init); ++ ++static void __exit mv88e6063_cleanup(void) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) ++ unregister_switch_driver(&mv88e6063_switch_ops); ++#else ++ unregister_switch_driver(&mv88e6063_switch_drv); ++#endif ++} ++module_exit(mv88e6063_cleanup); +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/Kconfig b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/Kconfig +new file mode 100644 +index 0000000000..42d544f731 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/Kconfig +@@ -0,0 +1,33 @@ ++config AG71XX ++ tristate "Atheros AR7XXX/AR9XXX built-in ethernet mac support" ++ depends on ATH79 ++ select PHYLIB ++ help ++ If you wish to compile a kernel for AR7XXX/91XXX and enable ++ ethernet support, then you should always answer Y to this. ++ ++if AG71XX ++ ++config AG71XX_DEBUG ++ bool "Atheros AR71xx built-in ethernet driver debugging" ++ default n ++ help ++ Atheros AR71xx built-in ethernet driver debugging messages. ++ ++config AG71XX_DEBUG_FS ++ bool "Atheros AR71xx built-in ethernet driver debugfs support" ++ depends on DEBUG_FS ++ default n ++ help ++ Say Y, if you need access to various statistics provided by ++ the ag71xx driver. ++ ++config AG71XX_AR8216_SUPPORT ++ bool "special support for the Atheros AR8216 switch" ++ default n ++ default y if ATH79_MACH_WNR2000 || ATH79_MACH_MZK_W04NU ++ help ++ Say 'y' here if you want to enable special support for the ++ Atheros AR8216 switch found on some boards. ++ ++endif +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/Makefile b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/Makefile +new file mode 100644 +index 0000000000..b3ec4084c8 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Atheros AR71xx built-in ethernet macs ++# ++ ++ag71xx-y += ag71xx_main.o ++ag71xx-y += ag71xx_ethtool.o ++ag71xx-y += ag71xx_phy.o ++ag71xx-y += ag71xx_mdio.o ++ag71xx-y += ag71xx_ar7240.o ++ ++ag71xx-$(CONFIG_AG71XX_DEBUG_FS) += ag71xx_debugfs.o ++ag71xx-$(CONFIG_AG71XX_AR8216_SUPPORT) += ag71xx_ar8216.o ++ ++obj-$(CONFIG_AG71XX) += ag71xx.o ++ +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +new file mode 100644 +index 0000000000..2d9a865043 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +@@ -0,0 +1,508 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * 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 __AG71XX_H ++#define __AG71XX_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#define AG71XX_DRV_NAME "ag71xx" ++#define AG71XX_DRV_VERSION "0.5.35" ++ ++/* ++ * For our NAPI weight bigger does *NOT* mean better - it means more ++ * D-cache misses and lots more wasted cycles than we'll ever ++ * possibly gain from saving instructions. ++ */ ++#define AG71XX_NAPI_WEIGHT 32 ++#define AG71XX_OOM_REFILL (1 + HZ/10) ++ ++#define AG71XX_INT_ERR (AG71XX_INT_RX_BE | AG71XX_INT_TX_BE) ++#define AG71XX_INT_TX (AG71XX_INT_TX_PS) ++#define AG71XX_INT_RX (AG71XX_INT_RX_PR | AG71XX_INT_RX_OF) ++ ++#define AG71XX_INT_POLL (AG71XX_INT_RX | AG71XX_INT_TX) ++#define AG71XX_INT_INIT (AG71XX_INT_ERR | AG71XX_INT_POLL) ++ ++#define AG71XX_TX_MTU_LEN 1540 ++ ++#define AG71XX_TX_RING_SPLIT 512 ++#define AG71XX_TX_RING_DS_PER_PKT DIV_ROUND_UP(AG71XX_TX_MTU_LEN, \ ++ AG71XX_TX_RING_SPLIT) ++#define AG71XX_TX_RING_SIZE_DEFAULT 128 ++#define AG71XX_RX_RING_SIZE_DEFAULT 256 ++ ++#define AG71XX_TX_RING_SIZE_MAX 128 ++#define AG71XX_RX_RING_SIZE_MAX 256 ++ ++#define QCA955X_SGMII_LINK_WAR_MAX_TRY 10 ++ ++#ifdef CONFIG_AG71XX_DEBUG ++#define DBG(fmt, args...) pr_debug(fmt, ## args) ++#else ++#define DBG(fmt, args...) do {} while (0) ++#endif ++ ++#define ag71xx_assert(_cond) \ ++do { \ ++ if (_cond) \ ++ break; \ ++ printk("%s,%d: assertion failed\n", __FILE__, __LINE__); \ ++ BUG(); \ ++} while (0) ++ ++struct ag71xx_desc { ++ u32 data; ++ u32 ctrl; ++#define DESC_EMPTY BIT(31) ++#define DESC_MORE BIT(24) ++#define DESC_PKTLEN_M 0xfff ++ u32 next; ++ u32 pad; ++} __attribute__((aligned(4))); ++ ++#define AG71XX_DESC_SIZE roundup(sizeof(struct ag71xx_desc), \ ++ L1_CACHE_BYTES) ++ ++struct ag71xx_buf { ++ union { ++ struct sk_buff *skb; ++ void *rx_buf; ++ }; ++ union { ++ dma_addr_t dma_addr; ++ unsigned int len; ++ }; ++}; ++ ++struct ag71xx_ring { ++ struct ag71xx_buf *buf; ++ u8 *descs_cpu; ++ dma_addr_t descs_dma; ++ u16 desc_split; ++ u16 order; ++ unsigned int curr; ++ unsigned int dirty; ++}; ++ ++struct ag71xx_mdio { ++ struct mii_bus *mii_bus; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ int mii_irq[PHY_MAX_ADDR]; ++#endif ++ void __iomem *mdio_base; ++ struct ag71xx_mdio_platform_data *pdata; ++}; ++ ++struct ag71xx_int_stats { ++ unsigned long rx_pr; ++ unsigned long rx_be; ++ unsigned long rx_of; ++ unsigned long tx_ps; ++ unsigned long tx_be; ++ unsigned long tx_ur; ++ unsigned long total; ++}; ++ ++struct ag71xx_napi_stats { ++ unsigned long napi_calls; ++ unsigned long rx_count; ++ unsigned long rx_packets; ++ unsigned long rx_packets_max; ++ unsigned long tx_count; ++ unsigned long tx_packets; ++ unsigned long tx_packets_max; ++ ++ unsigned long rx[AG71XX_NAPI_WEIGHT + 1]; ++ unsigned long tx[AG71XX_NAPI_WEIGHT + 1]; ++}; ++ ++struct ag71xx_debug { ++ struct dentry *debugfs_dir; ++ ++ struct ag71xx_int_stats int_stats; ++ struct ag71xx_napi_stats napi_stats; ++}; ++ ++struct ag71xx { ++ /* ++ * Critical data related to the per-packet data path are clustered ++ * early in this structure to help improve the D-cache footprint. ++ */ ++ struct ag71xx_ring rx_ring ____cacheline_aligned; ++ struct ag71xx_ring tx_ring ____cacheline_aligned; ++ ++ unsigned int max_frame_len; ++ unsigned int desc_pktlen_mask; ++ unsigned int rx_buf_size; ++ ++ struct net_device *dev; ++ struct platform_device *pdev; ++ spinlock_t lock; ++ struct napi_struct napi; ++ u32 msg_enable; ++ ++ /* ++ * From this point onwards we're not looking at per-packet fields. ++ */ ++ void __iomem *mac_base; ++ ++ struct ag71xx_desc *stop_desc; ++ dma_addr_t stop_desc_dma; ++ ++ struct mii_bus *mii_bus; ++ struct phy_device *phy_dev; ++ void *phy_priv; ++ ++ unsigned int link; ++ unsigned int speed; ++ int duplex; ++ ++ struct delayed_work restart_work; ++ struct delayed_work link_work; ++ struct timer_list oom_timer; ++ ++#ifdef CONFIG_AG71XX_DEBUG_FS ++ struct ag71xx_debug debug; ++#endif ++}; ++ ++extern struct ethtool_ops ag71xx_ethtool_ops; ++void ag71xx_link_adjust(struct ag71xx *ag); ++ ++int ag71xx_mdio_driver_init(void) __init; ++void ag71xx_mdio_driver_exit(void); ++ ++int ag71xx_phy_connect(struct ag71xx *ag); ++void ag71xx_phy_disconnect(struct ag71xx *ag); ++void ag71xx_phy_start(struct ag71xx *ag); ++void ag71xx_phy_stop(struct ag71xx *ag); ++ ++static inline struct ag71xx_platform_data *ag71xx_get_pdata(struct ag71xx *ag) ++{ ++ return ag->pdev->dev.platform_data; ++} ++ ++static inline int ag71xx_desc_empty(struct ag71xx_desc *desc) ++{ ++ return (desc->ctrl & DESC_EMPTY) != 0; ++} ++ ++static inline struct ag71xx_desc * ++ag71xx_ring_desc(struct ag71xx_ring *ring, int idx) ++{ ++ return (struct ag71xx_desc *) &ring->descs_cpu[idx * AG71XX_DESC_SIZE]; ++} ++ ++static inline int ++ag71xx_ring_size_order(int size) ++{ ++ return fls(size - 1); ++} ++ ++/* Register offsets */ ++#define AG71XX_REG_MAC_CFG1 0x0000 ++#define AG71XX_REG_MAC_CFG2 0x0004 ++#define AG71XX_REG_MAC_IPG 0x0008 ++#define AG71XX_REG_MAC_HDX 0x000c ++#define AG71XX_REG_MAC_MFL 0x0010 ++#define AG71XX_REG_MII_CFG 0x0020 ++#define AG71XX_REG_MII_CMD 0x0024 ++#define AG71XX_REG_MII_ADDR 0x0028 ++#define AG71XX_REG_MII_CTRL 0x002c ++#define AG71XX_REG_MII_STATUS 0x0030 ++#define AG71XX_REG_MII_IND 0x0034 ++#define AG71XX_REG_MAC_IFCTL 0x0038 ++#define AG71XX_REG_MAC_ADDR1 0x0040 ++#define AG71XX_REG_MAC_ADDR2 0x0044 ++#define AG71XX_REG_FIFO_CFG0 0x0048 ++#define AG71XX_REG_FIFO_CFG1 0x004c ++#define AG71XX_REG_FIFO_CFG2 0x0050 ++#define AG71XX_REG_FIFO_CFG3 0x0054 ++#define AG71XX_REG_FIFO_CFG4 0x0058 ++#define AG71XX_REG_FIFO_CFG5 0x005c ++#define AG71XX_REG_FIFO_RAM0 0x0060 ++#define AG71XX_REG_FIFO_RAM1 0x0064 ++#define AG71XX_REG_FIFO_RAM2 0x0068 ++#define AG71XX_REG_FIFO_RAM3 0x006c ++#define AG71XX_REG_FIFO_RAM4 0x0070 ++#define AG71XX_REG_FIFO_RAM5 0x0074 ++#define AG71XX_REG_FIFO_RAM6 0x0078 ++#define AG71XX_REG_FIFO_RAM7 0x007c ++ ++#define AG71XX_REG_TX_CTRL 0x0180 ++#define AG71XX_REG_TX_DESC 0x0184 ++#define AG71XX_REG_TX_STATUS 0x0188 ++#define AG71XX_REG_RX_CTRL 0x018c ++#define AG71XX_REG_RX_DESC 0x0190 ++#define AG71XX_REG_RX_STATUS 0x0194 ++#define AG71XX_REG_INT_ENABLE 0x0198 ++#define AG71XX_REG_INT_STATUS 0x019c ++ ++#define AG71XX_REG_FIFO_DEPTH 0x01a8 ++#define AG71XX_REG_RX_SM 0x01b0 ++#define AG71XX_REG_TX_SM 0x01b4 ++ ++#define MAC_CFG1_TXE BIT(0) /* Tx Enable */ ++#define MAC_CFG1_STX BIT(1) /* Synchronize Tx Enable */ ++#define MAC_CFG1_RXE BIT(2) /* Rx Enable */ ++#define MAC_CFG1_SRX BIT(3) /* Synchronize Rx Enable */ ++#define MAC_CFG1_TFC BIT(4) /* Tx Flow Control Enable */ ++#define MAC_CFG1_RFC BIT(5) /* Rx Flow Control Enable */ ++#define MAC_CFG1_LB BIT(8) /* Loopback mode */ ++#define MAC_CFG1_SR BIT(31) /* Soft Reset */ ++ ++#define MAC_CFG2_FDX BIT(0) ++#define MAC_CFG2_CRC_EN BIT(1) ++#define MAC_CFG2_PAD_CRC_EN BIT(2) ++#define MAC_CFG2_LEN_CHECK BIT(4) ++#define MAC_CFG2_HUGE_FRAME_EN BIT(5) ++#define MAC_CFG2_IF_1000 BIT(9) ++#define MAC_CFG2_IF_10_100 BIT(8) ++ ++#define FIFO_CFG0_WTM BIT(0) /* Watermark Module */ ++#define FIFO_CFG0_RXS BIT(1) /* Rx System Module */ ++#define FIFO_CFG0_RXF BIT(2) /* Rx Fabric Module */ ++#define FIFO_CFG0_TXS BIT(3) /* Tx System Module */ ++#define FIFO_CFG0_TXF BIT(4) /* Tx Fabric Module */ ++#define FIFO_CFG0_ALL (FIFO_CFG0_WTM | FIFO_CFG0_RXS | FIFO_CFG0_RXF \ ++ | FIFO_CFG0_TXS | FIFO_CFG0_TXF) ++ ++#define FIFO_CFG0_ENABLE_SHIFT 8 ++ ++#define FIFO_CFG4_DE BIT(0) /* Drop Event */ ++#define FIFO_CFG4_DV BIT(1) /* RX_DV Event */ ++#define FIFO_CFG4_FC BIT(2) /* False Carrier */ ++#define FIFO_CFG4_CE BIT(3) /* Code Error */ ++#define FIFO_CFG4_CR BIT(4) /* CRC error */ ++#define FIFO_CFG4_LM BIT(5) /* Length Mismatch */ ++#define FIFO_CFG4_LO BIT(6) /* Length out of range */ ++#define FIFO_CFG4_OK BIT(7) /* Packet is OK */ ++#define FIFO_CFG4_MC BIT(8) /* Multicast Packet */ ++#define FIFO_CFG4_BC BIT(9) /* Broadcast Packet */ ++#define FIFO_CFG4_DR BIT(10) /* Dribble */ ++#define FIFO_CFG4_LE BIT(11) /* Long Event */ ++#define FIFO_CFG4_CF BIT(12) /* Control Frame */ ++#define FIFO_CFG4_PF BIT(13) /* Pause Frame */ ++#define FIFO_CFG4_UO BIT(14) /* Unsupported Opcode */ ++#define FIFO_CFG4_VT BIT(15) /* VLAN tag detected */ ++#define FIFO_CFG4_FT BIT(16) /* Frame Truncated */ ++#define FIFO_CFG4_UC BIT(17) /* Unicast Packet */ ++ ++#define FIFO_CFG5_DE BIT(0) /* Drop Event */ ++#define FIFO_CFG5_DV BIT(1) /* RX_DV Event */ ++#define FIFO_CFG5_FC BIT(2) /* False Carrier */ ++#define FIFO_CFG5_CE BIT(3) /* Code Error */ ++#define FIFO_CFG5_LM BIT(4) /* Length Mismatch */ ++#define FIFO_CFG5_LO BIT(5) /* Length Out of Range */ ++#define FIFO_CFG5_OK BIT(6) /* Packet is OK */ ++#define FIFO_CFG5_MC BIT(7) /* Multicast Packet */ ++#define FIFO_CFG5_BC BIT(8) /* Broadcast Packet */ ++#define FIFO_CFG5_DR BIT(9) /* Dribble */ ++#define FIFO_CFG5_CF BIT(10) /* Control Frame */ ++#define FIFO_CFG5_PF BIT(11) /* Pause Frame */ ++#define FIFO_CFG5_UO BIT(12) /* Unsupported Opcode */ ++#define FIFO_CFG5_VT BIT(13) /* VLAN tag detected */ ++#define FIFO_CFG5_LE BIT(14) /* Long Event */ ++#define FIFO_CFG5_FT BIT(15) /* Frame Truncated */ ++#define FIFO_CFG5_16 BIT(16) /* unknown */ ++#define FIFO_CFG5_17 BIT(17) /* unknown */ ++#define FIFO_CFG5_SF BIT(18) /* Short Frame */ ++#define FIFO_CFG5_BM BIT(19) /* Byte Mode */ ++ ++#define AG71XX_INT_TX_PS BIT(0) ++#define AG71XX_INT_TX_UR BIT(1) ++#define AG71XX_INT_TX_BE BIT(3) ++#define AG71XX_INT_RX_PR BIT(4) ++#define AG71XX_INT_RX_OF BIT(6) ++#define AG71XX_INT_RX_BE BIT(7) ++ ++#define MAC_IFCTL_SPEED BIT(16) ++ ++#define MII_CFG_CLK_DIV_4 0 ++#define MII_CFG_CLK_DIV_6 2 ++#define MII_CFG_CLK_DIV_8 3 ++#define MII_CFG_CLK_DIV_10 4 ++#define MII_CFG_CLK_DIV_14 5 ++#define MII_CFG_CLK_DIV_20 6 ++#define MII_CFG_CLK_DIV_28 7 ++#define MII_CFG_CLK_DIV_34 8 ++#define MII_CFG_CLK_DIV_42 9 ++#define MII_CFG_CLK_DIV_50 10 ++#define MII_CFG_CLK_DIV_58 11 ++#define MII_CFG_CLK_DIV_66 12 ++#define MII_CFG_CLK_DIV_74 13 ++#define MII_CFG_CLK_DIV_82 14 ++#define MII_CFG_CLK_DIV_98 15 ++#define MII_CFG_RESET BIT(31) ++ ++#define MII_CMD_WRITE 0x0 ++#define MII_CMD_READ 0x1 ++#define MII_ADDR_SHIFT 8 ++#define MII_IND_BUSY BIT(0) ++#define MII_IND_INVALID BIT(2) ++ ++#define TX_CTRL_TXE BIT(0) /* Tx Enable */ ++ ++#define TX_STATUS_PS BIT(0) /* Packet Sent */ ++#define TX_STATUS_UR BIT(1) /* Tx Underrun */ ++#define TX_STATUS_BE BIT(3) /* Bus Error */ ++ ++#define RX_CTRL_RXE BIT(0) /* Rx Enable */ ++ ++#define RX_STATUS_PR BIT(0) /* Packet Received */ ++#define RX_STATUS_OF BIT(2) /* Rx Overflow */ ++#define RX_STATUS_BE BIT(3) /* Bus Error */ ++ ++static inline void ag71xx_check_reg_offset(struct ag71xx *ag, unsigned reg) ++{ ++ switch (reg) { ++ case AG71XX_REG_MAC_CFG1 ... AG71XX_REG_MAC_MFL: ++ case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_TX_SM: ++ case AG71XX_REG_MII_CFG: ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++ ++static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value) ++{ ++ ag71xx_check_reg_offset(ag, reg); ++ ++ __raw_writel(value, ag->mac_base + reg); ++ /* flush write */ ++ (void) __raw_readl(ag->mac_base + reg); ++} ++ ++static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg) ++{ ++ ag71xx_check_reg_offset(ag, reg); ++ ++ return __raw_readl(ag->mac_base + reg); ++} ++ ++static inline void ag71xx_sb(struct ag71xx *ag, unsigned reg, u32 mask) ++{ ++ void __iomem *r; ++ ++ ag71xx_check_reg_offset(ag, reg); ++ ++ r = ag->mac_base + reg; ++ __raw_writel(__raw_readl(r) | mask, r); ++ /* flush write */ ++ (void)__raw_readl(r); ++} ++ ++static inline void ag71xx_cb(struct ag71xx *ag, unsigned reg, u32 mask) ++{ ++ void __iomem *r; ++ ++ ag71xx_check_reg_offset(ag, reg); ++ ++ r = ag->mac_base + reg; ++ __raw_writel(__raw_readl(r) & ~mask, r); ++ /* flush write */ ++ (void) __raw_readl(r); ++} ++ ++static inline void ag71xx_int_enable(struct ag71xx *ag, u32 ints) ++{ ++ ag71xx_sb(ag, AG71XX_REG_INT_ENABLE, ints); ++} ++ ++static inline void ag71xx_int_disable(struct ag71xx *ag, u32 ints) ++{ ++ ag71xx_cb(ag, AG71XX_REG_INT_ENABLE, ints); ++} ++ ++#ifdef CONFIG_AG71XX_AR8216_SUPPORT ++void ag71xx_add_ar8216_header(struct ag71xx *ag, struct sk_buff *skb); ++int ag71xx_remove_ar8216_header(struct ag71xx *ag, struct sk_buff *skb, ++ int pktlen); ++static inline int ag71xx_has_ar8216(struct ag71xx *ag) ++{ ++ return ag71xx_get_pdata(ag)->has_ar8216; ++} ++#else ++static inline void ag71xx_add_ar8216_header(struct ag71xx *ag, ++ struct sk_buff *skb) ++{ ++} ++ ++static inline int ag71xx_remove_ar8216_header(struct ag71xx *ag, ++ struct sk_buff *skb, ++ int pktlen) ++{ ++ return 0; ++} ++static inline int ag71xx_has_ar8216(struct ag71xx *ag) ++{ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_AG71XX_DEBUG_FS ++int ag71xx_debugfs_root_init(void); ++void ag71xx_debugfs_root_exit(void); ++int ag71xx_debugfs_init(struct ag71xx *ag); ++void ag71xx_debugfs_exit(struct ag71xx *ag); ++void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, u32 status); ++void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx); ++#else ++static inline int ag71xx_debugfs_root_init(void) { return 0; } ++static inline void ag71xx_debugfs_root_exit(void) {} ++static inline int ag71xx_debugfs_init(struct ag71xx *ag) { return 0; } ++static inline void ag71xx_debugfs_exit(struct ag71xx *ag) {} ++static inline void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, ++ u32 status) {} ++static inline void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, ++ int rx, int tx) {} ++#endif /* CONFIG_AG71XX_DEBUG_FS */ ++ ++void ag71xx_ar7240_start(struct ag71xx *ag); ++void ag71xx_ar7240_stop(struct ag71xx *ag); ++int ag71xx_ar7240_init(struct ag71xx *ag); ++void ag71xx_ar7240_cleanup(struct ag71xx *ag); ++ ++int ag71xx_mdio_mii_read(struct ag71xx_mdio *am, int addr, int reg); ++void ag71xx_mdio_mii_write(struct ag71xx_mdio *am, int addr, int reg, u16 val); ++ ++u16 ar7240sw_phy_read(struct mii_bus *mii, unsigned phy_addr, ++ unsigned reg_addr); ++int ar7240sw_phy_write(struct mii_bus *mii, unsigned phy_addr, ++ unsigned reg_addr, u16 reg_val); ++ ++#endif /* _AG71XX_H */ +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c +new file mode 100644 +index 0000000000..2859c0dbe1 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c +@@ -0,0 +1,1386 @@ ++/* ++ * Driver for the built-in ethernet switch of the Atheros AR7240 SoC ++ * Copyright (c) 2010 Gabor Juhos ++ * Copyright (c) 2010 Felix Fietkau ++ * ++ * 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 ++#include "ag71xx.h" ++ ++#define BITM(_count) (BIT(_count) - 1) ++#define BITS(_shift, _count) (BITM(_count) << _shift) ++ ++#define AR7240_REG_MASK_CTRL 0x00 ++#define AR7240_MASK_CTRL_REVISION_M BITM(8) ++#define AR7240_MASK_CTRL_VERSION_M BITM(8) ++#define AR7240_MASK_CTRL_VERSION_S 8 ++#define AR7240_MASK_CTRL_VERSION_AR7240 0x01 ++#define AR7240_MASK_CTRL_VERSION_AR934X 0x02 ++#define AR7240_MASK_CTRL_SOFT_RESET BIT(31) ++ ++#define AR7240_REG_MAC_ADDR0 0x20 ++#define AR7240_REG_MAC_ADDR1 0x24 ++ ++#define AR7240_REG_FLOOD_MASK 0x2c ++#define AR7240_FLOOD_MASK_BROAD_TO_CPU BIT(26) ++ ++#define AR7240_REG_GLOBAL_CTRL 0x30 ++#define AR7240_GLOBAL_CTRL_MTU_M BITM(11) ++#define AR9340_GLOBAL_CTRL_MTU_M BITM(14) ++ ++#define AR7240_REG_VTU 0x0040 ++#define AR7240_VTU_OP BITM(3) ++#define AR7240_VTU_OP_NOOP 0x0 ++#define AR7240_VTU_OP_FLUSH 0x1 ++#define AR7240_VTU_OP_LOAD 0x2 ++#define AR7240_VTU_OP_PURGE 0x3 ++#define AR7240_VTU_OP_REMOVE_PORT 0x4 ++#define AR7240_VTU_ACTIVE BIT(3) ++#define AR7240_VTU_FULL BIT(4) ++#define AR7240_VTU_PORT BITS(8, 4) ++#define AR7240_VTU_PORT_S 8 ++#define AR7240_VTU_VID BITS(16, 12) ++#define AR7240_VTU_VID_S 16 ++#define AR7240_VTU_PRIO BITS(28, 3) ++#define AR7240_VTU_PRIO_S 28 ++#define AR7240_VTU_PRIO_EN BIT(31) ++ ++#define AR7240_REG_VTU_DATA 0x0044 ++#define AR7240_VTUDATA_MEMBER BITS(0, 10) ++#define AR7240_VTUDATA_VALID BIT(11) ++ ++#define AR7240_REG_ATU 0x50 ++#define AR7240_ATU_FLUSH_ALL 0x1 ++ ++#define AR7240_REG_AT_CTRL 0x5c ++#define AR7240_AT_CTRL_AGE_TIME BITS(0, 15) ++#define AR7240_AT_CTRL_AGE_EN BIT(17) ++#define AR7240_AT_CTRL_LEARN_CHANGE BIT(18) ++#define AR7240_AT_CTRL_RESERVED BIT(19) ++#define AR7240_AT_CTRL_ARP_EN BIT(20) ++ ++#define AR7240_REG_TAG_PRIORITY 0x70 ++ ++#define AR7240_REG_SERVICE_TAG 0x74 ++#define AR7240_SERVICE_TAG_M BITM(16) ++ ++#define AR7240_REG_CPU_PORT 0x78 ++#define AR7240_MIRROR_PORT_S 4 ++#define AR7240_MIRROR_PORT_M BITM(4) ++#define AR7240_CPU_PORT_EN BIT(8) ++ ++#define AR7240_REG_MIB_FUNCTION0 0x80 ++#define AR7240_MIB_TIMER_M BITM(16) ++#define AR7240_MIB_AT_HALF_EN BIT(16) ++#define AR7240_MIB_BUSY BIT(17) ++#define AR7240_MIB_FUNC_S 24 ++#define AR7240_MIB_FUNC_M BITM(3) ++#define AR7240_MIB_FUNC_NO_OP 0x0 ++#define AR7240_MIB_FUNC_FLUSH 0x1 ++#define AR7240_MIB_FUNC_CAPTURE 0x3 ++ ++#define AR7240_REG_MDIO_CTRL 0x98 ++#define AR7240_MDIO_CTRL_DATA_M BITM(16) ++#define AR7240_MDIO_CTRL_REG_ADDR_S 16 ++#define AR7240_MDIO_CTRL_PHY_ADDR_S 21 ++#define AR7240_MDIO_CTRL_CMD_WRITE 0 ++#define AR7240_MDIO_CTRL_CMD_READ BIT(27) ++#define AR7240_MDIO_CTRL_MASTER_EN BIT(30) ++#define AR7240_MDIO_CTRL_BUSY BIT(31) ++ ++#define AR7240_REG_PORT_BASE(_port) (0x100 + (_port) * 0x100) ++ ++#define AR7240_REG_PORT_STATUS(_port) (AR7240_REG_PORT_BASE((_port)) + 0x00) ++#define AR7240_PORT_STATUS_SPEED_S 0 ++#define AR7240_PORT_STATUS_SPEED_M BITM(2) ++#define AR7240_PORT_STATUS_SPEED_10 0 ++#define AR7240_PORT_STATUS_SPEED_100 1 ++#define AR7240_PORT_STATUS_SPEED_1000 2 ++#define AR7240_PORT_STATUS_TXMAC BIT(2) ++#define AR7240_PORT_STATUS_RXMAC BIT(3) ++#define AR7240_PORT_STATUS_TXFLOW BIT(4) ++#define AR7240_PORT_STATUS_RXFLOW BIT(5) ++#define AR7240_PORT_STATUS_DUPLEX BIT(6) ++#define AR7240_PORT_STATUS_LINK_UP BIT(8) ++#define AR7240_PORT_STATUS_LINK_AUTO BIT(9) ++#define AR7240_PORT_STATUS_LINK_PAUSE BIT(10) ++ ++#define AR7240_REG_PORT_CTRL(_port) (AR7240_REG_PORT_BASE((_port)) + 0x04) ++#define AR7240_PORT_CTRL_STATE_M BITM(3) ++#define AR7240_PORT_CTRL_STATE_DISABLED 0 ++#define AR7240_PORT_CTRL_STATE_BLOCK 1 ++#define AR7240_PORT_CTRL_STATE_LISTEN 2 ++#define AR7240_PORT_CTRL_STATE_LEARN 3 ++#define AR7240_PORT_CTRL_STATE_FORWARD 4 ++#define AR7240_PORT_CTRL_LEARN_LOCK BIT(7) ++#define AR7240_PORT_CTRL_VLAN_MODE_S 8 ++#define AR7240_PORT_CTRL_VLAN_MODE_KEEP 0 ++#define AR7240_PORT_CTRL_VLAN_MODE_STRIP 1 ++#define AR7240_PORT_CTRL_VLAN_MODE_ADD 2 ++#define AR7240_PORT_CTRL_VLAN_MODE_DOUBLE_TAG 3 ++#define AR7240_PORT_CTRL_IGMP_SNOOP BIT(10) ++#define AR7240_PORT_CTRL_HEADER BIT(11) ++#define AR7240_PORT_CTRL_MAC_LOOP BIT(12) ++#define AR7240_PORT_CTRL_SINGLE_VLAN BIT(13) ++#define AR7240_PORT_CTRL_LEARN BIT(14) ++#define AR7240_PORT_CTRL_DOUBLE_TAG BIT(15) ++#define AR7240_PORT_CTRL_MIRROR_TX BIT(16) ++#define AR7240_PORT_CTRL_MIRROR_RX BIT(17) ++ ++#define AR7240_REG_PORT_VLAN(_port) (AR7240_REG_PORT_BASE((_port)) + 0x08) ++ ++#define AR7240_PORT_VLAN_DEFAULT_ID_S 0 ++#define AR7240_PORT_VLAN_DEST_PORTS_S 16 ++#define AR7240_PORT_VLAN_MODE_S 30 ++#define AR7240_PORT_VLAN_MODE_PORT_ONLY 0 ++#define AR7240_PORT_VLAN_MODE_PORT_FALLBACK 1 ++#define AR7240_PORT_VLAN_MODE_VLAN_ONLY 2 ++#define AR7240_PORT_VLAN_MODE_SECURE 3 ++ ++ ++#define AR7240_REG_STATS_BASE(_port) (0x20000 + (_port) * 0x100) ++ ++#define AR7240_STATS_RXBROAD 0x00 ++#define AR7240_STATS_RXPAUSE 0x04 ++#define AR7240_STATS_RXMULTI 0x08 ++#define AR7240_STATS_RXFCSERR 0x0c ++#define AR7240_STATS_RXALIGNERR 0x10 ++#define AR7240_STATS_RXRUNT 0x14 ++#define AR7240_STATS_RXFRAGMENT 0x18 ++#define AR7240_STATS_RX64BYTE 0x1c ++#define AR7240_STATS_RX128BYTE 0x20 ++#define AR7240_STATS_RX256BYTE 0x24 ++#define AR7240_STATS_RX512BYTE 0x28 ++#define AR7240_STATS_RX1024BYTE 0x2c ++#define AR7240_STATS_RX1518BYTE 0x30 ++#define AR7240_STATS_RXMAXBYTE 0x34 ++#define AR7240_STATS_RXTOOLONG 0x38 ++#define AR7240_STATS_RXGOODBYTE 0x3c ++#define AR7240_STATS_RXBADBYTE 0x44 ++#define AR7240_STATS_RXOVERFLOW 0x4c ++#define AR7240_STATS_FILTERED 0x50 ++#define AR7240_STATS_TXBROAD 0x54 ++#define AR7240_STATS_TXPAUSE 0x58 ++#define AR7240_STATS_TXMULTI 0x5c ++#define AR7240_STATS_TXUNDERRUN 0x60 ++#define AR7240_STATS_TX64BYTE 0x64 ++#define AR7240_STATS_TX128BYTE 0x68 ++#define AR7240_STATS_TX256BYTE 0x6c ++#define AR7240_STATS_TX512BYTE 0x70 ++#define AR7240_STATS_TX1024BYTE 0x74 ++#define AR7240_STATS_TX1518BYTE 0x78 ++#define AR7240_STATS_TXMAXBYTE 0x7c ++#define AR7240_STATS_TXOVERSIZE 0x80 ++#define AR7240_STATS_TXBYTE 0x84 ++#define AR7240_STATS_TXCOLLISION 0x8c ++#define AR7240_STATS_TXABORTCOL 0x90 ++#define AR7240_STATS_TXMULTICOL 0x94 ++#define AR7240_STATS_TXSINGLECOL 0x98 ++#define AR7240_STATS_TXEXCDEFER 0x9c ++#define AR7240_STATS_TXDEFER 0xa0 ++#define AR7240_STATS_TXLATECOL 0xa4 ++ ++#define AR7240_PORT_CPU 0 ++#define AR7240_NUM_PORTS 6 ++#define AR7240_NUM_PHYS 5 ++ ++#define AR7240_PHY_ID1 0x004d ++#define AR7240_PHY_ID2 0xd041 ++ ++#define AR934X_PHY_ID1 0x004d ++#define AR934X_PHY_ID2 0xd042 ++ ++#define AR7240_MAX_VLANS 16 ++ ++#define AR934X_REG_OPER_MODE0 0x04 ++#define AR934X_OPER_MODE0_MAC_GMII_EN BIT(6) ++#define AR934X_OPER_MODE0_PHY_MII_EN BIT(10) ++ ++#define AR934X_REG_OPER_MODE1 0x08 ++#define AR934X_REG_OPER_MODE1_PHY4_MII_EN BIT(28) ++ ++#define AR934X_REG_FLOOD_MASK 0x2c ++#define AR934X_FLOOD_MASK_MC_DP(_p) BIT(16 + (_p)) ++#define AR934X_FLOOD_MASK_BC_DP(_p) BIT(25 + (_p)) ++ ++#define AR934X_REG_QM_CTRL 0x3c ++#define AR934X_QM_CTRL_ARP_EN BIT(15) ++ ++#define AR934X_REG_AT_CTRL 0x5c ++#define AR934X_AT_CTRL_AGE_TIME BITS(0, 15) ++#define AR934X_AT_CTRL_AGE_EN BIT(17) ++#define AR934X_AT_CTRL_LEARN_CHANGE BIT(18) ++ ++#define AR934X_MIB_ENABLE BIT(30) ++ ++#define AR934X_REG_PORT_BASE(_port) (0x100 + (_port) * 0x100) ++ ++#define AR934X_REG_PORT_VLAN1(_port) (AR934X_REG_PORT_BASE((_port)) + 0x08) ++#define AR934X_PORT_VLAN1_DEFAULT_SVID_S 0 ++#define AR934X_PORT_VLAN1_FORCE_DEFAULT_VID_EN BIT(12) ++#define AR934X_PORT_VLAN1_PORT_TLS_MODE BIT(13) ++#define AR934X_PORT_VLAN1_PORT_VLAN_PROP_EN BIT(14) ++#define AR934X_PORT_VLAN1_PORT_CLONE_EN BIT(15) ++#define AR934X_PORT_VLAN1_DEFAULT_CVID_S 16 ++#define AR934X_PORT_VLAN1_FORCE_PORT_VLAN_EN BIT(28) ++#define AR934X_PORT_VLAN1_ING_PORT_PRI_S 29 ++ ++#define AR934X_REG_PORT_VLAN2(_port) (AR934X_REG_PORT_BASE((_port)) + 0x0c) ++#define AR934X_PORT_VLAN2_PORT_VID_MEM_S 16 ++#define AR934X_PORT_VLAN2_8021Q_MODE_S 30 ++#define AR934X_PORT_VLAN2_8021Q_MODE_PORT_ONLY 0 ++#define AR934X_PORT_VLAN2_8021Q_MODE_PORT_FALLBACK 1 ++#define AR934X_PORT_VLAN2_8021Q_MODE_VLAN_ONLY 2 ++#define AR934X_PORT_VLAN2_8021Q_MODE_SECURE 3 ++ ++#define sw_to_ar7240(_dev) container_of(_dev, struct ar7240sw, swdev) ++ ++struct ar7240sw_port_stat { ++ unsigned long rx_broadcast; ++ unsigned long rx_pause; ++ unsigned long rx_multicast; ++ unsigned long rx_fcs_error; ++ unsigned long rx_align_error; ++ unsigned long rx_runt; ++ unsigned long rx_fragments; ++ unsigned long rx_64byte; ++ unsigned long rx_128byte; ++ unsigned long rx_256byte; ++ unsigned long rx_512byte; ++ unsigned long rx_1024byte; ++ unsigned long rx_1518byte; ++ unsigned long rx_maxbyte; ++ unsigned long rx_toolong; ++ unsigned long rx_good_byte; ++ unsigned long rx_bad_byte; ++ unsigned long rx_overflow; ++ unsigned long filtered; ++ ++ unsigned long tx_broadcast; ++ unsigned long tx_pause; ++ unsigned long tx_multicast; ++ unsigned long tx_underrun; ++ unsigned long tx_64byte; ++ unsigned long tx_128byte; ++ unsigned long tx_256byte; ++ unsigned long tx_512byte; ++ unsigned long tx_1024byte; ++ unsigned long tx_1518byte; ++ unsigned long tx_maxbyte; ++ unsigned long tx_oversize; ++ unsigned long tx_byte; ++ unsigned long tx_collision; ++ unsigned long tx_abortcol; ++ unsigned long tx_multicol; ++ unsigned long tx_singlecol; ++ unsigned long tx_excdefer; ++ unsigned long tx_defer; ++ unsigned long tx_xlatecol; ++}; ++ ++struct ar7240sw { ++ struct mii_bus *mii_bus; ++ struct ag71xx_switch_platform_data *swdata; ++ struct switch_dev swdev; ++ int num_ports; ++ u8 ver; ++ bool vlan; ++ u16 vlan_id[AR7240_MAX_VLANS]; ++ u8 vlan_table[AR7240_MAX_VLANS]; ++ u8 vlan_tagged; ++ u16 pvid[AR7240_NUM_PORTS]; ++ char buf[80]; ++ ++ rwlock_t stats_lock; ++ struct ar7240sw_port_stat port_stats[AR7240_NUM_PORTS]; ++}; ++ ++struct ar7240sw_hw_stat { ++ char string[ETH_GSTRING_LEN]; ++ int sizeof_stat; ++ int reg; ++}; ++ ++static DEFINE_MUTEX(reg_mutex); ++ ++static inline int sw_is_ar7240(struct ar7240sw *as) ++{ ++ return as->ver == AR7240_MASK_CTRL_VERSION_AR7240; ++} ++ ++static inline int sw_is_ar934x(struct ar7240sw *as) ++{ ++ return as->ver == AR7240_MASK_CTRL_VERSION_AR934X; ++} ++ ++static inline u32 ar7240sw_port_mask(struct ar7240sw *as, int port) ++{ ++ return BIT(port); ++} ++ ++static inline u32 ar7240sw_port_mask_all(struct ar7240sw *as) ++{ ++ return BIT(as->swdev.ports) - 1; ++} ++ ++static inline u32 ar7240sw_port_mask_but(struct ar7240sw *as, int port) ++{ ++ return ar7240sw_port_mask_all(as) & ~BIT(port); ++} ++ ++static inline u16 mk_phy_addr(u32 reg) ++{ ++ return 0x17 & ((reg >> 4) | 0x10); ++} ++ ++static inline u16 mk_phy_reg(u32 reg) ++{ ++ return (reg << 1) & 0x1e; ++} ++ ++static inline u16 mk_high_addr(u32 reg) ++{ ++ return (reg >> 7) & 0x1ff; ++} ++ ++static u32 __ar7240sw_reg_read(struct mii_bus *mii, u32 reg) ++{ ++ unsigned long flags; ++ u16 phy_addr; ++ u16 phy_reg; ++ u32 hi, lo; ++ ++ reg = (reg & 0xfffffffc) >> 2; ++ phy_addr = mk_phy_addr(reg); ++ phy_reg = mk_phy_reg(reg); ++ ++ local_irq_save(flags); ++ ag71xx_mdio_mii_write(mii->priv, 0x1f, 0x10, mk_high_addr(reg)); ++ lo = (u32) ag71xx_mdio_mii_read(mii->priv, phy_addr, phy_reg); ++ hi = (u32) ag71xx_mdio_mii_read(mii->priv, phy_addr, phy_reg + 1); ++ local_irq_restore(flags); ++ ++ return (hi << 16) | lo; ++} ++ ++static void __ar7240sw_reg_write(struct mii_bus *mii, u32 reg, u32 val) ++{ ++ unsigned long flags; ++ u16 phy_addr; ++ u16 phy_reg; ++ ++ reg = (reg & 0xfffffffc) >> 2; ++ phy_addr = mk_phy_addr(reg); ++ phy_reg = mk_phy_reg(reg); ++ ++ local_irq_save(flags); ++ ag71xx_mdio_mii_write(mii->priv, 0x1f, 0x10, mk_high_addr(reg)); ++ ag71xx_mdio_mii_write(mii->priv, phy_addr, phy_reg + 1, (val >> 16)); ++ ag71xx_mdio_mii_write(mii->priv, phy_addr, phy_reg, (val & 0xffff)); ++ local_irq_restore(flags); ++} ++ ++static u32 ar7240sw_reg_read(struct mii_bus *mii, u32 reg_addr) ++{ ++ u32 ret; ++ ++ mutex_lock(®_mutex); ++ ret = __ar7240sw_reg_read(mii, reg_addr); ++ mutex_unlock(®_mutex); ++ ++ return ret; ++} ++ ++static void ar7240sw_reg_write(struct mii_bus *mii, u32 reg_addr, u32 reg_val) ++{ ++ mutex_lock(®_mutex); ++ __ar7240sw_reg_write(mii, reg_addr, reg_val); ++ mutex_unlock(®_mutex); ++} ++ ++static u32 ar7240sw_reg_rmw(struct mii_bus *mii, u32 reg, u32 mask, u32 val) ++{ ++ u32 t; ++ ++ mutex_lock(®_mutex); ++ t = __ar7240sw_reg_read(mii, reg); ++ t &= ~mask; ++ t |= val; ++ __ar7240sw_reg_write(mii, reg, t); ++ mutex_unlock(®_mutex); ++ ++ return t; ++} ++ ++static void ar7240sw_reg_set(struct mii_bus *mii, u32 reg, u32 val) ++{ ++ u32 t; ++ ++ mutex_lock(®_mutex); ++ t = __ar7240sw_reg_read(mii, reg); ++ t |= val; ++ __ar7240sw_reg_write(mii, reg, t); ++ mutex_unlock(®_mutex); ++} ++ ++static int __ar7240sw_reg_wait(struct mii_bus *mii, u32 reg, u32 mask, u32 val, ++ unsigned timeout) ++{ ++ int i; ++ ++ for (i = 0; i < timeout; i++) { ++ u32 t; ++ ++ t = __ar7240sw_reg_read(mii, reg); ++ if ((t & mask) == val) ++ return 0; ++ ++ usleep_range(1000, 2000); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static int ar7240sw_reg_wait(struct mii_bus *mii, u32 reg, u32 mask, u32 val, ++ unsigned timeout) ++{ ++ int ret; ++ ++ mutex_lock(®_mutex); ++ ret = __ar7240sw_reg_wait(mii, reg, mask, val, timeout); ++ mutex_unlock(®_mutex); ++ return ret; ++} ++ ++u16 ar7240sw_phy_read(struct mii_bus *mii, unsigned phy_addr, ++ unsigned reg_addr) ++{ ++ u32 t, val = 0xffff; ++ int err; ++ ++ if (phy_addr >= AR7240_NUM_PHYS) ++ return 0xffff; ++ ++ mutex_lock(®_mutex); ++ t = (reg_addr << AR7240_MDIO_CTRL_REG_ADDR_S) | ++ (phy_addr << AR7240_MDIO_CTRL_PHY_ADDR_S) | ++ AR7240_MDIO_CTRL_MASTER_EN | ++ AR7240_MDIO_CTRL_BUSY | ++ AR7240_MDIO_CTRL_CMD_READ; ++ ++ __ar7240sw_reg_write(mii, AR7240_REG_MDIO_CTRL, t); ++ err = __ar7240sw_reg_wait(mii, AR7240_REG_MDIO_CTRL, ++ AR7240_MDIO_CTRL_BUSY, 0, 5); ++ if (!err) ++ val = __ar7240sw_reg_read(mii, AR7240_REG_MDIO_CTRL); ++ mutex_unlock(®_mutex); ++ ++ return val & AR7240_MDIO_CTRL_DATA_M; ++} ++ ++int ar7240sw_phy_write(struct mii_bus *mii, unsigned phy_addr, ++ unsigned reg_addr, u16 reg_val) ++{ ++ u32 t; ++ int ret; ++ ++ if (phy_addr >= AR7240_NUM_PHYS) ++ return -EINVAL; ++ ++ mutex_lock(®_mutex); ++ t = (phy_addr << AR7240_MDIO_CTRL_PHY_ADDR_S) | ++ (reg_addr << AR7240_MDIO_CTRL_REG_ADDR_S) | ++ AR7240_MDIO_CTRL_MASTER_EN | ++ AR7240_MDIO_CTRL_BUSY | ++ AR7240_MDIO_CTRL_CMD_WRITE | ++ reg_val; ++ ++ __ar7240sw_reg_write(mii, AR7240_REG_MDIO_CTRL, t); ++ ret = __ar7240sw_reg_wait(mii, AR7240_REG_MDIO_CTRL, ++ AR7240_MDIO_CTRL_BUSY, 0, 5); ++ mutex_unlock(®_mutex); ++ ++ return ret; ++} ++ ++static int ar7240sw_capture_stats(struct ar7240sw *as) ++{ ++ struct mii_bus *mii = as->mii_bus; ++ int port; ++ int ret; ++ ++ write_lock(&as->stats_lock); ++ ++ /* Capture the hardware statistics for all ports */ ++ ar7240sw_reg_rmw(mii, AR7240_REG_MIB_FUNCTION0, ++ (AR7240_MIB_FUNC_M << AR7240_MIB_FUNC_S), ++ (AR7240_MIB_FUNC_CAPTURE << AR7240_MIB_FUNC_S)); ++ ++ /* Wait for the capturing to complete. */ ++ ret = ar7240sw_reg_wait(mii, AR7240_REG_MIB_FUNCTION0, ++ AR7240_MIB_BUSY, 0, 10); ++ ++ if (ret) ++ goto unlock; ++ ++ for (port = 0; port < AR7240_NUM_PORTS; port++) { ++ unsigned int base; ++ struct ar7240sw_port_stat *stats; ++ ++ base = AR7240_REG_STATS_BASE(port); ++ stats = &as->port_stats[port]; ++ ++#define READ_STAT(_r) ar7240sw_reg_read(mii, base + AR7240_STATS_ ## _r) ++ ++ stats->rx_good_byte += READ_STAT(RXGOODBYTE); ++ stats->tx_byte += READ_STAT(TXBYTE); ++ ++#undef READ_STAT ++ } ++ ++ ret = 0; ++ ++unlock: ++ write_unlock(&as->stats_lock); ++ return ret; ++} ++ ++static void ar7240sw_disable_port(struct ar7240sw *as, unsigned port) ++{ ++ ar7240sw_reg_write(as->mii_bus, AR7240_REG_PORT_CTRL(port), ++ AR7240_PORT_CTRL_STATE_DISABLED); ++} ++ ++static void ar7240sw_setup(struct ar7240sw *as) ++{ ++ struct mii_bus *mii = as->mii_bus; ++ ++ /* Enable CPU port, and disable mirror port */ ++ ar7240sw_reg_write(mii, AR7240_REG_CPU_PORT, ++ AR7240_CPU_PORT_EN | ++ (15 << AR7240_MIRROR_PORT_S)); ++ ++ /* Setup TAG priority mapping */ ++ ar7240sw_reg_write(mii, AR7240_REG_TAG_PRIORITY, 0xfa50); ++ ++ if (sw_is_ar934x(as)) { ++ /* Enable aging, MAC replacing */ ++ ar7240sw_reg_write(mii, AR934X_REG_AT_CTRL, ++ 0x2b /* 5 min age time */ | ++ AR934X_AT_CTRL_AGE_EN | ++ AR934X_AT_CTRL_LEARN_CHANGE); ++ /* Enable ARP frame acknowledge */ ++ ar7240sw_reg_set(mii, AR934X_REG_QM_CTRL, ++ AR934X_QM_CTRL_ARP_EN); ++ /* Enable Broadcast/Multicast frames transmitted to the CPU */ ++ ar7240sw_reg_set(mii, AR934X_REG_FLOOD_MASK, ++ AR934X_FLOOD_MASK_BC_DP(0) | ++ AR934X_FLOOD_MASK_MC_DP(0)); ++ ++ /* setup MTU */ ++ ar7240sw_reg_rmw(mii, AR7240_REG_GLOBAL_CTRL, ++ AR9340_GLOBAL_CTRL_MTU_M, ++ AR9340_GLOBAL_CTRL_MTU_M); ++ ++ /* Enable MIB counters */ ++ ar7240sw_reg_set(mii, AR7240_REG_MIB_FUNCTION0, ++ AR934X_MIB_ENABLE); ++ ++ } else { ++ /* Enable ARP frame acknowledge, aging, MAC replacing */ ++ ar7240sw_reg_write(mii, AR7240_REG_AT_CTRL, ++ AR7240_AT_CTRL_RESERVED | ++ 0x2b /* 5 min age time */ | ++ AR7240_AT_CTRL_AGE_EN | ++ AR7240_AT_CTRL_ARP_EN | ++ AR7240_AT_CTRL_LEARN_CHANGE); ++ /* Enable Broadcast frames transmitted to the CPU */ ++ ar7240sw_reg_set(mii, AR7240_REG_FLOOD_MASK, ++ AR7240_FLOOD_MASK_BROAD_TO_CPU); ++ ++ /* setup MTU */ ++ ar7240sw_reg_rmw(mii, AR7240_REG_GLOBAL_CTRL, ++ AR7240_GLOBAL_CTRL_MTU_M, ++ AR7240_GLOBAL_CTRL_MTU_M); ++ } ++ ++ /* setup Service TAG */ ++ ar7240sw_reg_rmw(mii, AR7240_REG_SERVICE_TAG, AR7240_SERVICE_TAG_M, 0); ++} ++ ++/* inspired by phy_poll_reset in drivers/net/phy/phy_device.c */ ++static int ++ar7240sw_phy_poll_reset(struct mii_bus *bus) ++{ ++ const unsigned int sleep_msecs = 20; ++ int ret, elapsed, i; ++ ++ for (elapsed = sleep_msecs; elapsed <= 600; ++ elapsed += sleep_msecs) { ++ msleep(sleep_msecs); ++ for (i = 0; i < AR7240_NUM_PHYS; i++) { ++ ret = ar7240sw_phy_read(bus, i, MII_BMCR); ++ if (ret < 0) ++ return ret; ++ if (ret & BMCR_RESET) ++ break; ++ if (i == AR7240_NUM_PHYS - 1) { ++ usleep_range(1000, 2000); ++ return 0; ++ } ++ } ++ } ++ return -ETIMEDOUT; ++} ++ ++static int ar7240sw_reset(struct ar7240sw *as) ++{ ++ struct mii_bus *mii = as->mii_bus; ++ int ret; ++ int i; ++ ++ /* Set all ports to disabled state. */ ++ for (i = 0; i < AR7240_NUM_PORTS; i++) ++ ar7240sw_disable_port(as, i); ++ ++ /* Wait for transmit queues to drain. */ ++ usleep_range(2000, 3000); ++ ++ /* Reset the switch. */ ++ ar7240sw_reg_write(mii, AR7240_REG_MASK_CTRL, ++ AR7240_MASK_CTRL_SOFT_RESET); ++ ++ ret = ar7240sw_reg_wait(mii, AR7240_REG_MASK_CTRL, ++ AR7240_MASK_CTRL_SOFT_RESET, 0, 1000); ++ ++ /* setup PHYs */ ++ for (i = 0; i < AR7240_NUM_PHYS; i++) { ++ ar7240sw_phy_write(mii, i, MII_ADVERTISE, ++ ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ++ ADVERTISE_PAUSE_ASYM); ++ ar7240sw_phy_write(mii, i, MII_BMCR, ++ BMCR_RESET | BMCR_ANENABLE); ++ } ++ ret = ar7240sw_phy_poll_reset(mii); ++ if (ret) ++ return ret; ++ ++ ar7240sw_setup(as); ++ return ret; ++} ++ ++static void ar7240sw_setup_port(struct ar7240sw *as, unsigned port, u8 portmask) ++{ ++ struct mii_bus *mii = as->mii_bus; ++ u32 ctrl; ++ u32 vid, mode; ++ ++ ctrl = AR7240_PORT_CTRL_STATE_FORWARD | AR7240_PORT_CTRL_LEARN | ++ AR7240_PORT_CTRL_SINGLE_VLAN; ++ ++ if (port == AR7240_PORT_CPU) { ++ ar7240sw_reg_write(mii, AR7240_REG_PORT_STATUS(port), ++ AR7240_PORT_STATUS_SPEED_1000 | ++ AR7240_PORT_STATUS_TXFLOW | ++ AR7240_PORT_STATUS_RXFLOW | ++ AR7240_PORT_STATUS_TXMAC | ++ AR7240_PORT_STATUS_RXMAC | ++ AR7240_PORT_STATUS_DUPLEX); ++ } else { ++ ar7240sw_reg_write(mii, AR7240_REG_PORT_STATUS(port), ++ AR7240_PORT_STATUS_LINK_AUTO); ++ } ++ ++ /* Set the default VID for this port */ ++ if (as->vlan) { ++ vid = as->vlan_id[as->pvid[port]]; ++ mode = AR7240_PORT_VLAN_MODE_SECURE; ++ } else { ++ vid = port; ++ mode = AR7240_PORT_VLAN_MODE_PORT_ONLY; ++ } ++ ++ if (as->vlan) { ++ if (as->vlan_tagged & BIT(port)) ++ ctrl |= AR7240_PORT_CTRL_VLAN_MODE_ADD << ++ AR7240_PORT_CTRL_VLAN_MODE_S; ++ else ++ ctrl |= AR7240_PORT_CTRL_VLAN_MODE_STRIP << ++ AR7240_PORT_CTRL_VLAN_MODE_S; ++ } else { ++ ctrl |= AR7240_PORT_CTRL_VLAN_MODE_KEEP << ++ AR7240_PORT_CTRL_VLAN_MODE_S; ++ } ++ ++ if (!portmask) { ++ if (port == AR7240_PORT_CPU) ++ portmask = ar7240sw_port_mask_but(as, AR7240_PORT_CPU); ++ else ++ portmask = ar7240sw_port_mask(as, AR7240_PORT_CPU); ++ } ++ ++ /* preserve mirror rx&tx flags */ ++ ctrl |= ar7240sw_reg_read(mii, AR7240_REG_PORT_CTRL(port)) & ++ (AR7240_PORT_CTRL_MIRROR_RX | AR7240_PORT_CTRL_MIRROR_TX); ++ ++ /* allow the port to talk to all other ports, but exclude its ++ * own ID to prevent frames from being reflected back to the ++ * port that they came from */ ++ portmask &= ar7240sw_port_mask_but(as, port); ++ ++ ar7240sw_reg_write(mii, AR7240_REG_PORT_CTRL(port), ctrl); ++ if (sw_is_ar934x(as)) { ++ u32 vlan1, vlan2; ++ ++ vlan1 = (vid << AR934X_PORT_VLAN1_DEFAULT_CVID_S); ++ vlan2 = (portmask << AR934X_PORT_VLAN2_PORT_VID_MEM_S) | ++ (mode << AR934X_PORT_VLAN2_8021Q_MODE_S); ++ ar7240sw_reg_write(mii, AR934X_REG_PORT_VLAN1(port), vlan1); ++ ar7240sw_reg_write(mii, AR934X_REG_PORT_VLAN2(port), vlan2); ++ } else { ++ u32 vlan; ++ ++ vlan = vid | (mode << AR7240_PORT_VLAN_MODE_S) | ++ (portmask << AR7240_PORT_VLAN_DEST_PORTS_S); ++ ++ ar7240sw_reg_write(mii, AR7240_REG_PORT_VLAN(port), vlan); ++ } ++} ++ ++static int ar7240_set_addr(struct ar7240sw *as, u8 *addr) ++{ ++ struct mii_bus *mii = as->mii_bus; ++ u32 t; ++ ++ t = (addr[4] << 8) | addr[5]; ++ ar7240sw_reg_write(mii, AR7240_REG_MAC_ADDR0, t); ++ ++ t = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3]; ++ ar7240sw_reg_write(mii, AR7240_REG_MAC_ADDR1, t); ++ ++ return 0; ++} ++ ++static int ++ar7240_set_vid(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ as->vlan_id[val->port_vlan] = val->value.i; ++ return 0; ++} ++ ++static int ++ar7240_get_vid(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ val->value.i = as->vlan_id[val->port_vlan]; ++ return 0; ++} ++ ++static int ++ar7240_set_pvid(struct switch_dev *dev, int port, int vlan) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ ++ /* make sure no invalid PVIDs get set */ ++ ++ if (vlan >= dev->vlans) ++ return -EINVAL; ++ ++ as->pvid[port] = vlan; ++ return 0; ++} ++ ++static int ++ar7240_get_pvid(struct switch_dev *dev, int port, int *vlan) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ *vlan = as->pvid[port]; ++ return 0; ++} ++ ++static int ++ar7240_get_ports(struct switch_dev *dev, struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ u8 ports = as->vlan_table[val->port_vlan]; ++ int i; ++ ++ val->len = 0; ++ for (i = 0; i < as->swdev.ports; i++) { ++ struct switch_port *p; ++ ++ if (!(ports & (1 << i))) ++ continue; ++ ++ p = &val->value.ports[val->len++]; ++ p->id = i; ++ if (as->vlan_tagged & (1 << i)) ++ p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); ++ else ++ p->flags = 0; ++ } ++ return 0; ++} ++ ++static int ++ar7240_set_ports(struct switch_dev *dev, struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ u8 *vt = &as->vlan_table[val->port_vlan]; ++ int i, j; ++ ++ *vt = 0; ++ for (i = 0; i < val->len; i++) { ++ struct switch_port *p = &val->value.ports[i]; ++ ++ if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) ++ as->vlan_tagged |= (1 << p->id); ++ else { ++ as->vlan_tagged &= ~(1 << p->id); ++ as->pvid[p->id] = val->port_vlan; ++ ++ /* make sure that an untagged port does not ++ * appear in other vlans */ ++ for (j = 0; j < AR7240_MAX_VLANS; j++) { ++ if (j == val->port_vlan) ++ continue; ++ as->vlan_table[j] &= ~(1 << p->id); ++ } ++ } ++ ++ *vt |= 1 << p->id; ++ } ++ return 0; ++} ++ ++static int ++ar7240_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ as->vlan = !!val->value.i; ++ return 0; ++} ++ ++static int ++ar7240_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ val->value.i = as->vlan; ++ return 0; ++} ++ ++static void ++ar7240_vtu_op(struct ar7240sw *as, u32 op, u32 val) ++{ ++ struct mii_bus *mii = as->mii_bus; ++ ++ if (ar7240sw_reg_wait(mii, AR7240_REG_VTU, AR7240_VTU_ACTIVE, 0, 5)) ++ return; ++ ++ if ((op & AR7240_VTU_OP) == AR7240_VTU_OP_LOAD) { ++ val &= AR7240_VTUDATA_MEMBER; ++ val |= AR7240_VTUDATA_VALID; ++ ar7240sw_reg_write(mii, AR7240_REG_VTU_DATA, val); ++ } ++ op |= AR7240_VTU_ACTIVE; ++ ar7240sw_reg_write(mii, AR7240_REG_VTU, op); ++} ++ ++static int ++ar7240_hw_apply(struct switch_dev *dev) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ u8 portmask[AR7240_NUM_PORTS]; ++ int i, j; ++ ++ /* flush all vlan translation unit entries */ ++ ar7240_vtu_op(as, AR7240_VTU_OP_FLUSH, 0); ++ ++ memset(portmask, 0, sizeof(portmask)); ++ if (as->vlan) { ++ /* calculate the port destination masks and load vlans ++ * into the vlan translation unit */ ++ for (j = 0; j < AR7240_MAX_VLANS; j++) { ++ u8 vp = as->vlan_table[j]; ++ ++ if (!vp) ++ continue; ++ ++ for (i = 0; i < as->swdev.ports; i++) { ++ u8 mask = (1 << i); ++ if (vp & mask) ++ portmask[i] |= vp & ~mask; ++ } ++ ++ ar7240_vtu_op(as, ++ AR7240_VTU_OP_LOAD | ++ (as->vlan_id[j] << AR7240_VTU_VID_S), ++ as->vlan_table[j]); ++ } ++ } else { ++ /* vlan disabled: ++ * isolate all ports, but connect them to the cpu port */ ++ for (i = 0; i < as->swdev.ports; i++) { ++ if (i == AR7240_PORT_CPU) ++ continue; ++ ++ portmask[i] = 1 << AR7240_PORT_CPU; ++ portmask[AR7240_PORT_CPU] |= (1 << i); ++ } ++ } ++ ++ /* update the port destination mask registers and tag settings */ ++ for (i = 0; i < as->swdev.ports; i++) ++ ar7240sw_setup_port(as, i, portmask[i]); ++ ++ return 0; ++} ++ ++static int ++ar7240_reset_switch(struct switch_dev *dev) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ ar7240sw_reset(as); ++ return 0; ++} ++ ++static int ++ar7240_get_port_link(struct switch_dev *dev, int port, ++ struct switch_port_link *link) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ struct mii_bus *mii = as->mii_bus; ++ u32 status; ++ ++ if (port >= AR7240_NUM_PORTS) ++ return -EINVAL; ++ ++ status = ar7240sw_reg_read(mii, AR7240_REG_PORT_STATUS(port)); ++ link->aneg = !!(status & AR7240_PORT_STATUS_LINK_AUTO); ++ if (link->aneg) { ++ link->link = !!(status & AR7240_PORT_STATUS_LINK_UP); ++ if (!link->link) ++ return 0; ++ } else { ++ link->link = true; ++ } ++ ++ link->duplex = !!(status & AR7240_PORT_STATUS_DUPLEX); ++ link->tx_flow = !!(status & AR7240_PORT_STATUS_TXFLOW); ++ link->rx_flow = !!(status & AR7240_PORT_STATUS_RXFLOW); ++ switch (status & AR7240_PORT_STATUS_SPEED_M) { ++ case AR7240_PORT_STATUS_SPEED_10: ++ link->speed = SWITCH_PORT_SPEED_10; ++ break; ++ case AR7240_PORT_STATUS_SPEED_100: ++ link->speed = SWITCH_PORT_SPEED_100; ++ break; ++ case AR7240_PORT_STATUS_SPEED_1000: ++ link->speed = SWITCH_PORT_SPEED_1000; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int ++ar7240_get_port_stats(struct switch_dev *dev, int port, ++ struct switch_port_stats *stats) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ ++ if (port >= AR7240_NUM_PORTS) ++ return -EINVAL; ++ ++ ar7240sw_capture_stats(as); ++ ++ read_lock(&as->stats_lock); ++ stats->rx_bytes = as->port_stats[port].rx_good_byte; ++ stats->tx_bytes = as->port_stats[port].tx_byte; ++ read_unlock(&as->stats_lock); ++ ++ return 0; ++} ++ ++static int ++ar7240_set_mirror_monitor_port(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ struct mii_bus *mii = as->mii_bus; ++ ++ int port = val->value.i; ++ ++ if (port > 15) ++ return -EINVAL; ++ ++ ar7240sw_reg_rmw(mii, AR7240_REG_CPU_PORT, ++ AR7240_MIRROR_PORT_M << AR7240_MIRROR_PORT_S, ++ port << AR7240_MIRROR_PORT_S); ++ ++ return 0; ++} ++ ++static int ++ar7240_get_mirror_monitor_port(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ struct mii_bus *mii = as->mii_bus; ++ ++ u32 ret; ++ ++ ret = ar7240sw_reg_read(mii, AR7240_REG_CPU_PORT); ++ val->value.i = (ret >> AR7240_MIRROR_PORT_S) & AR7240_MIRROR_PORT_M; ++ ++ return 0; ++} ++ ++static int ++ar7240_set_mirror_rx(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ struct mii_bus *mii = as->mii_bus; ++ ++ int port = val->port_vlan; ++ ++ if (port >= dev->ports) ++ return -EINVAL; ++ ++ if (val && val->value.i == 1) ++ ar7240sw_reg_set(mii, AR7240_REG_PORT_CTRL(port), ++ AR7240_PORT_CTRL_MIRROR_RX); ++ else ++ ar7240sw_reg_rmw(mii, AR7240_REG_PORT_CTRL(port), ++ AR7240_PORT_CTRL_MIRROR_RX, 0); ++ ++ return 0; ++} ++ ++static int ++ar7240_get_mirror_rx(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ struct mii_bus *mii = as->mii_bus; ++ ++ u32 ctrl; ++ ++ int port = val->port_vlan; ++ ++ if (port >= dev->ports) ++ return -EINVAL; ++ ++ ctrl = ar7240sw_reg_read(mii, AR7240_REG_PORT_CTRL(port)); ++ ++ if ((ctrl & AR7240_PORT_CTRL_MIRROR_RX) == AR7240_PORT_CTRL_MIRROR_RX) ++ val->value.i = 1; ++ else ++ val->value.i = 0; ++ ++ return 0; ++} ++ ++static int ++ar7240_set_mirror_tx(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ struct mii_bus *mii = as->mii_bus; ++ ++ int port = val->port_vlan; ++ ++ if (port >= dev->ports) ++ return -EINVAL; ++ ++ if (val && val->value.i == 1) ++ ar7240sw_reg_set(mii, AR7240_REG_PORT_CTRL(port), ++ AR7240_PORT_CTRL_MIRROR_TX); ++ else ++ ar7240sw_reg_rmw(mii, AR7240_REG_PORT_CTRL(port), ++ AR7240_PORT_CTRL_MIRROR_TX, 0); ++ ++ return 0; ++} ++ ++static int ++ar7240_get_mirror_tx(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar7240sw *as = sw_to_ar7240(dev); ++ struct mii_bus *mii = as->mii_bus; ++ ++ u32 ctrl; ++ ++ int port = val->port_vlan; ++ ++ if (port >= dev->ports) ++ return -EINVAL; ++ ++ ctrl = ar7240sw_reg_read(mii, AR7240_REG_PORT_CTRL(port)); ++ ++ if ((ctrl & AR7240_PORT_CTRL_MIRROR_TX) == AR7240_PORT_CTRL_MIRROR_TX) ++ val->value.i = 1; ++ else ++ val->value.i = 0; ++ ++ return 0; ++} ++ ++static struct switch_attr ar7240_globals[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "enable_vlan", ++ .description = "Enable VLAN mode", ++ .set = ar7240_set_vlan, ++ .get = ar7240_get_vlan, ++ .max = 1 ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "mirror_monitor_port", ++ .description = "Mirror monitor port", ++ .set = ar7240_set_mirror_monitor_port, ++ .get = ar7240_get_mirror_monitor_port, ++ .max = 15 ++ }, ++}; ++ ++static struct switch_attr ar7240_port[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "enable_mirror_rx", ++ .description = "Enable mirroring of RX packets", ++ .set = ar7240_set_mirror_rx, ++ .get = ar7240_get_mirror_rx, ++ .max = 1 ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "enable_mirror_tx", ++ .description = "Enable mirroring of TX packets", ++ .set = ar7240_set_mirror_tx, ++ .get = ar7240_get_mirror_tx, ++ .max = 1 ++ }, ++}; ++ ++static struct switch_attr ar7240_vlan[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "vid", ++ .description = "VLAN ID", ++ .set = ar7240_set_vid, ++ .get = ar7240_get_vid, ++ .max = 4094, ++ }, ++}; ++ ++static const struct switch_dev_ops ar7240_ops = { ++ .attr_global = { ++ .attr = ar7240_globals, ++ .n_attr = ARRAY_SIZE(ar7240_globals), ++ }, ++ .attr_port = { ++ .attr = ar7240_port, ++ .n_attr = ARRAY_SIZE(ar7240_port), ++ }, ++ .attr_vlan = { ++ .attr = ar7240_vlan, ++ .n_attr = ARRAY_SIZE(ar7240_vlan), ++ }, ++ .get_port_pvid = ar7240_get_pvid, ++ .set_port_pvid = ar7240_set_pvid, ++ .get_vlan_ports = ar7240_get_ports, ++ .set_vlan_ports = ar7240_set_ports, ++ .apply_config = ar7240_hw_apply, ++ .reset_switch = ar7240_reset_switch, ++ .get_port_link = ar7240_get_port_link, ++ .get_port_stats = ar7240_get_port_stats, ++}; ++ ++static struct ar7240sw *ar7240_probe(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ struct mii_bus *mii = ag->mii_bus; ++ struct ar7240sw *as; ++ struct switch_dev *swdev; ++ u32 ctrl; ++ u16 phy_id1; ++ u16 phy_id2; ++ int i; ++ ++ phy_id1 = ar7240sw_phy_read(mii, 0, MII_PHYSID1); ++ phy_id2 = ar7240sw_phy_read(mii, 0, MII_PHYSID2); ++ if ((phy_id1 != AR7240_PHY_ID1 || phy_id2 != AR7240_PHY_ID2) && ++ (phy_id1 != AR934X_PHY_ID1 || phy_id2 != AR934X_PHY_ID2)) { ++ pr_err("%s: unknown phy id '%04x:%04x'\n", ++ dev_name(&mii->dev), phy_id1, phy_id2); ++ return NULL; ++ } ++ ++ as = kzalloc(sizeof(*as), GFP_KERNEL); ++ if (!as) ++ return NULL; ++ ++ as->mii_bus = mii; ++ as->swdata = pdata->switch_data; ++ ++ swdev = &as->swdev; ++ ++ ctrl = ar7240sw_reg_read(mii, AR7240_REG_MASK_CTRL); ++ as->ver = (ctrl >> AR7240_MASK_CTRL_VERSION_S) & ++ AR7240_MASK_CTRL_VERSION_M; ++ ++ if (sw_is_ar7240(as)) { ++ swdev->name = "AR7240/AR9330 built-in switch"; ++ swdev->ports = AR7240_NUM_PORTS - 1; ++ } else if (sw_is_ar934x(as)) { ++ swdev->name = "AR934X built-in switch"; ++ ++ if (pdata->phy_if_mode == PHY_INTERFACE_MODE_GMII) { ++ ar7240sw_reg_set(mii, AR934X_REG_OPER_MODE0, ++ AR934X_OPER_MODE0_MAC_GMII_EN); ++ } else if (pdata->phy_if_mode == PHY_INTERFACE_MODE_MII) { ++ ar7240sw_reg_set(mii, AR934X_REG_OPER_MODE0, ++ AR934X_OPER_MODE0_PHY_MII_EN); ++ } else { ++ pr_err("%s: invalid PHY interface mode\n", ++ dev_name(&mii->dev)); ++ goto err_free; ++ } ++ ++ if (as->swdata->phy4_mii_en) { ++ ar7240sw_reg_set(mii, AR934X_REG_OPER_MODE1, ++ AR934X_REG_OPER_MODE1_PHY4_MII_EN); ++ swdev->ports = AR7240_NUM_PORTS - 1; ++ } else { ++ swdev->ports = AR7240_NUM_PORTS; ++ } ++ } else { ++ pr_err("%s: unsupported chip, ctrl=%08x\n", ++ dev_name(&mii->dev), ctrl); ++ goto err_free; ++ } ++ ++ swdev->cpu_port = AR7240_PORT_CPU; ++ swdev->vlans = AR7240_MAX_VLANS; ++ swdev->ops = &ar7240_ops; ++ ++ if (register_switch(&as->swdev, ag->dev) < 0) ++ goto err_free; ++ ++ pr_info("%s: Found an %s\n", dev_name(&mii->dev), swdev->name); ++ ++ /* initialize defaults */ ++ for (i = 0; i < AR7240_MAX_VLANS; i++) ++ as->vlan_id[i] = i; ++ ++ as->vlan_table[0] = ar7240sw_port_mask_all(as); ++ ++ return as; ++ ++err_free: ++ kfree(as); ++ return NULL; ++} ++ ++static void link_function(struct work_struct *work) { ++ struct ag71xx *ag = container_of(work, struct ag71xx, link_work.work); ++ struct ar7240sw *as = ag->phy_priv; ++ unsigned long flags; ++ u8 mask; ++ int i; ++ int status = 0; ++ ++ mask = ~as->swdata->phy_poll_mask; ++ for (i = 0; i < AR7240_NUM_PHYS; i++) { ++ int link; ++ ++ if (!(mask & BIT(i))) ++ continue; ++ ++ link = ar7240sw_phy_read(ag->mii_bus, i, MII_BMSR); ++ if (link & BMSR_LSTATUS) { ++ status = 1; ++ break; ++ } ++ } ++ ++ spin_lock_irqsave(&ag->lock, flags); ++ if (status != ag->link) { ++ ag->link = status; ++ ag71xx_link_adjust(ag); ++ } ++ spin_unlock_irqrestore(&ag->lock, flags); ++ ++ schedule_delayed_work(&ag->link_work, HZ / 2); ++} ++ ++void ag71xx_ar7240_start(struct ag71xx *ag) ++{ ++ struct ar7240sw *as = ag->phy_priv; ++ ++ ar7240sw_reset(as); ++ ++ ag->speed = SPEED_1000; ++ ag->duplex = 1; ++ ++ ar7240_set_addr(as, ag->dev->dev_addr); ++ ar7240_hw_apply(&as->swdev); ++ ++ schedule_delayed_work(&ag->link_work, HZ / 10); ++} ++ ++void ag71xx_ar7240_stop(struct ag71xx *ag) ++{ ++ cancel_delayed_work_sync(&ag->link_work); ++} ++ ++int ag71xx_ar7240_init(struct ag71xx *ag) ++{ ++ struct ar7240sw *as; ++ ++ as = ar7240_probe(ag); ++ if (!as) ++ return -ENODEV; ++ ++ ag->phy_priv = as; ++ ar7240sw_reset(as); ++ ++ rwlock_init(&as->stats_lock); ++ INIT_DELAYED_WORK(&ag->link_work, link_function); ++ ++ return 0; ++} ++ ++void ag71xx_ar7240_cleanup(struct ag71xx *ag) ++{ ++ struct ar7240sw *as = ag->phy_priv; ++ ++ if (!as) ++ return; ++ ++ unregister_switch(&as->swdev); ++ kfree(as); ++ ag->phy_priv = NULL; ++} +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar8216.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar8216.c +new file mode 100644 +index 0000000000..7ec43b7221 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar8216.c +@@ -0,0 +1,44 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * Special support for the Atheros ar8216 switch chip ++ * ++ * Copyright (C) 2009-2010 Gabor Juhos ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * 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 "ag71xx.h" ++ ++#define AR8216_PACKET_TYPE_MASK 0xf ++#define AR8216_PACKET_TYPE_NORMAL 0 ++ ++#define AR8216_HEADER_LEN 2 ++ ++void ag71xx_add_ar8216_header(struct ag71xx *ag, struct sk_buff *skb) ++{ ++ skb_push(skb, AR8216_HEADER_LEN); ++ skb->data[0] = 0x10; ++ skb->data[1] = 0x80; ++} ++ ++int ag71xx_remove_ar8216_header(struct ag71xx *ag, struct sk_buff *skb, ++ int pktlen) ++{ ++ u8 type; ++ ++ type = skb->data[1] & AR8216_PACKET_TYPE_MASK; ++ switch (type) { ++ case AR8216_PACKET_TYPE_NORMAL: ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ skb_pull(skb, AR8216_HEADER_LEN); ++ return 0; ++} +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c +new file mode 100644 +index 0000000000..20cf1c15c8 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c +@@ -0,0 +1,285 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * 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 "ag71xx.h" ++ ++static struct dentry *ag71xx_debugfs_root; ++ ++static int ag71xx_debugfs_generic_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = inode->i_private; ++ return 0; ++} ++ ++void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, u32 status) ++{ ++ if (status) ++ ag->debug.int_stats.total++; ++ if (status & AG71XX_INT_TX_PS) ++ ag->debug.int_stats.tx_ps++; ++ if (status & AG71XX_INT_TX_UR) ++ ag->debug.int_stats.tx_ur++; ++ if (status & AG71XX_INT_TX_BE) ++ ag->debug.int_stats.tx_be++; ++ if (status & AG71XX_INT_RX_PR) ++ ag->debug.int_stats.rx_pr++; ++ if (status & AG71XX_INT_RX_OF) ++ ag->debug.int_stats.rx_of++; ++ if (status & AG71XX_INT_RX_BE) ++ ag->debug.int_stats.rx_be++; ++} ++ ++static ssize_t read_file_int_stats(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++#define PR_INT_STAT(_label, _field) \ ++ len += snprintf(buf + len, sizeof(buf) - len, \ ++ "%20s: %10lu\n", _label, ag->debug.int_stats._field); ++ ++ struct ag71xx *ag = file->private_data; ++ char buf[256]; ++ unsigned int len = 0; ++ ++ PR_INT_STAT("TX Packet Sent", tx_ps); ++ PR_INT_STAT("TX Underrun", tx_ur); ++ PR_INT_STAT("TX Bus Error", tx_be); ++ PR_INT_STAT("RX Packet Received", rx_pr); ++ PR_INT_STAT("RX Overflow", rx_of); ++ PR_INT_STAT("RX Bus Error", rx_be); ++ len += snprintf(buf + len, sizeof(buf) - len, "\n"); ++ PR_INT_STAT("Total", total); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++#undef PR_INT_STAT ++} ++ ++static const struct file_operations ag71xx_fops_int_stats = { ++ .open = ag71xx_debugfs_generic_open, ++ .read = read_file_int_stats, ++ .owner = THIS_MODULE ++}; ++ ++void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx) ++{ ++ struct ag71xx_napi_stats *stats = &ag->debug.napi_stats; ++ ++ if (rx) { ++ stats->rx_count++; ++ stats->rx_packets += rx; ++ if (rx <= AG71XX_NAPI_WEIGHT) ++ stats->rx[rx]++; ++ if (rx > stats->rx_packets_max) ++ stats->rx_packets_max = rx; ++ } ++ ++ if (tx) { ++ stats->tx_count++; ++ stats->tx_packets += tx; ++ if (tx <= AG71XX_NAPI_WEIGHT) ++ stats->tx[tx]++; ++ if (tx > stats->tx_packets_max) ++ stats->tx_packets_max = tx; ++ } ++} ++ ++static ssize_t read_file_napi_stats(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ag71xx *ag = file->private_data; ++ struct ag71xx_napi_stats *stats = &ag->debug.napi_stats; ++ char *buf; ++ unsigned int buflen; ++ unsigned int len = 0; ++ unsigned long rx_avg = 0; ++ unsigned long tx_avg = 0; ++ int ret; ++ int i; ++ ++ buflen = 2048; ++ buf = kmalloc(buflen, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (stats->rx_count) ++ rx_avg = stats->rx_packets / stats->rx_count; ++ ++ if (stats->tx_count) ++ tx_avg = stats->tx_packets / stats->tx_count; ++ ++ len += snprintf(buf + len, buflen - len, "%3s %10s %10s\n", ++ "len", "rx", "tx"); ++ ++ for (i = 1; i <= AG71XX_NAPI_WEIGHT; i++) ++ len += snprintf(buf + len, buflen - len, ++ "%3d: %10lu %10lu\n", ++ i, stats->rx[i], stats->tx[i]); ++ ++ len += snprintf(buf + len, buflen - len, "\n"); ++ ++ len += snprintf(buf + len, buflen - len, "%3s: %10lu %10lu\n", ++ "sum", stats->rx_count, stats->tx_count); ++ len += snprintf(buf + len, buflen - len, "%3s: %10lu %10lu\n", ++ "avg", rx_avg, tx_avg); ++ len += snprintf(buf + len, buflen - len, "%3s: %10lu %10lu\n", ++ "max", stats->rx_packets_max, stats->tx_packets_max); ++ len += snprintf(buf + len, buflen - len, "%3s: %10lu %10lu\n", ++ "pkt", stats->rx_packets, stats->tx_packets); ++ ++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return ret; ++} ++ ++static const struct file_operations ag71xx_fops_napi_stats = { ++ .open = ag71xx_debugfs_generic_open, ++ .read = read_file_napi_stats, ++ .owner = THIS_MODULE ++}; ++ ++#define DESC_PRINT_LEN 64 ++ ++static ssize_t read_file_ring(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos, ++ struct ag71xx *ag, ++ struct ag71xx_ring *ring, ++ unsigned desc_reg) ++{ ++ int ring_size = BIT(ring->order); ++ int ring_mask = ring_size - 1; ++ char *buf; ++ unsigned int buflen; ++ unsigned int len = 0; ++ unsigned long flags; ++ ssize_t ret; ++ int curr; ++ int dirty; ++ u32 desc_hw; ++ int i; ++ ++ buflen = (ring_size * DESC_PRINT_LEN); ++ buf = kmalloc(buflen, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ len += snprintf(buf + len, buflen - len, ++ "Idx ... %-8s %-8s %-8s %-8s .\n", ++ "desc", "next", "data", "ctrl"); ++ ++ spin_lock_irqsave(&ag->lock, flags); ++ ++ curr = (ring->curr & ring_mask); ++ dirty = (ring->dirty & ring_mask); ++ desc_hw = ag71xx_rr(ag, desc_reg); ++ for (i = 0; i < ring_size; i++) { ++ struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); ++ u32 desc_dma = ((u32) ring->descs_dma) + i * AG71XX_DESC_SIZE; ++ ++ len += snprintf(buf + len, buflen - len, ++ "%3d %c%c%c %08x %08x %08x %08x %c\n", ++ i, ++ (i == curr) ? 'C' : ' ', ++ (i == dirty) ? 'D' : ' ', ++ (desc_hw == desc_dma) ? 'H' : ' ', ++ desc_dma, ++ desc->next, ++ desc->data, ++ desc->ctrl, ++ (desc->ctrl & DESC_EMPTY) ? 'E' : '*'); ++ } ++ ++ spin_unlock_irqrestore(&ag->lock, flags); ++ ++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return ret; ++} ++ ++static ssize_t read_file_tx_ring(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ag71xx *ag = file->private_data; ++ ++ return read_file_ring(file, user_buf, count, ppos, ag, &ag->tx_ring, ++ AG71XX_REG_TX_DESC); ++} ++ ++static const struct file_operations ag71xx_fops_tx_ring = { ++ .open = ag71xx_debugfs_generic_open, ++ .read = read_file_tx_ring, ++ .owner = THIS_MODULE ++}; ++ ++static ssize_t read_file_rx_ring(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ag71xx *ag = file->private_data; ++ ++ return read_file_ring(file, user_buf, count, ppos, ag, &ag->rx_ring, ++ AG71XX_REG_RX_DESC); ++} ++ ++static const struct file_operations ag71xx_fops_rx_ring = { ++ .open = ag71xx_debugfs_generic_open, ++ .read = read_file_rx_ring, ++ .owner = THIS_MODULE ++}; ++ ++void ag71xx_debugfs_exit(struct ag71xx *ag) ++{ ++ debugfs_remove_recursive(ag->debug.debugfs_dir); ++} ++ ++int ag71xx_debugfs_init(struct ag71xx *ag) ++{ ++ struct device *dev = &ag->pdev->dev; ++ ++ ag->debug.debugfs_dir = debugfs_create_dir(dev_name(dev), ++ ag71xx_debugfs_root); ++ if (!ag->debug.debugfs_dir) { ++ dev_err(dev, "unable to create debugfs directory\n"); ++ return -ENOENT; ++ } ++ ++ debugfs_create_file("int_stats", S_IRUGO, ag->debug.debugfs_dir, ++ ag, &ag71xx_fops_int_stats); ++ debugfs_create_file("napi_stats", S_IRUGO, ag->debug.debugfs_dir, ++ ag, &ag71xx_fops_napi_stats); ++ debugfs_create_file("tx_ring", S_IRUGO, ag->debug.debugfs_dir, ++ ag, &ag71xx_fops_tx_ring); ++ debugfs_create_file("rx_ring", S_IRUGO, ag->debug.debugfs_dir, ++ ag, &ag71xx_fops_rx_ring); ++ ++ return 0; ++} ++ ++int ag71xx_debugfs_root_init(void) ++{ ++ if (ag71xx_debugfs_root) ++ return -EBUSY; ++ ++ ag71xx_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); ++ if (!ag71xx_debugfs_root) ++ return -ENOENT; ++ ++ return 0; ++} ++ ++void ag71xx_debugfs_root_exit(void) ++{ ++ debugfs_remove(ag71xx_debugfs_root); ++ ag71xx_debugfs_root = NULL; ++} +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c +new file mode 100644 +index 0000000000..9e5a53e7fc +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c +@@ -0,0 +1,120 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * 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 "ag71xx.h" ++#include ++ ++static void ag71xx_ethtool_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ strcpy(info->driver, ag->pdev->dev.driver->name); ++ strcpy(info->version, AG71XX_DRV_VERSION); ++ strcpy(info->bus_info, dev_name(&ag->pdev->dev)); ++} ++ ++static u32 ag71xx_ethtool_get_msglevel(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ return ag->msg_enable; ++} ++ ++static void ag71xx_ethtool_set_msglevel(struct net_device *dev, u32 msg_level) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ ag->msg_enable = msg_level; ++} ++ ++static void ag71xx_ethtool_get_ringparam(struct net_device *dev, ++ struct ethtool_ringparam *er) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ er->tx_max_pending = AG71XX_TX_RING_SIZE_MAX; ++ er->rx_max_pending = AG71XX_RX_RING_SIZE_MAX; ++ er->rx_mini_max_pending = 0; ++ er->rx_jumbo_max_pending = 0; ++ ++ er->tx_pending = BIT(ag->tx_ring.order); ++ er->rx_pending = BIT(ag->rx_ring.order); ++ er->rx_mini_pending = 0; ++ er->rx_jumbo_pending = 0; ++ ++ if (ag->tx_ring.desc_split) ++ er->tx_pending /= AG71XX_TX_RING_DS_PER_PKT; ++} ++ ++static int ag71xx_ethtool_set_ringparam(struct net_device *dev, ++ struct ethtool_ringparam *er) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ unsigned tx_size; ++ unsigned rx_size; ++ int err = 0; ++ ++ if (er->rx_mini_pending != 0|| ++ er->rx_jumbo_pending != 0 || ++ er->rx_pending == 0 || ++ er->tx_pending == 0) ++ return -EINVAL; ++ ++ tx_size = er->tx_pending < AG71XX_TX_RING_SIZE_MAX ? ++ er->tx_pending : AG71XX_TX_RING_SIZE_MAX; ++ ++ rx_size = er->rx_pending < AG71XX_RX_RING_SIZE_MAX ? ++ er->rx_pending : AG71XX_RX_RING_SIZE_MAX; ++ ++ if (netif_running(dev)) { ++ err = dev->netdev_ops->ndo_stop(dev); ++ if (err) ++ return err; ++ } ++ ++ if (ag->tx_ring.desc_split) ++ tx_size *= AG71XX_TX_RING_DS_PER_PKT; ++ ++ ag->tx_ring.order = ag71xx_ring_size_order(tx_size); ++ ag->rx_ring.order = ag71xx_ring_size_order(rx_size); ++ ++ if (netif_running(dev)) ++ err = dev->netdev_ops->ndo_open(dev); ++ ++ return err; ++} ++ ++static int ag71xx_ethtool_nway_reset(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ struct phy_device *phydev = ag->phy_dev; ++ ++ if (!phydev) ++ return -ENODEV; ++ ++ return genphy_restart_aneg(phydev); ++} ++ ++struct ethtool_ops ag71xx_ethtool_ops = { ++ .get_drvinfo = ag71xx_ethtool_get_drvinfo, ++ .get_msglevel = ag71xx_ethtool_get_msglevel, ++ .set_msglevel = ag71xx_ethtool_set_msglevel, ++ .get_ringparam = ag71xx_ethtool_get_ringparam, ++ .set_ringparam = ag71xx_ethtool_set_ringparam, ++ .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .set_link_ksettings = phy_ethtool_set_link_ksettings, ++ .get_link = ethtool_op_get_link, ++ .get_ts_info = ethtool_op_get_ts_info, ++ .nway_reset = ag71xx_ethtool_nway_reset, ++}; +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +new file mode 100644 +index 0000000000..ebbe8a7472 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +@@ -0,0 +1,1494 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * 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 "ag71xx.h" ++ ++#define AG71XX_DEFAULT_MSG_ENABLE \ ++ (NETIF_MSG_DRV \ ++ | NETIF_MSG_PROBE \ ++ | NETIF_MSG_LINK \ ++ | NETIF_MSG_TIMER \ ++ | NETIF_MSG_IFDOWN \ ++ | NETIF_MSG_IFUP \ ++ | NETIF_MSG_RX_ERR \ ++ | NETIF_MSG_TX_ERR) ++ ++static int ag71xx_msg_level = -1; ++ ++module_param_named(msg_level, ag71xx_msg_level, int, 0); ++MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); ++ ++#define ETH_SWITCH_HEADER_LEN 2 ++ ++static int ag71xx_tx_packets(struct ag71xx *ag, bool flush); ++static void ag71xx_qca955x_sgmii_init(void); ++ ++static inline unsigned int ag71xx_max_frame_len(unsigned int mtu) ++{ ++ return ETH_SWITCH_HEADER_LEN + ETH_HLEN + VLAN_HLEN + mtu + ETH_FCS_LEN; ++} ++ ++static void ag71xx_dump_dma_regs(struct ag71xx *ag) ++{ ++ DBG("%s: dma_tx_ctrl=%08x, dma_tx_desc=%08x, dma_tx_status=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_TX_CTRL), ++ ag71xx_rr(ag, AG71XX_REG_TX_DESC), ++ ag71xx_rr(ag, AG71XX_REG_TX_STATUS)); ++ ++ DBG("%s: dma_rx_ctrl=%08x, dma_rx_desc=%08x, dma_rx_status=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_RX_CTRL), ++ ag71xx_rr(ag, AG71XX_REG_RX_DESC), ++ ag71xx_rr(ag, AG71XX_REG_RX_STATUS)); ++} ++ ++static void ag71xx_dump_regs(struct ag71xx *ag) ++{ ++ DBG("%s: mac_cfg1=%08x, mac_cfg2=%08x, ipg=%08x, hdx=%08x, mfl=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_MAC_CFG1), ++ ag71xx_rr(ag, AG71XX_REG_MAC_CFG2), ++ ag71xx_rr(ag, AG71XX_REG_MAC_IPG), ++ ag71xx_rr(ag, AG71XX_REG_MAC_HDX), ++ ag71xx_rr(ag, AG71XX_REG_MAC_MFL)); ++ DBG("%s: mac_ifctl=%08x, mac_addr1=%08x, mac_addr2=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL), ++ ag71xx_rr(ag, AG71XX_REG_MAC_ADDR1), ++ ag71xx_rr(ag, AG71XX_REG_MAC_ADDR2)); ++ DBG("%s: fifo_cfg0=%08x, fifo_cfg1=%08x, fifo_cfg2=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2)); ++ DBG("%s: fifo_cfg3=%08x, fifo_cfg4=%08x, fifo_cfg5=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5)); ++} ++ ++static inline void ag71xx_dump_intr(struct ag71xx *ag, char *label, u32 intr) ++{ ++ DBG("%s: %s intr=%08x %s%s%s%s%s%s\n", ++ ag->dev->name, label, intr, ++ (intr & AG71XX_INT_TX_PS) ? "TXPS " : "", ++ (intr & AG71XX_INT_TX_UR) ? "TXUR " : "", ++ (intr & AG71XX_INT_TX_BE) ? "TXBE " : "", ++ (intr & AG71XX_INT_RX_PR) ? "RXPR " : "", ++ (intr & AG71XX_INT_RX_OF) ? "RXOF " : "", ++ (intr & AG71XX_INT_RX_BE) ? "RXBE " : ""); ++} ++ ++static void ag71xx_ring_tx_clean(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->tx_ring; ++ struct net_device *dev = ag->dev; ++ int ring_mask = BIT(ring->order) - 1; ++ u32 bytes_compl = 0, pkts_compl = 0; ++ ++ while (ring->curr != ring->dirty) { ++ struct ag71xx_desc *desc; ++ u32 i = ring->dirty & ring_mask; ++ ++ desc = ag71xx_ring_desc(ring, i); ++ if (!ag71xx_desc_empty(desc)) { ++ desc->ctrl = 0; ++ dev->stats.tx_errors++; ++ } ++ ++ if (ring->buf[i].skb) { ++ bytes_compl += ring->buf[i].len; ++ pkts_compl++; ++ dev_kfree_skb_any(ring->buf[i].skb); ++ } ++ ring->buf[i].skb = NULL; ++ ring->dirty++; ++ } ++ ++ /* flush descriptors */ ++ wmb(); ++ ++ netdev_completed_queue(dev, pkts_compl, bytes_compl); ++} ++ ++static void ag71xx_ring_tx_init(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->tx_ring; ++ int ring_size = BIT(ring->order); ++ int ring_mask = BIT(ring->order) - 1; ++ int i; ++ ++ for (i = 0; i < ring_size; i++) { ++ struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); ++ ++ desc->next = (u32) (ring->descs_dma + ++ AG71XX_DESC_SIZE * ((i + 1) & ring_mask)); ++ ++ desc->ctrl = DESC_EMPTY; ++ ring->buf[i].skb = NULL; ++ } ++ ++ /* flush descriptors */ ++ wmb(); ++ ++ ring->curr = 0; ++ ring->dirty = 0; ++ netdev_reset_queue(ag->dev); ++} ++ ++static void ag71xx_ring_rx_clean(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ int ring_size = BIT(ring->order); ++ int i; ++ ++ if (!ring->buf) ++ return; ++ ++ for (i = 0; i < ring_size; i++) ++ if (ring->buf[i].rx_buf) { ++ dma_unmap_single(&ag->pdev->dev, ring->buf[i].dma_addr, ++ ag->rx_buf_size, DMA_FROM_DEVICE); ++ skb_free_frag(ring->buf[i].rx_buf); ++ } ++} ++ ++static int ag71xx_buffer_offset(struct ag71xx *ag) ++{ ++ int offset = NET_SKB_PAD; ++ ++ /* ++ * On AR71xx/AR91xx packets must be 4-byte aligned. ++ * ++ * When using builtin AR8216 support, hardware adds a 2-byte header, ++ * so we don't need any extra alignment in that case. ++ */ ++ if (!ag71xx_get_pdata(ag)->is_ar724x || ag71xx_has_ar8216(ag)) ++ return offset; ++ ++ return offset + NET_IP_ALIGN; ++} ++ ++static int ag71xx_buffer_size(struct ag71xx *ag) ++{ ++ return ag->rx_buf_size + ++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); ++} ++ ++static bool ag71xx_fill_rx_buf(struct ag71xx *ag, struct ag71xx_buf *buf, ++ int offset, ++ void *(*alloc)(unsigned int size)) ++{ ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ struct ag71xx_desc *desc = ag71xx_ring_desc(ring, buf - &ring->buf[0]); ++ void *data; ++ ++ data = alloc(ag71xx_buffer_size(ag)); ++ if (!data) ++ return false; ++ ++ buf->rx_buf = data; ++ buf->dma_addr = dma_map_single(&ag->pdev->dev, data, ag->rx_buf_size, ++ DMA_FROM_DEVICE); ++ desc->data = (u32) buf->dma_addr + offset; ++ return true; ++} ++ ++static int ag71xx_ring_rx_init(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ int ring_size = BIT(ring->order); ++ int ring_mask = BIT(ring->order) - 1; ++ unsigned int i; ++ int ret; ++ int offset = ag71xx_buffer_offset(ag); ++ ++ ret = 0; ++ for (i = 0; i < ring_size; i++) { ++ struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); ++ ++ desc->next = (u32) (ring->descs_dma + ++ AG71XX_DESC_SIZE * ((i + 1) & ring_mask)); ++ ++ DBG("ag71xx: RX desc at %p, next is %08x\n", ++ desc, desc->next); ++ } ++ ++ for (i = 0; i < ring_size; i++) { ++ struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); ++ ++ if (!ag71xx_fill_rx_buf(ag, &ring->buf[i], offset, ++ netdev_alloc_frag)) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ desc->ctrl = DESC_EMPTY; ++ } ++ ++ /* flush descriptors */ ++ wmb(); ++ ++ ring->curr = 0; ++ ring->dirty = 0; ++ ++ return ret; ++} ++ ++static int ag71xx_ring_rx_refill(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ int ring_mask = BIT(ring->order) - 1; ++ unsigned int count; ++ int offset = ag71xx_buffer_offset(ag); ++ ++ count = 0; ++ for (; ring->curr - ring->dirty > 0; ring->dirty++) { ++ struct ag71xx_desc *desc; ++ unsigned int i; ++ ++ i = ring->dirty & ring_mask; ++ desc = ag71xx_ring_desc(ring, i); ++ ++ if (!ring->buf[i].rx_buf && ++ !ag71xx_fill_rx_buf(ag, &ring->buf[i], offset, ++ napi_alloc_frag)) ++ break; ++ ++ desc->ctrl = DESC_EMPTY; ++ count++; ++ } ++ ++ /* flush descriptors */ ++ wmb(); ++ ++ DBG("%s: %u rx descriptors refilled\n", ag->dev->name, count); ++ ++ return count; ++} ++ ++static int ag71xx_rings_init(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *tx = &ag->tx_ring; ++ struct ag71xx_ring *rx = &ag->rx_ring; ++ int ring_size = BIT(tx->order) + BIT(rx->order); ++ int tx_size = BIT(tx->order); ++ ++ tx->buf = kzalloc(ring_size * sizeof(*tx->buf), GFP_KERNEL); ++ if (!tx->buf) ++ return -ENOMEM; ++ ++ tx->descs_cpu = dma_alloc_coherent(&ag->pdev->dev, ring_size * AG71XX_DESC_SIZE, ++ &tx->descs_dma, GFP_KERNEL); ++ if (!tx->descs_cpu) { ++ kfree(tx->buf); ++ tx->buf = NULL; ++ return -ENOMEM; ++ } ++ ++ rx->buf = &tx->buf[tx_size]; ++ rx->descs_cpu = ((void *)tx->descs_cpu) + tx_size * AG71XX_DESC_SIZE; ++ rx->descs_dma = tx->descs_dma + tx_size * AG71XX_DESC_SIZE; ++ ++ ag71xx_ring_tx_init(ag); ++ return ag71xx_ring_rx_init(ag); ++} ++ ++static void ag71xx_rings_free(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *tx = &ag->tx_ring; ++ struct ag71xx_ring *rx = &ag->rx_ring; ++ int ring_size = BIT(tx->order) + BIT(rx->order); ++ ++ if (tx->descs_cpu) ++ dma_free_coherent(&ag->pdev->dev, ring_size * AG71XX_DESC_SIZE, ++ tx->descs_cpu, tx->descs_dma); ++ ++ kfree(tx->buf); ++ ++ tx->descs_cpu = NULL; ++ rx->descs_cpu = NULL; ++ tx->buf = NULL; ++ rx->buf = NULL; ++} ++ ++static void ag71xx_rings_cleanup(struct ag71xx *ag) ++{ ++ ag71xx_ring_rx_clean(ag); ++ ag71xx_ring_tx_clean(ag); ++ ag71xx_rings_free(ag); ++ ++ netdev_reset_queue(ag->dev); ++} ++ ++static unsigned char *ag71xx_speed_str(struct ag71xx *ag) ++{ ++ switch (ag->speed) { ++ case SPEED_1000: ++ return "1000"; ++ case SPEED_100: ++ return "100"; ++ case SPEED_10: ++ return "10"; ++ } ++ ++ return "?"; ++} ++ ++static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac) ++{ ++ u32 t; ++ ++ t = (((u32) mac[5]) << 24) | (((u32) mac[4]) << 16) ++ | (((u32) mac[3]) << 8) | ((u32) mac[2]); ++ ++ ag71xx_wr(ag, AG71XX_REG_MAC_ADDR1, t); ++ ++ t = (((u32) mac[1]) << 24) | (((u32) mac[0]) << 16); ++ ag71xx_wr(ag, AG71XX_REG_MAC_ADDR2, t); ++} ++ ++static void ag71xx_dma_reset(struct ag71xx *ag) ++{ ++ u32 val; ++ int i; ++ ++ ag71xx_dump_dma_regs(ag); ++ ++ /* stop RX and TX */ ++ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0); ++ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0); ++ ++ /* ++ * give the hardware some time to really stop all rx/tx activity ++ * clearing the descriptors too early causes random memory corruption ++ */ ++ mdelay(1); ++ ++ /* clear descriptor addresses */ ++ ag71xx_wr(ag, AG71XX_REG_TX_DESC, ag->stop_desc_dma); ++ ag71xx_wr(ag, AG71XX_REG_RX_DESC, ag->stop_desc_dma); ++ ++ /* clear pending RX/TX interrupts */ ++ for (i = 0; i < 256; i++) { ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR); ++ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS); ++ } ++ ++ /* clear pending errors */ ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE | RX_STATUS_OF); ++ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE | TX_STATUS_UR); ++ ++ val = ag71xx_rr(ag, AG71XX_REG_RX_STATUS); ++ if (val) ++ pr_alert("%s: unable to clear DMA Rx status: %08x\n", ++ ag->dev->name, val); ++ ++ val = ag71xx_rr(ag, AG71XX_REG_TX_STATUS); ++ ++ /* mask out reserved bits */ ++ val &= ~0xff000000; ++ ++ if (val) ++ pr_alert("%s: unable to clear DMA Tx status: %08x\n", ++ ag->dev->name, val); ++ ++ ag71xx_dump_dma_regs(ag); ++} ++ ++#define MAC_CFG1_INIT (MAC_CFG1_RXE | MAC_CFG1_TXE | \ ++ MAC_CFG1_SRX | MAC_CFG1_STX) ++ ++#define FIFO_CFG0_INIT (FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT) ++ ++#define FIFO_CFG4_INIT (FIFO_CFG4_DE | FIFO_CFG4_DV | FIFO_CFG4_FC | \ ++ FIFO_CFG4_CE | FIFO_CFG4_CR | FIFO_CFG4_LM | \ ++ FIFO_CFG4_LO | FIFO_CFG4_OK | FIFO_CFG4_MC | \ ++ FIFO_CFG4_BC | FIFO_CFG4_DR | FIFO_CFG4_LE | \ ++ FIFO_CFG4_CF | FIFO_CFG4_PF | FIFO_CFG4_UO | \ ++ FIFO_CFG4_VT) ++ ++#define FIFO_CFG5_INIT (FIFO_CFG5_DE | FIFO_CFG5_DV | FIFO_CFG5_FC | \ ++ FIFO_CFG5_CE | FIFO_CFG5_LO | FIFO_CFG5_OK | \ ++ FIFO_CFG5_MC | FIFO_CFG5_BC | FIFO_CFG5_DR | \ ++ FIFO_CFG5_CF | FIFO_CFG5_PF | FIFO_CFG5_VT | \ ++ FIFO_CFG5_LE | FIFO_CFG5_FT | FIFO_CFG5_16 | \ ++ FIFO_CFG5_17 | FIFO_CFG5_SF) ++ ++static void ag71xx_hw_stop(struct ag71xx *ag) ++{ ++ /* disable all interrupts and stop the rx/tx engine */ ++ ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0); ++ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0); ++ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0); ++} ++ ++static void ag71xx_hw_setup(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ u32 init = MAC_CFG1_INIT; ++ ++ /* setup MAC configuration registers */ ++ if (pdata->use_flow_control) ++ init |= MAC_CFG1_TFC | MAC_CFG1_RFC; ++ ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, init); ++ ++ ag71xx_sb(ag, AG71XX_REG_MAC_CFG2, ++ MAC_CFG2_PAD_CRC_EN | MAC_CFG2_LEN_CHECK); ++ ++ /* setup max frame length to zero */ ++ ag71xx_wr(ag, AG71XX_REG_MAC_MFL, 0); ++ ++ /* setup FIFO configuration registers */ ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG0, FIFO_CFG0_INIT); ++ if (pdata->is_ar724x) { ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0010ffff); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x015500aa); ++ } else { ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff); ++ } ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG4, FIFO_CFG4_INIT); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, FIFO_CFG5_INIT); ++} ++ ++static void ag71xx_hw_init(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ u32 reset_mask = pdata->reset_bit; ++ ++ ag71xx_hw_stop(ag); ++ ++ if (pdata->is_ar724x) { ++ u32 reset_phy = reset_mask; ++ ++ reset_phy &= AR71XX_RESET_GE0_PHY | AR71XX_RESET_GE1_PHY; ++ reset_mask &= ~(AR71XX_RESET_GE0_PHY | AR71XX_RESET_GE1_PHY); ++ ++ ath79_device_reset_set(reset_phy); ++ msleep(50); ++ ath79_device_reset_clear(reset_phy); ++ msleep(200); ++ } ++ ++ ag71xx_sb(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_SR); ++ udelay(20); ++ ++ ath79_device_reset_set(reset_mask); ++ msleep(100); ++ ath79_device_reset_clear(reset_mask); ++ msleep(200); ++ ++ ag71xx_hw_setup(ag); ++ ++ ag71xx_dma_reset(ag); ++} ++ ++static void ag71xx_fast_reset(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ struct net_device *dev = ag->dev; ++ u32 reset_mask = pdata->reset_bit; ++ u32 rx_ds; ++ u32 mii_reg; ++ ++ reset_mask &= AR71XX_RESET_GE0_MAC | AR71XX_RESET_GE1_MAC; ++ ++ ag71xx_hw_stop(ag); ++ wmb(); ++ ++ mii_reg = ag71xx_rr(ag, AG71XX_REG_MII_CFG); ++ rx_ds = ag71xx_rr(ag, AG71XX_REG_RX_DESC); ++ ++ ag71xx_tx_packets(ag, true); ++ ++ ath79_device_reset_set(reset_mask); ++ udelay(10); ++ ath79_device_reset_clear(reset_mask); ++ udelay(10); ++ ++ ag71xx_dma_reset(ag); ++ ag71xx_hw_setup(ag); ++ ag->tx_ring.curr = 0; ++ ag->tx_ring.dirty = 0; ++ netdev_reset_queue(ag->dev); ++ ++ /* setup max frame length */ ++ ag71xx_wr(ag, AG71XX_REG_MAC_MFL, ++ ag71xx_max_frame_len(ag->dev->mtu)); ++ ++ ag71xx_wr(ag, AG71XX_REG_RX_DESC, rx_ds); ++ ag71xx_wr(ag, AG71XX_REG_TX_DESC, ag->tx_ring.descs_dma); ++ ag71xx_wr(ag, AG71XX_REG_MII_CFG, mii_reg); ++ ++ ag71xx_hw_set_macaddr(ag, dev->dev_addr); ++} ++ ++static void ag71xx_hw_start(struct ag71xx *ag) ++{ ++ /* start RX engine */ ++ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE); ++ ++ /* enable interrupts */ ++ ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, AG71XX_INT_INIT); ++ ++ netif_wake_queue(ag->dev); ++} ++ ++static void ++__ag71xx_link_adjust(struct ag71xx *ag, bool update) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ u32 cfg2; ++ u32 ifctl; ++ u32 fifo5; ++ u32 fifo3; ++ ++ if (!ag->link && update) { ++ ag71xx_hw_stop(ag); ++ netif_carrier_off(ag->dev); ++ if (netif_msg_link(ag)) ++ pr_info("%s: link down\n", ag->dev->name); ++ return; ++ } ++ ++ if (pdata->is_ar724x) ++ ag71xx_fast_reset(ag); ++ ++ cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2); ++ cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX); ++ cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0; ++ ++ ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL); ++ ifctl &= ~(MAC_IFCTL_SPEED); ++ ++ fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5); ++ fifo5 &= ~FIFO_CFG5_BM; ++ ++ switch (ag->speed) { ++ case SPEED_1000: ++ cfg2 |= MAC_CFG2_IF_1000; ++ fifo5 |= FIFO_CFG5_BM; ++ break; ++ case SPEED_100: ++ cfg2 |= MAC_CFG2_IF_10_100; ++ ifctl |= MAC_IFCTL_SPEED; ++ break; ++ case SPEED_10: ++ cfg2 |= MAC_CFG2_IF_10_100; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ if (pdata->is_ar91xx) ++ fifo3 = 0x00780fff; ++ else if (pdata->is_ar724x) ++ fifo3 = 0x01f00140; ++ else ++ fifo3 = 0x008001ff; ++ ++ if (ag->tx_ring.desc_split) { ++ fifo3 &= 0xffff; ++ fifo3 |= ((2048 - ag->tx_ring.desc_split) / 4) << 16; ++ } ++ ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, fifo3); ++ ++ if (update && pdata->set_speed) ++ pdata->set_speed(ag->speed); ++ ++ if (update && pdata->enable_sgmii_fixup) ++ ag71xx_qca955x_sgmii_init(); ++ ++ ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5); ++ ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl); ++ ++ if (pdata->disable_inline_checksum_engine) { ++ /* ++ * The rx ring buffer can stall on small packets on QCA953x and ++ * QCA956x. Disabling the inline checksum engine fixes the stall. ++ * The wr, rr functions cannot be used since this hidden register ++ * is outside of the normal ag71xx register block. ++ */ ++ void __iomem *dam = ioremap_nocache(0xb90001bc, 0x4); ++ if (dam) { ++ __raw_writel(__raw_readl(dam) & ~BIT(27), dam); ++ (void)__raw_readl(dam); ++ iounmap(dam); ++ } ++ } ++ ++ ag71xx_hw_start(ag); ++ ++ netif_carrier_on(ag->dev); ++ if (update && netif_msg_link(ag)) ++ pr_info("%s: link up (%sMbps/%s duplex)\n", ++ ag->dev->name, ++ ag71xx_speed_str(ag), ++ (DUPLEX_FULL == ag->duplex) ? "Full" : "Half"); ++ ++ ag71xx_dump_regs(ag); ++} ++ ++void ag71xx_link_adjust(struct ag71xx *ag) ++{ ++ __ag71xx_link_adjust(ag, true); ++} ++ ++static int ag71xx_hw_enable(struct ag71xx *ag) ++{ ++ int ret; ++ ++ ret = ag71xx_rings_init(ag); ++ if (ret) ++ return ret; ++ ++ napi_enable(&ag->napi); ++ ag71xx_wr(ag, AG71XX_REG_TX_DESC, ag->tx_ring.descs_dma); ++ ag71xx_wr(ag, AG71XX_REG_RX_DESC, ag->rx_ring.descs_dma); ++ netif_start_queue(ag->dev); ++ ++ return 0; ++} ++ ++static void ag71xx_hw_disable(struct ag71xx *ag) ++{ ++ netif_stop_queue(ag->dev); ++ ++ ag71xx_hw_stop(ag); ++ ag71xx_dma_reset(ag); ++ ++ napi_disable(&ag->napi); ++ del_timer_sync(&ag->oom_timer); ++ ++ ag71xx_rings_cleanup(ag); ++} ++ ++static int ag71xx_open(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ unsigned int max_frame_len; ++ int ret; ++ ++ netif_carrier_off(dev); ++ max_frame_len = ag71xx_max_frame_len(dev->mtu); ++ ag->rx_buf_size = SKB_DATA_ALIGN(max_frame_len + NET_SKB_PAD + NET_IP_ALIGN); ++ ++ /* setup max frame length */ ++ ag71xx_wr(ag, AG71XX_REG_MAC_MFL, max_frame_len); ++ ag71xx_hw_set_macaddr(ag, dev->dev_addr); ++ ++ ret = ag71xx_hw_enable(ag); ++ if (ret) ++ goto err; ++ ++ ag71xx_phy_start(ag); ++ ++ return 0; ++ ++err: ++ ag71xx_rings_cleanup(ag); ++ return ret; ++} ++ ++static int ag71xx_stop(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ netif_carrier_off(dev); ++ ag71xx_phy_stop(ag); ++ ag71xx_hw_disable(ag); ++ ++ return 0; ++} ++ ++static int ag71xx_fill_dma_desc(struct ag71xx_ring *ring, u32 addr, int len) ++{ ++ int i; ++ struct ag71xx_desc *desc; ++ int ring_mask = BIT(ring->order) - 1; ++ int ndesc = 0; ++ int split = ring->desc_split; ++ ++ if (!split) ++ split = len; ++ ++ while (len > 0) { ++ unsigned int cur_len = len; ++ ++ i = (ring->curr + ndesc) & ring_mask; ++ desc = ag71xx_ring_desc(ring, i); ++ ++ if (!ag71xx_desc_empty(desc)) ++ return -1; ++ ++ if (cur_len > split) { ++ cur_len = split; ++ ++ /* ++ * TX will hang if DMA transfers <= 4 bytes, ++ * make sure next segment is more than 4 bytes long. ++ */ ++ if (len <= split + 4) ++ cur_len -= 4; ++ } ++ ++ desc->data = addr; ++ addr += cur_len; ++ len -= cur_len; ++ ++ if (len > 0) ++ cur_len |= DESC_MORE; ++ ++ /* prevent early tx attempt of this descriptor */ ++ if (!ndesc) ++ cur_len |= DESC_EMPTY; ++ ++ desc->ctrl = cur_len; ++ ndesc++; ++ } ++ ++ return ndesc; ++} ++ ++static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ struct ag71xx_ring *ring = &ag->tx_ring; ++ int ring_mask = BIT(ring->order) - 1; ++ int ring_size = BIT(ring->order); ++ struct ag71xx_desc *desc; ++ dma_addr_t dma_addr; ++ int i, n, ring_min; ++ ++ if (ag71xx_has_ar8216(ag)) ++ ag71xx_add_ar8216_header(ag, skb); ++ ++ if (skb->len <= 4) { ++ DBG("%s: packet len is too small\n", ag->dev->name); ++ goto err_drop; ++ } ++ ++ dma_addr = dma_map_single(&ag->pdev->dev, skb->data, skb->len, ++ DMA_TO_DEVICE); ++ ++ i = ring->curr & ring_mask; ++ desc = ag71xx_ring_desc(ring, i); ++ ++ /* setup descriptor fields */ ++ n = ag71xx_fill_dma_desc(ring, (u32) dma_addr, skb->len & ag->desc_pktlen_mask); ++ if (n < 0) ++ goto err_drop_unmap; ++ ++ i = (ring->curr + n - 1) & ring_mask; ++ ring->buf[i].len = skb->len; ++ ring->buf[i].skb = skb; ++ ++ netdev_sent_queue(dev, skb->len); ++ ++ skb_tx_timestamp(skb); ++ ++ desc->ctrl &= ~DESC_EMPTY; ++ ring->curr += n; ++ ++ /* flush descriptor */ ++ wmb(); ++ ++ ring_min = 2; ++ if (ring->desc_split) ++ ring_min *= AG71XX_TX_RING_DS_PER_PKT; ++ ++ if (ring->curr - ring->dirty >= ring_size - ring_min) { ++ DBG("%s: tx queue full\n", dev->name); ++ netif_stop_queue(dev); ++ } ++ ++ DBG("%s: packet injected into TX queue\n", ag->dev->name); ++ ++ /* enable TX engine */ ++ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, TX_CTRL_TXE); ++ ++ return NETDEV_TX_OK; ++ ++err_drop_unmap: ++ dma_unmap_single(&ag->pdev->dev, dma_addr, skb->len, DMA_TO_DEVICE); ++ ++err_drop: ++ dev->stats.tx_dropped++; ++ ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++} ++ ++static int ag71xx_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ switch (cmd) { ++ case SIOCSIFHWADDR: ++ if (copy_from_user ++ (dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr))) ++ return -EFAULT; ++ return 0; ++ ++ case SIOCGIFHWADDR: ++ if (copy_to_user ++ (ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr))) ++ return -EFAULT; ++ return 0; ++ ++ case SIOCGMIIPHY: ++ case SIOCGMIIREG: ++ case SIOCSMIIREG: ++ if (ag->phy_dev == NULL) ++ break; ++ ++ return phy_mii_ioctl(ag->phy_dev, ifr, cmd); ++ ++ default: ++ break; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static void ag71xx_oom_timer_handler(unsigned long data) ++{ ++ struct net_device *dev = (struct net_device *) data; ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ napi_schedule(&ag->napi); ++} ++ ++static void ag71xx_tx_timeout(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ if (netif_msg_tx_err(ag)) ++ pr_info("%s: tx timeout\n", ag->dev->name); ++ ++ schedule_delayed_work(&ag->restart_work, 1); ++} ++ ++static void ag71xx_bit_set(void __iomem *reg, u32 bit) ++{ ++ u32 val = __raw_readl(reg) | bit; ++ __raw_writel(val, reg); ++ __raw_readl(reg); ++} ++ ++static void ag71xx_bit_clear(void __iomem *reg, u32 bit) ++{ ++ u32 val = __raw_readl(reg) & ~bit; ++ __raw_writel(val, reg); ++ __raw_readl(reg); ++} ++ ++static void ag71xx_qca955x_sgmii_init() ++{ ++ void __iomem *gmac_base; ++ u32 mr_an_status, sgmii_status; ++ u8 tries = 0; ++ ++ gmac_base = ioremap_nocache(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); ++ ++ if (!gmac_base) ++ goto sgmii_out; ++ ++ mr_an_status = __raw_readl(gmac_base + QCA955X_GMAC_REG_MR_AN_STATUS); ++ if (!(mr_an_status & QCA955X_MR_AN_STATUS_AN_ABILITY)) ++ goto sgmii_out; ++ ++ __raw_writel(QCA955X_SGMII_RESET_RX_CLK_N_RESET , ++ gmac_base + QCA955X_GMAC_REG_SGMII_RESET); ++ __raw_readl(gmac_base + QCA955X_GMAC_REG_SGMII_RESET); ++ udelay(10); ++ ++ /* Init sequence */ ++ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET, ++ QCA955X_SGMII_RESET_HW_RX_125M_N); ++ udelay(10); ++ ++ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET, ++ QCA955X_SGMII_RESET_RX_125M_N); ++ udelay(10); ++ ++ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET, ++ QCA955X_SGMII_RESET_TX_125M_N); ++ udelay(10); ++ ++ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET, ++ QCA955X_SGMII_RESET_RX_CLK_N); ++ udelay(10); ++ ++ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET, ++ QCA955X_SGMII_RESET_TX_CLK_N); ++ udelay(10); ++ ++ do { ++ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_MR_AN_CONTROL, ++ QCA955X_MR_AN_CONTROL_PHY_RESET | ++ QCA955X_MR_AN_CONTROL_AN_ENABLE); ++ udelay(100); ++ ag71xx_bit_clear(gmac_base + QCA955X_GMAC_REG_MR_AN_CONTROL, ++ QCA955X_MR_AN_CONTROL_PHY_RESET); ++ mdelay(10); ++ sgmii_status = __raw_readl(gmac_base + QCA955X_GMAC_REG_SGMII_DEBUG) & 0xF; ++ ++ if (tries++ >= QCA955X_SGMII_LINK_WAR_MAX_TRY) { ++ pr_warn("ag71xx: max retries for SGMII fixup exceeded!\n"); ++ break; ++ } ++ } while (!(sgmii_status == 0xf || sgmii_status == 0x10)); ++ ++sgmii_out: ++ iounmap(gmac_base); ++} ++ ++static void ag71xx_restart_work_func(struct work_struct *work) ++{ ++ struct ag71xx *ag = container_of(work, struct ag71xx, restart_work.work); ++ ++ rtnl_lock(); ++ ag71xx_hw_disable(ag); ++ ag71xx_hw_enable(ag); ++ if (ag->link) ++ __ag71xx_link_adjust(ag, false); ++ rtnl_unlock(); ++} ++ ++static bool ag71xx_check_dma_stuck(struct ag71xx *ag) ++{ ++ unsigned long timestamp; ++ u32 rx_sm, tx_sm, rx_fd; ++ ++ timestamp = netdev_get_tx_queue(ag->dev, 0)->trans_start; ++ if (likely(time_before(jiffies, timestamp + HZ/10))) ++ return false; ++ ++ if (!netif_carrier_ok(ag->dev)) ++ return false; ++ ++ rx_sm = ag71xx_rr(ag, AG71XX_REG_RX_SM); ++ if ((rx_sm & 0x7) == 0x3 && ((rx_sm >> 4) & 0x7) == 0x6) ++ return true; ++ ++ tx_sm = ag71xx_rr(ag, AG71XX_REG_TX_SM); ++ rx_fd = ag71xx_rr(ag, AG71XX_REG_FIFO_DEPTH); ++ if (((tx_sm >> 4) & 0x7) == 0 && ((rx_sm & 0x7) == 0) && ++ ((rx_sm >> 4) & 0x7) == 0 && rx_fd == 0) ++ return true; ++ ++ return false; ++} ++ ++static int ag71xx_tx_packets(struct ag71xx *ag, bool flush) ++{ ++ struct ag71xx_ring *ring = &ag->tx_ring; ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ bool dma_stuck = false; ++ int ring_mask = BIT(ring->order) - 1; ++ int ring_size = BIT(ring->order); ++ int sent = 0; ++ int bytes_compl = 0; ++ int n = 0; ++ ++ DBG("%s: processing TX ring\n", ag->dev->name); ++ ++ while (ring->dirty + n != ring->curr) { ++ unsigned int i = (ring->dirty + n) & ring_mask; ++ struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); ++ struct sk_buff *skb = ring->buf[i].skb; ++ ++ if (!flush && !ag71xx_desc_empty(desc)) { ++ if (pdata->is_ar724x && ++ ag71xx_check_dma_stuck(ag)) { ++ schedule_delayed_work(&ag->restart_work, HZ / 2); ++ dma_stuck = true; ++ } ++ break; ++ } ++ ++ if (flush) ++ desc->ctrl |= DESC_EMPTY; ++ ++ n++; ++ if (!skb) ++ continue; ++ ++ dev_kfree_skb_any(skb); ++ ring->buf[i].skb = NULL; ++ ++ bytes_compl += ring->buf[i].len; ++ ++ sent++; ++ ring->dirty += n; ++ ++ while (n > 0) { ++ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS); ++ n--; ++ } ++ } ++ ++ DBG("%s: %d packets sent out\n", ag->dev->name, sent); ++ ++ if (!sent) ++ return 0; ++ ++ ag->dev->stats.tx_bytes += bytes_compl; ++ ag->dev->stats.tx_packets += sent; ++ ++ netdev_completed_queue(ag->dev, sent, bytes_compl); ++ if ((ring->curr - ring->dirty) < (ring_size * 3) / 4) ++ netif_wake_queue(ag->dev); ++ ++ if (!dma_stuck) ++ cancel_delayed_work(&ag->restart_work); ++ ++ return sent; ++} ++ ++static int ag71xx_rx_packets(struct ag71xx *ag, int limit) ++{ ++ struct net_device *dev = ag->dev; ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ int offset = ag71xx_buffer_offset(ag); ++ unsigned int pktlen_mask = ag->desc_pktlen_mask; ++ int ring_mask = BIT(ring->order) - 1; ++ int ring_size = BIT(ring->order); ++ struct sk_buff_head queue; ++ struct sk_buff *skb; ++ int done = 0; ++ ++ DBG("%s: rx packets, limit=%d, curr=%u, dirty=%u\n", ++ dev->name, limit, ring->curr, ring->dirty); ++ ++ skb_queue_head_init(&queue); ++ ++ while (done < limit) { ++ unsigned int i = ring->curr & ring_mask; ++ struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); ++ int pktlen; ++ int err = 0; ++ ++ if (ag71xx_desc_empty(desc)) ++ break; ++ ++ if ((ring->dirty + ring_size) == ring->curr) { ++ ag71xx_assert(0); ++ break; ++ } ++ ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR); ++ ++ pktlen = desc->ctrl & pktlen_mask; ++ pktlen -= ETH_FCS_LEN; ++ ++ dma_unmap_single(&ag->pdev->dev, ring->buf[i].dma_addr, ++ ag->rx_buf_size, DMA_FROM_DEVICE); ++ ++ dev->stats.rx_packets++; ++ dev->stats.rx_bytes += pktlen; ++ ++ skb = build_skb(ring->buf[i].rx_buf, ag71xx_buffer_size(ag)); ++ if (!skb) { ++ skb_free_frag(ring->buf[i].rx_buf); ++ goto next; ++ } ++ ++ skb_reserve(skb, offset); ++ skb_put(skb, pktlen); ++ ++ if (ag71xx_has_ar8216(ag)) ++ err = ag71xx_remove_ar8216_header(ag, skb, pktlen); ++ ++ if (err) { ++ dev->stats.rx_dropped++; ++ kfree_skb(skb); ++ } else { ++ skb->dev = dev; ++ skb->ip_summed = CHECKSUM_NONE; ++ __skb_queue_tail(&queue, skb); ++ } ++ ++next: ++ ring->buf[i].rx_buf = NULL; ++ done++; ++ ++ ring->curr++; ++ } ++ ++ ag71xx_ring_rx_refill(ag); ++ ++ while ((skb = __skb_dequeue(&queue)) != NULL) { ++ skb->protocol = eth_type_trans(skb, dev); ++ netif_receive_skb(skb); ++ } ++ ++ DBG("%s: rx finish, curr=%u, dirty=%u, done=%d\n", ++ dev->name, ring->curr, ring->dirty, done); ++ ++ return done; ++} ++ ++static int ag71xx_poll(struct napi_struct *napi, int limit) ++{ ++ struct ag71xx *ag = container_of(napi, struct ag71xx, napi); ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ struct net_device *dev = ag->dev; ++ struct ag71xx_ring *rx_ring = &ag->rx_ring; ++ int rx_ring_size = BIT(rx_ring->order); ++ unsigned long flags; ++ u32 status; ++ int tx_done; ++ int rx_done; ++ ++ pdata->ddr_flush(); ++ tx_done = ag71xx_tx_packets(ag, false); ++ ++ DBG("%s: processing RX ring\n", dev->name); ++ rx_done = ag71xx_rx_packets(ag, limit); ++ ++ ag71xx_debugfs_update_napi_stats(ag, rx_done, tx_done); ++ ++ if (rx_ring->buf[rx_ring->dirty % rx_ring_size].rx_buf == NULL) ++ goto oom; ++ ++ status = ag71xx_rr(ag, AG71XX_REG_RX_STATUS); ++ if (unlikely(status & RX_STATUS_OF)) { ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_OF); ++ dev->stats.rx_fifo_errors++; ++ ++ /* restart RX */ ++ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE); ++ } ++ ++ if (rx_done < limit) { ++ if (status & RX_STATUS_PR) ++ goto more; ++ ++ status = ag71xx_rr(ag, AG71XX_REG_TX_STATUS); ++ if (status & TX_STATUS_PS) ++ goto more; ++ ++ DBG("%s: disable polling mode, rx=%d, tx=%d,limit=%d\n", ++ dev->name, rx_done, tx_done, limit); ++ ++ napi_complete(napi); ++ ++ /* enable interrupts */ ++ spin_lock_irqsave(&ag->lock, flags); ++ ag71xx_int_enable(ag, AG71XX_INT_POLL); ++ spin_unlock_irqrestore(&ag->lock, flags); ++ return rx_done; ++ } ++ ++more: ++ DBG("%s: stay in polling mode, rx=%d, tx=%d, limit=%d\n", ++ dev->name, rx_done, tx_done, limit); ++ return limit; ++ ++oom: ++ if (netif_msg_rx_err(ag)) ++ pr_info("%s: out of memory\n", dev->name); ++ ++ mod_timer(&ag->oom_timer, jiffies + AG71XX_OOM_REFILL); ++ napi_complete(napi); ++ return 0; ++} ++ ++static irqreturn_t ag71xx_interrupt(int irq, void *dev_id) ++{ ++ struct net_device *dev = dev_id; ++ struct ag71xx *ag = netdev_priv(dev); ++ u32 status; ++ ++ status = ag71xx_rr(ag, AG71XX_REG_INT_STATUS); ++ ag71xx_dump_intr(ag, "raw", status); ++ ++ if (unlikely(!status)) ++ return IRQ_NONE; ++ ++ if (unlikely(status & AG71XX_INT_ERR)) { ++ if (status & AG71XX_INT_TX_BE) { ++ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE); ++ dev_err(&dev->dev, "TX BUS error\n"); ++ } ++ if (status & AG71XX_INT_RX_BE) { ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE); ++ dev_err(&dev->dev, "RX BUS error\n"); ++ } ++ } ++ ++ if (likely(status & AG71XX_INT_POLL)) { ++ ag71xx_int_disable(ag, AG71XX_INT_POLL); ++ DBG("%s: enable polling mode\n", dev->name); ++ napi_schedule(&ag->napi); ++ } ++ ++ ag71xx_debugfs_update_int_stats(ag, status); ++ ++ return IRQ_HANDLED; ++} ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* ++ * Polling 'interrupt' - used by things like netconsole to send skbs ++ * without having to re-enable interrupts. It's not called while ++ * the interrupt routine is executing. ++ */ ++static void ag71xx_netpoll(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ ag71xx_interrupt(dev->irq, dev); ++ enable_irq(dev->irq); ++} ++#endif ++ ++static int ag71xx_change_mtu(struct net_device *dev, int new_mtu) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ unsigned int max_frame_len; ++ ++ max_frame_len = ag71xx_max_frame_len(new_mtu); ++ if (new_mtu < 68 || max_frame_len > ag->max_frame_len) ++ return -EINVAL; ++ ++ if (netif_running(dev)) ++ return -EBUSY; ++ ++ dev->mtu = new_mtu; ++ ag71xx_wr(ag, AG71XX_REG_MAC_MFL, ++ ag71xx_max_frame_len(dev->mtu)); ++ ++ return 0; ++} ++ ++static const struct net_device_ops ag71xx_netdev_ops = { ++ .ndo_open = ag71xx_open, ++ .ndo_stop = ag71xx_stop, ++ .ndo_start_xmit = ag71xx_hard_start_xmit, ++ .ndo_do_ioctl = ag71xx_do_ioctl, ++ .ndo_tx_timeout = ag71xx_tx_timeout, ++ .ndo_change_mtu = ag71xx_change_mtu, ++ .ndo_set_mac_address = eth_mac_addr, ++ .ndo_validate_addr = eth_validate_addr, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = ag71xx_netpoll, ++#endif ++}; ++ ++static int ag71xx_probe(struct platform_device *pdev) ++{ ++ struct net_device *dev; ++ struct resource *res; ++ struct ag71xx *ag; ++ struct ag71xx_platform_data *pdata; ++ int tx_size, err; ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) { ++ dev_err(&pdev->dev, "no platform data specified\n"); ++ return -ENXIO; ++ ++ } ++ ++ if (pdata->mii_bus_dev == NULL && pdata->phy_mask) { ++ dev_err(&pdev->dev, "no MII bus device specified\n"); ++ return -EINVAL; ++ } ++ ++ dev = devm_alloc_etherdev(&pdev->dev, sizeof(*ag)); ++ if (!dev) ++ return -ENOMEM; ++ ++ if (!pdata->max_frame_len || !pdata->desc_pktlen_mask) ++ return -EINVAL; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; ++ ++ SET_NETDEV_DEV(dev, &pdev->dev); ++ ++ ag = netdev_priv(dev); ++ ag->pdev = pdev; ++ ag->dev = dev; ++ ag->msg_enable = netif_msg_init(ag71xx_msg_level, ++ AG71XX_DEFAULT_MSG_ENABLE); ++ spin_lock_init(&ag->lock); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac_base"); ++ if (!res) { ++ dev_err(&pdev->dev, "no mac_base resource found\n"); ++ return -ENXIO; ++ } ++ ++ ag->mac_base = devm_ioremap_nocache(&pdev->dev, res->start, ++ res->end - res->start + 1); ++ if (!ag->mac_base) ++ return -ENOMEM; ++ ++ dev->irq = platform_get_irq(pdev, 0); ++ err = devm_request_irq(&pdev->dev, dev->irq, ag71xx_interrupt, ++ 0x0, dev_name(&pdev->dev), dev); ++ if (err) { ++ dev_err(&pdev->dev, "unable to request IRQ %d\n", dev->irq); ++ return err; ++ } ++ ++ dev->base_addr = (unsigned long)ag->mac_base; ++ dev->netdev_ops = &ag71xx_netdev_ops; ++ dev->ethtool_ops = &ag71xx_ethtool_ops; ++ ++ INIT_DELAYED_WORK(&ag->restart_work, ag71xx_restart_work_func); ++ ++ init_timer(&ag->oom_timer); ++ ag->oom_timer.data = (unsigned long) dev; ++ ag->oom_timer.function = ag71xx_oom_timer_handler; ++ ++ tx_size = AG71XX_TX_RING_SIZE_DEFAULT; ++ ag->rx_ring.order = ag71xx_ring_size_order(AG71XX_RX_RING_SIZE_DEFAULT); ++ ++ ag->max_frame_len = pdata->max_frame_len; ++ ag->desc_pktlen_mask = pdata->desc_pktlen_mask; ++ ++ if (!pdata->is_ar724x && !pdata->is_ar91xx) { ++ ag->tx_ring.desc_split = AG71XX_TX_RING_SPLIT; ++ tx_size *= AG71XX_TX_RING_DS_PER_PKT; ++ } ++ ag->tx_ring.order = ag71xx_ring_size_order(tx_size); ++ ++ ag->stop_desc = dmam_alloc_coherent(&pdev->dev, ++ sizeof(struct ag71xx_desc), ++ &ag->stop_desc_dma, GFP_KERNEL); ++ ++ if (!ag->stop_desc) ++ return -ENOMEM; ++ ++ ag->stop_desc->data = 0; ++ ag->stop_desc->ctrl = 0; ++ ag->stop_desc->next = (u32) ag->stop_desc_dma; ++ ++ memcpy(dev->dev_addr, pdata->mac_addr, ETH_ALEN); ++ ++ netif_napi_add(dev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT); ++ ++ ag71xx_dump_regs(ag); ++ ++ ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, 0); ++ ++ ag71xx_hw_init(ag); ++ ++ ag71xx_dump_regs(ag); ++ ++ err = ag71xx_phy_connect(ag); ++ if (err) ++ return err; ++ ++ err = ag71xx_debugfs_init(ag); ++ if (err) ++ goto err_phy_disconnect; ++ ++ platform_set_drvdata(pdev, dev); ++ ++ err = register_netdev(dev); ++ if (err) { ++ dev_err(&pdev->dev, "unable to register net device\n"); ++ platform_set_drvdata(pdev, NULL); ++ ag71xx_debugfs_exit(ag); ++ goto err_phy_disconnect; ++ } ++ ++ pr_info("%s: Atheros AG71xx at 0x%08lx, irq %d, mode: %s\n", ++ dev->name, (unsigned long) ag->mac_base, dev->irq, ++ phy_modes(pdata->phy_if_mode)); ++ ++ return 0; ++ ++err_phy_disconnect: ++ ag71xx_phy_disconnect(ag); ++ return err; ++} ++ ++static int ag71xx_remove(struct platform_device *pdev) ++{ ++ struct net_device *dev = platform_get_drvdata(pdev); ++ struct ag71xx *ag; ++ ++ if (!dev) ++ return 0; ++ ++ ag = netdev_priv(dev); ++ ag71xx_debugfs_exit(ag); ++ ag71xx_phy_disconnect(ag); ++ unregister_netdev(dev); ++ platform_set_drvdata(pdev, NULL); ++ return 0; ++} ++ ++static struct platform_driver ag71xx_driver = { ++ .probe = ag71xx_probe, ++ .remove = ag71xx_remove, ++ .driver = { ++ .name = AG71XX_DRV_NAME, ++ } ++}; ++ ++static int __init ag71xx_module_init(void) ++{ ++ int ret; ++ ++ ret = ag71xx_debugfs_root_init(); ++ if (ret) ++ goto err_out; ++ ++ ret = ag71xx_mdio_driver_init(); ++ if (ret) ++ goto err_debugfs_exit; ++ ++ ret = platform_driver_register(&ag71xx_driver); ++ if (ret) ++ goto err_mdio_exit; ++ ++ return 0; ++ ++err_mdio_exit: ++ ag71xx_mdio_driver_exit(); ++err_debugfs_exit: ++ ag71xx_debugfs_root_exit(); ++err_out: ++ return ret; ++} ++ ++static void __exit ag71xx_module_exit(void) ++{ ++ platform_driver_unregister(&ag71xx_driver); ++ ag71xx_mdio_driver_exit(); ++ ag71xx_debugfs_root_exit(); ++} ++ ++module_init(ag71xx_module_init); ++module_exit(ag71xx_module_exit); ++ ++MODULE_VERSION(AG71XX_DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_AUTHOR("Imre Kaloz "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" AG71XX_DRV_NAME); +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c +new file mode 100644 +index 0000000000..cf41aa8a3f +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c +@@ -0,0 +1,320 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * 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 "ag71xx.h" ++ ++#define AG71XX_MDIO_RETRY 1000 ++#define AG71XX_MDIO_DELAY 5 ++ ++static inline void ag71xx_mdio_wr(struct ag71xx_mdio *am, unsigned reg, ++ u32 value) ++{ ++ void __iomem *r; ++ ++ r = am->mdio_base + reg; ++ __raw_writel(value, r); ++ ++ /* flush write */ ++ (void) __raw_readl(r); ++} ++ ++static inline u32 ag71xx_mdio_rr(struct ag71xx_mdio *am, unsigned reg) ++{ ++ return __raw_readl(am->mdio_base + reg); ++} ++ ++static void ag71xx_mdio_dump_regs(struct ag71xx_mdio *am) ++{ ++ DBG("%s: mii_cfg=%08x, mii_cmd=%08x, mii_addr=%08x\n", ++ am->mii_bus->name, ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_CFG), ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_CMD), ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_ADDR)); ++ DBG("%s: mii_ctrl=%08x, mii_status=%08x, mii_ind=%08x\n", ++ am->mii_bus->name, ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_CTRL), ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_STATUS), ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_IND)); ++} ++ ++static int ag71xx_mdio_wait_busy(struct ag71xx_mdio *am) ++{ ++ int i; ++ ++ for (i = 0; i < AG71XX_MDIO_RETRY; i++) { ++ u32 busy; ++ ++ udelay(AG71XX_MDIO_DELAY); ++ ++ busy = ag71xx_mdio_rr(am, AG71XX_REG_MII_IND); ++ if (!busy) ++ return 0; ++ ++ udelay(AG71XX_MDIO_DELAY); ++ } ++ ++ pr_err("%s: MDIO operation timed out\n", am->mii_bus->name); ++ ++ return -ETIMEDOUT; ++} ++ ++int ag71xx_mdio_mii_read(struct ag71xx_mdio *am, int addr, int reg) ++{ ++ int err; ++ int ret; ++ ++ err = ag71xx_mdio_wait_busy(am); ++ if (err) ++ return 0xffff; ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE); ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR, ++ ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff)); ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_READ); ++ ++ err = ag71xx_mdio_wait_busy(am); ++ if (err) ++ return 0xffff; ++ ++ ret = ag71xx_mdio_rr(am, AG71XX_REG_MII_STATUS) & 0xffff; ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE); ++ ++ DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, ret); ++ ++ return ret; ++} ++ ++void ag71xx_mdio_mii_write(struct ag71xx_mdio *am, int addr, int reg, u16 val) ++{ ++ DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val); ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR, ++ ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff)); ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CTRL, val); ++ ++ ag71xx_mdio_wait_busy(am); ++} ++ ++static const u32 ar71xx_mdio_div_table[] = { ++ 4, 4, 6, 8, 10, 14, 20, 28, ++}; ++ ++static const u32 ar7240_mdio_div_table[] = { ++ 2, 2, 4, 6, 8, 12, 18, 26, 32, 40, 48, 56, 62, 70, 78, 96, ++}; ++ ++static const u32 ar933x_mdio_div_table[] = { ++ 4, 4, 6, 8, 10, 14, 20, 28, 34, 42, 50, 58, 66, 74, 82, 98, ++}; ++ ++static int ag71xx_mdio_get_divider(struct ag71xx_mdio *am, u32 *div) ++{ ++ unsigned long ref_clock, mdio_clock; ++ const u32 *table; ++ int ndivs; ++ int i; ++ ++ ref_clock = am->pdata->ref_clock; ++ mdio_clock = am->pdata->mdio_clock; ++ ++ if (!ref_clock || !mdio_clock) ++ return -EINVAL; ++ ++ if (am->pdata->is_ar9330 || am->pdata->is_ar934x) { ++ table = ar933x_mdio_div_table; ++ ndivs = ARRAY_SIZE(ar933x_mdio_div_table); ++ } else if (am->pdata->is_ar7240) { ++ table = ar7240_mdio_div_table; ++ ndivs = ARRAY_SIZE(ar7240_mdio_div_table); ++ } else { ++ table = ar71xx_mdio_div_table; ++ ndivs = ARRAY_SIZE(ar71xx_mdio_div_table); ++ } ++ ++ for (i = 0; i < ndivs; i++) { ++ unsigned long t; ++ ++ t = ref_clock / table[i]; ++ if (t <= mdio_clock) { ++ *div = i; ++ return 0; ++ } ++ } ++ ++ dev_err(&am->mii_bus->dev, "no divider found for %lu/%lu\n", ++ ref_clock, mdio_clock); ++ return -ENOENT; ++} ++ ++static int ag71xx_mdio_reset(struct mii_bus *bus) ++{ ++ struct ag71xx_mdio *am = bus->priv; ++ u32 t; ++ int err; ++ ++ err = ag71xx_mdio_get_divider(am, &t); ++ if (err) { ++ /* fallback */ ++ if (am->pdata->is_ar7240) ++ t = MII_CFG_CLK_DIV_6; ++ else if (am->pdata->builtin_switch && !am->pdata->is_ar934x) ++ t = MII_CFG_CLK_DIV_10; ++ else if (!am->pdata->builtin_switch && am->pdata->is_ar934x) ++ t = MII_CFG_CLK_DIV_58; ++ else ++ t = MII_CFG_CLK_DIV_28; ++ } ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t | MII_CFG_RESET); ++ udelay(100); ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t); ++ udelay(100); ++ ++ if (am->pdata->reset) ++ am->pdata->reset(bus); ++ ++ return 0; ++} ++ ++static int ag71xx_mdio_read(struct mii_bus *bus, int addr, int reg) ++{ ++ struct ag71xx_mdio *am = bus->priv; ++ ++ if (am->pdata->builtin_switch) ++ return ar7240sw_phy_read(bus, addr, reg); ++ else ++ return ag71xx_mdio_mii_read(am, addr, reg); ++} ++ ++static int ag71xx_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val) ++{ ++ struct ag71xx_mdio *am = bus->priv; ++ ++ if (am->pdata->builtin_switch) ++ ar7240sw_phy_write(bus, addr, reg, val); ++ else ++ ag71xx_mdio_mii_write(am, addr, reg, val); ++ return 0; ++} ++ ++static int ag71xx_mdio_probe(struct platform_device *pdev) ++{ ++ struct ag71xx_mdio_platform_data *pdata; ++ struct ag71xx_mdio *am; ++ struct resource *res; ++ int i; ++ int err; ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) { ++ dev_err(&pdev->dev, "no platform data specified\n"); ++ return -EINVAL; ++ } ++ ++ am = kzalloc(sizeof(*am), GFP_KERNEL); ++ if (!am) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ am->pdata = pdata; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no iomem resource found\n"); ++ err = -ENXIO; ++ goto err_free_mdio; ++ } ++ ++ am->mdio_base = ioremap_nocache(res->start, res->end - res->start + 1); ++ if (!am->mdio_base) { ++ dev_err(&pdev->dev, "unable to ioremap registers\n"); ++ err = -ENOMEM; ++ goto err_free_mdio; ++ } ++ ++ am->mii_bus = mdiobus_alloc(); ++ if (am->mii_bus == NULL) { ++ err = -ENOMEM; ++ goto err_iounmap; ++ } ++ ++ am->mii_bus->name = "ag71xx_mdio"; ++ am->mii_bus->read = ag71xx_mdio_read; ++ am->mii_bus->write = ag71xx_mdio_write; ++ am->mii_bus->reset = ag71xx_mdio_reset; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ am->mii_bus->irq = am->mii_irq; ++#endif ++ am->mii_bus->priv = am; ++ am->mii_bus->parent = &pdev->dev; ++ snprintf(am->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(&pdev->dev)); ++ am->mii_bus->phy_mask = pdata->phy_mask; ++ ++ for (i = 0; i < PHY_MAX_ADDR; i++) ++ am->mii_bus->irq[i] = PHY_POLL; ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MAC_CFG1, 0); ++ ++ err = mdiobus_register(am->mii_bus); ++ if (err) ++ goto err_free_bus; ++ ++ ag71xx_mdio_dump_regs(am); ++ ++ platform_set_drvdata(pdev, am); ++ return 0; ++ ++err_free_bus: ++ mdiobus_free(am->mii_bus); ++err_iounmap: ++ iounmap(am->mdio_base); ++err_free_mdio: ++ kfree(am); ++err_out: ++ return err; ++} ++ ++static int ag71xx_mdio_remove(struct platform_device *pdev) ++{ ++ struct ag71xx_mdio *am = platform_get_drvdata(pdev); ++ ++ if (am) { ++ mdiobus_unregister(am->mii_bus); ++ mdiobus_free(am->mii_bus); ++ iounmap(am->mdio_base); ++ kfree(am); ++ platform_set_drvdata(pdev, NULL); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver ag71xx_mdio_driver = { ++ .probe = ag71xx_mdio_probe, ++ .remove = ag71xx_mdio_remove, ++ .driver = { ++ .name = "ag71xx-mdio", ++ } ++}; ++ ++int __init ag71xx_mdio_driver_init(void) ++{ ++ return platform_driver_register(&ag71xx_mdio_driver); ++} ++ ++void ag71xx_mdio_driver_exit(void) ++{ ++ platform_driver_unregister(&ag71xx_mdio_driver); ++} +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c +new file mode 100644 +index 0000000000..336143f753 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c +@@ -0,0 +1,261 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * 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 "ag71xx.h" ++ ++static void ag71xx_phy_link_adjust(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ struct phy_device *phydev = ag->phy_dev; ++ unsigned long flags; ++ int status_change = 0; ++ ++ spin_lock_irqsave(&ag->lock, flags); ++ ++ if (phydev->link) { ++ if (ag->duplex != phydev->duplex ++ || ag->speed != phydev->speed) { ++ status_change = 1; ++ } ++ } ++ ++ if (phydev->link != ag->link) ++ status_change = 1; ++ ++ ag->link = phydev->link; ++ ag->duplex = phydev->duplex; ++ ag->speed = phydev->speed; ++ ++ if (status_change) ++ ag71xx_link_adjust(ag); ++ ++ spin_unlock_irqrestore(&ag->lock, flags); ++} ++ ++void ag71xx_phy_start(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ ++ if (ag->phy_dev) { ++ phy_start(ag->phy_dev); ++ } else if (pdata->mii_bus_dev && pdata->switch_data) { ++ ag71xx_ar7240_start(ag); ++ } else { ++ ag->link = 1; ++ ag71xx_link_adjust(ag); ++ } ++} ++ ++void ag71xx_phy_stop(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ unsigned long flags; ++ ++ if (ag->phy_dev) ++ phy_stop(ag->phy_dev); ++ else if (pdata->mii_bus_dev && pdata->switch_data) ++ ag71xx_ar7240_stop(ag); ++ ++ spin_lock_irqsave(&ag->lock, flags); ++ if (ag->link) { ++ ag->link = 0; ++ ag71xx_link_adjust(ag); ++ } ++ spin_unlock_irqrestore(&ag->lock, flags); ++} ++ ++static int ag71xx_phy_connect_fixed(struct ag71xx *ag) ++{ ++ struct device *dev = &ag->pdev->dev; ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ int ret = 0; ++ ++ /* use fixed settings */ ++ switch (pdata->speed) { ++ case SPEED_10: ++ case SPEED_100: ++ case SPEED_1000: ++ break; ++ default: ++ dev_err(dev, "invalid speed specified\n"); ++ ret = -EINVAL; ++ break; ++ } ++ ++ dev_dbg(dev, "using fixed link parameters\n"); ++ ++ ag->duplex = pdata->duplex; ++ ag->speed = pdata->speed; ++ ++ return ret; ++} ++ ++static int ag71xx_phy_connect_multi(struct ag71xx *ag) ++{ ++ struct device *dev = &ag->pdev->dev; ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ struct phy_device *phydev = NULL; ++ int phy_addr; ++ int ret = 0; ++ ++ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { ++ if (!(pdata->phy_mask & (1 << phy_addr))) ++ continue; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ if (ag->mii_bus->phy_map[phy_addr] == NULL) ++ continue; ++ ++ DBG("%s: PHY found at %s, uid=%08x\n", ++ dev_name(dev), ++ dev_name(&ag->mii_bus->phy_map[phy_addr]->dev), ++ ag->mii_bus->phy_map[phy_addr]->phy_id); ++ ++ if (phydev == NULL) ++ phydev = ag->mii_bus->phy_map[phy_addr]; ++#else ++ if (ag->mii_bus->mdio_map[phy_addr] == NULL) ++ continue; ++ ++ DBG("%s: PHY found at %s, uid=%08x\n", ++ dev_name(dev), ++ dev_name(&ag->mii_bus->mdio_map[phy_addr]->dev), ++ (phydev) ? phydev->phy_id : 0); ++ ++ if (phydev == NULL) ++ phydev = mdiobus_get_phy(ag->mii_bus, phy_addr); ++#endif ++ } ++ ++ if (!phydev) { ++ dev_err(dev, "no PHY found with phy_mask=%08x\n", ++ pdata->phy_mask); ++ return -ENODEV; ++ } ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ ag->phy_dev = phy_connect(ag->dev, dev_name(&phydev->dev), ++#else ++ ag->phy_dev = phy_connect(ag->dev, phydev_name(phydev), ++#endif ++ &ag71xx_phy_link_adjust, ++ pdata->phy_if_mode); ++ ++ if (IS_ERR(ag->phy_dev)) { ++ dev_err(dev, "could not connect to PHY at %s\n", ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ dev_name(&phydev->dev)); ++#else ++ phydev_name(phydev)); ++#endif ++ return PTR_ERR(ag->phy_dev); ++ } ++ ++ /* mask with MAC supported features */ ++ if (pdata->has_gbit) ++ phydev->supported &= PHY_GBIT_FEATURES; ++ else ++ phydev->supported &= PHY_BASIC_FEATURES; ++ ++ phydev->advertising = phydev->supported; ++ ++ dev_info(dev, "connected to PHY at %s [uid=%08x, driver=%s]\n", ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ dev_name(&phydev->dev), ++#else ++ phydev_name(phydev), ++#endif ++ phydev->phy_id, phydev->drv->name); ++ ++ ag->link = 0; ++ ag->speed = 0; ++ ag->duplex = -1; ++ ++ return ret; ++} ++ ++static int dev_is_class(struct device *dev, void *class) ++{ ++ if (dev->class != NULL && !strcmp(dev->class->name, class)) ++ return 1; ++ ++ return 0; ++} ++ ++static struct device *dev_find_class(struct device *parent, char *class) ++{ ++ if (dev_is_class(parent, class)) { ++ get_device(parent); ++ return parent; ++ } ++ ++ return device_find_child(parent, class, dev_is_class); ++} ++ ++static struct mii_bus *dev_to_mii_bus(struct device *dev) ++{ ++ struct device *d; ++ ++ d = dev_find_class(dev, "mdio_bus"); ++ if (d != NULL) { ++ struct mii_bus *bus; ++ ++ bus = to_mii_bus(d); ++ put_device(d); ++ ++ return bus; ++ } ++ ++ return NULL; ++} ++ ++int ag71xx_phy_connect(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ ++ if (pdata->mii_bus_dev == NULL || ++ pdata->mii_bus_dev->bus == NULL ) ++ return ag71xx_phy_connect_fixed(ag); ++ ++ ag->mii_bus = dev_to_mii_bus(pdata->mii_bus_dev); ++ if (ag->mii_bus == NULL) { ++ dev_err(&ag->pdev->dev, "unable to find MII bus on device '%s'\n", ++ dev_name(pdata->mii_bus_dev)); ++ return -ENODEV; ++ } ++ ++ /* Reset the mdio bus explicitly */ ++ if (ag->mii_bus->reset) { ++ mutex_lock(&ag->mii_bus->mdio_lock); ++ ag->mii_bus->reset(ag->mii_bus); ++ mutex_unlock(&ag->mii_bus->mdio_lock); ++ } ++ ++ if (pdata->switch_data) ++ return ag71xx_ar7240_init(ag); ++ ++ if (pdata->phy_mask) ++ return ag71xx_phy_connect_multi(ag); ++ ++ return ag71xx_phy_connect_fixed(ag); ++} ++ ++void ag71xx_phy_disconnect(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ ++ if (pdata->switch_data) ++ ag71xx_ar7240_cleanup(ag); ++ else if (ag->phy_dev) ++ phy_disconnect(ag->phy_dev); ++} +diff --git a/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c b/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c +new file mode 100644 +index 0000000000..18af83b67c +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c +@@ -0,0 +1,347 @@ ++/* ++ * SPI driver for the CPLD chip on the Mikrotik RB4xx boards ++ * ++ * Copyright (C) 2010 Gabor Juhos ++ * ++ * This file was based on the patches for Linux 2.6.27.39 published by ++ * MikroTik for their RouterBoard 4xx series devices. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define DRV_NAME "spi-rb4xx-cpld" ++#define DRV_DESC "RB4xx CPLD driver" ++#define DRV_VERSION "0.1.0" ++ ++#define CPLD_CMD_WRITE_NAND 0x08 /* send cmd, n x send data, send indle */ ++#define CPLD_CMD_WRITE_CFG 0x09 /* send cmd, n x send cfg */ ++#define CPLD_CMD_READ_NAND 0x0a /* send cmd, send idle, n x read data */ ++#define CPLD_CMD_READ_FAST 0x0b /* send cmd, 4 x idle, n x read data */ ++#define CPLD_CMD_LED5_ON 0x0c /* send cmd */ ++#define CPLD_CMD_LED5_OFF 0x0d /* send cmd */ ++ ++struct rb4xx_cpld { ++ struct spi_device *spi; ++ struct mutex lock; ++ struct gpio_chip chip; ++ unsigned int config; ++}; ++ ++static struct rb4xx_cpld *rb4xx_cpld; ++ ++static inline struct rb4xx_cpld *gpio_to_cpld(struct gpio_chip *chip) ++{ ++ return container_of(chip, struct rb4xx_cpld, chip); ++} ++ ++static int rb4xx_cpld_write_cmd(struct rb4xx_cpld *cpld, unsigned char cmd) ++{ ++ struct spi_transfer t[1]; ++ struct spi_message m; ++ unsigned char tx_buf[1]; ++ int err; ++ ++ spi_message_init(&m); ++ memset(&t, 0, sizeof(t)); ++ ++ t[0].tx_buf = tx_buf; ++ t[0].len = sizeof(tx_buf); ++ spi_message_add_tail(&t[0], &m); ++ ++ tx_buf[0] = cmd; ++ ++ err = spi_sync(cpld->spi, &m); ++ return err; ++} ++ ++static int rb4xx_cpld_write_cfg(struct rb4xx_cpld *cpld, unsigned char config) ++{ ++ struct spi_transfer t[1]; ++ struct spi_message m; ++ unsigned char cmd[2]; ++ int err; ++ ++ spi_message_init(&m); ++ memset(&t, 0, sizeof(t)); ++ ++ t[0].tx_buf = cmd; ++ t[0].len = sizeof(cmd); ++ spi_message_add_tail(&t[0], &m); ++ ++ cmd[0] = CPLD_CMD_WRITE_CFG; ++ cmd[1] = config; ++ ++ err = spi_sync(cpld->spi, &m); ++ return err; ++} ++ ++static int __rb4xx_cpld_change_cfg(struct rb4xx_cpld *cpld, unsigned mask, ++ unsigned value) ++{ ++ unsigned int config; ++ int err; ++ ++ config = cpld->config & ~mask; ++ config |= value; ++ ++ if ((cpld->config ^ config) & 0xff) { ++ err = rb4xx_cpld_write_cfg(cpld, config); ++ if (err) ++ return err; ++ } ++ ++ if ((cpld->config ^ config) & CPLD_CFG_nLED5) { ++ err = rb4xx_cpld_write_cmd(cpld, (value) ? CPLD_CMD_LED5_ON : ++ CPLD_CMD_LED5_OFF); ++ if (err) ++ return err; ++ } ++ ++ cpld->config = config; ++ return 0; ++} ++ ++int rb4xx_cpld_change_cfg(unsigned mask, unsigned value) ++{ ++ int ret; ++ ++ if (rb4xx_cpld == NULL) ++ return -ENODEV; ++ ++ mutex_lock(&rb4xx_cpld->lock); ++ ret = __rb4xx_cpld_change_cfg(rb4xx_cpld, mask, value); ++ mutex_unlock(&rb4xx_cpld->lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(rb4xx_cpld_change_cfg); ++ ++int rb4xx_cpld_read(unsigned char *rx_buf, unsigned count) ++{ ++ static const unsigned char cmd[2] = { CPLD_CMD_READ_NAND, 0 }; ++ struct spi_transfer t[2] = { ++ { ++ .tx_buf = &cmd, ++ .len = 2, ++ }, { ++ .rx_buf = rx_buf, ++ .len = count, ++ }, ++ }; ++ struct spi_message m; ++ ++ if (rb4xx_cpld == NULL) ++ return -ENODEV; ++ ++ spi_message_init(&m); ++ spi_message_add_tail(&t[0], &m); ++ spi_message_add_tail(&t[1], &m); ++ return spi_sync(rb4xx_cpld->spi, &m); ++} ++EXPORT_SYMBOL_GPL(rb4xx_cpld_read); ++ ++int rb4xx_cpld_write(const unsigned char *buf, unsigned count) ++{ ++ static const unsigned char cmd = CPLD_CMD_WRITE_NAND; ++ struct spi_transfer t[3] = { ++ { ++ .tx_buf = &cmd, ++ .len = 1, ++ }, { ++ .tx_buf = buf, ++ .len = count, ++ .tx_nbits = SPI_NBITS_DUAL, ++ }, { ++ .len = 1, ++ .tx_nbits = SPI_NBITS_DUAL, ++ }, ++ }; ++ struct spi_message m; ++ ++ if (rb4xx_cpld == NULL) ++ return -ENODEV; ++ ++ spi_message_init(&m); ++ spi_message_add_tail(&t[0], &m); ++ spi_message_add_tail(&t[1], &m); ++ spi_message_add_tail(&t[2], &m); ++ return spi_sync(rb4xx_cpld->spi, &m); ++} ++EXPORT_SYMBOL_GPL(rb4xx_cpld_write); ++ ++static int rb4xx_cpld_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct rb4xx_cpld *cpld = gpio_to_cpld(chip); ++ int ret; ++ ++ mutex_lock(&cpld->lock); ++ ret = (cpld->config >> offset) & 1; ++ mutex_unlock(&cpld->lock); ++ ++ return ret; ++} ++ ++static void rb4xx_cpld_gpio_set(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct rb4xx_cpld *cpld = gpio_to_cpld(chip); ++ ++ mutex_lock(&cpld->lock); ++ __rb4xx_cpld_change_cfg(cpld, (1 << offset), !!value << offset); ++ mutex_unlock(&cpld->lock); ++} ++ ++static int rb4xx_cpld_gpio_direction_input(struct gpio_chip *chip, ++ unsigned offset) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int rb4xx_cpld_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, ++ int value) ++{ ++ struct rb4xx_cpld *cpld = gpio_to_cpld(chip); ++ int ret; ++ ++ mutex_lock(&cpld->lock); ++ ret = __rb4xx_cpld_change_cfg(cpld, (1 << offset), !!value << offset); ++ mutex_unlock(&cpld->lock); ++ ++ return ret; ++} ++ ++static int rb4xx_cpld_gpio_init(struct rb4xx_cpld *cpld, unsigned int base) ++{ ++ int err; ++ ++ /* init config */ ++ cpld->config = CPLD_CFG_nLED1 | CPLD_CFG_nLED2 | CPLD_CFG_nLED3 | ++ CPLD_CFG_nLED4 | CPLD_CFG_nCE; ++ rb4xx_cpld_write_cfg(cpld, cpld->config); ++ ++ /* setup GPIO chip */ ++ cpld->chip.label = DRV_NAME; ++ ++ cpld->chip.get = rb4xx_cpld_gpio_get; ++ cpld->chip.set = rb4xx_cpld_gpio_set; ++ cpld->chip.direction_input = rb4xx_cpld_gpio_direction_input; ++ cpld->chip.direction_output = rb4xx_cpld_gpio_direction_output; ++ ++ cpld->chip.base = base; ++ cpld->chip.ngpio = CPLD_NUM_GPIOS; ++ cpld->chip.can_sleep = 1; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) ++ cpld->chip.dev = &cpld->spi->dev; ++#else ++ cpld->chip.parent = &cpld->spi->dev; ++#endif ++ cpld->chip.owner = THIS_MODULE; ++ ++ err = gpiochip_add(&cpld->chip); ++ if (err) ++ dev_err(&cpld->spi->dev, "adding GPIO chip failed, err=%d\n", ++ err); ++ ++ return err; ++} ++ ++static int rb4xx_cpld_probe(struct spi_device *spi) ++{ ++ struct rb4xx_cpld *cpld; ++ struct rb4xx_cpld_platform_data *pdata; ++ int err; ++ ++ pdata = spi->dev.platform_data; ++ if (!pdata) { ++ dev_dbg(&spi->dev, "no platform data\n"); ++ return -EINVAL; ++ } ++ ++ cpld = kzalloc(sizeof(*cpld), GFP_KERNEL); ++ if (!cpld) { ++ dev_err(&spi->dev, "no memory for private data\n"); ++ return -ENOMEM; ++ } ++ ++ mutex_init(&cpld->lock); ++ cpld->spi = spi_dev_get(spi); ++ dev_set_drvdata(&spi->dev, cpld); ++ ++ spi->mode = SPI_MODE_0 | SPI_TX_DUAL; ++ spi->bits_per_word = 8; ++ err = spi_setup(spi); ++ if (err) { ++ dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); ++ goto err_drvdata; ++ } ++ ++ err = rb4xx_cpld_gpio_init(cpld, pdata->gpio_base); ++ if (err) ++ goto err_drvdata; ++ ++ rb4xx_cpld = cpld; ++ ++ return 0; ++ ++err_drvdata: ++ dev_set_drvdata(&spi->dev, NULL); ++ kfree(cpld); ++ ++ return err; ++} ++ ++static int rb4xx_cpld_remove(struct spi_device *spi) ++{ ++ struct rb4xx_cpld *cpld; ++ ++ rb4xx_cpld = NULL; ++ cpld = dev_get_drvdata(&spi->dev); ++ dev_set_drvdata(&spi->dev, NULL); ++ kfree(cpld); ++ ++ return 0; ++} ++ ++static struct spi_driver rb4xx_cpld_driver = { ++ .driver = { ++ .name = DRV_NAME, ++ .bus = &spi_bus_type, ++ .owner = THIS_MODULE, ++ }, ++ .probe = rb4xx_cpld_probe, ++ .remove = rb4xx_cpld_remove, ++}; ++ ++static int __init rb4xx_cpld_init(void) ++{ ++ return spi_register_driver(&rb4xx_cpld_driver); ++} ++module_init(rb4xx_cpld_init); ++ ++static void __exit rb4xx_cpld_exit(void) ++{ ++ spi_unregister_driver(&rb4xx_cpld_driver); ++} ++module_exit(rb4xx_cpld_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/ar71xx/files/drivers/spi/spi-rb4xx.c b/target/linux/ar71xx/files/drivers/spi/spi-rb4xx.c +new file mode 100644 +index 0000000000..2d95e80495 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/spi/spi-rb4xx.c +@@ -0,0 +1,430 @@ ++/* ++ * SPI controller driver for the Mikrotik RB4xx boards ++ * ++ * Copyright (C) 2010 Gabor Juhos ++ * ++ * This file was based on the patches for Linux 2.6.27.39 published by ++ * MikroTik for their RouterBoard 4xx series devices. ++ * ++ * 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 ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define DRV_NAME "rb4xx-spi" ++#define DRV_DESC "Mikrotik RB4xx SPI controller driver" ++#define DRV_VERSION "0.1.0" ++ ++#define SPI_CTRL_FASTEST 0x40 ++#define SPI_FLASH_HZ 33333334 ++#define SPI_CPLD_HZ 33333334 ++ ++#define CPLD_CMD_READ_FAST 0x0b ++ ++#undef RB4XX_SPI_DEBUG ++ ++struct rb4xx_spi { ++ void __iomem *base; ++ struct spi_master *master; ++ ++ unsigned spi_ctrl_flash; ++ unsigned spi_ctrl_fread; ++ ++ struct clk *ahb_clk; ++ unsigned long ahb_freq; ++ ++ spinlock_t lock; ++ struct list_head queue; ++ int busy:1; ++ int cs_wait; ++}; ++ ++static unsigned spi_clk_low = AR71XX_SPI_IOC_CS1; ++ ++#ifdef RB4XX_SPI_DEBUG ++static inline void do_spi_delay(void) ++{ ++ ndelay(20000); ++} ++#else ++static inline void do_spi_delay(void) { } ++#endif ++ ++static inline void do_spi_init(struct spi_device *spi) ++{ ++ unsigned cs = AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1; ++ ++ if (!(spi->mode & SPI_CS_HIGH)) ++ cs ^= (spi->chip_select == 2) ? AR71XX_SPI_IOC_CS1 : ++ AR71XX_SPI_IOC_CS0; ++ ++ spi_clk_low = cs; ++} ++ ++static inline void do_spi_finish(void __iomem *base) ++{ ++ do_spi_delay(); ++ __raw_writel(AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1, ++ base + AR71XX_SPI_REG_IOC); ++} ++ ++static inline void do_spi_clk(void __iomem *base, int bit) ++{ ++ unsigned bval = spi_clk_low | ((bit & 1) ? AR71XX_SPI_IOC_DO : 0); ++ ++ do_spi_delay(); ++ __raw_writel(bval, base + AR71XX_SPI_REG_IOC); ++ do_spi_delay(); ++ __raw_writel(bval | AR71XX_SPI_IOC_CLK, base + AR71XX_SPI_REG_IOC); ++} ++ ++static void do_spi_byte(void __iomem *base, unsigned char byte) ++{ ++ do_spi_clk(base, byte >> 7); ++ do_spi_clk(base, byte >> 6); ++ do_spi_clk(base, byte >> 5); ++ do_spi_clk(base, byte >> 4); ++ do_spi_clk(base, byte >> 3); ++ do_spi_clk(base, byte >> 2); ++ do_spi_clk(base, byte >> 1); ++ do_spi_clk(base, byte); ++ ++ pr_debug("spi_byte sent 0x%02x got 0x%02x\n", ++ (unsigned)byte, ++ (unsigned char)__raw_readl(base + AR71XX_SPI_REG_RDS)); ++} ++ ++static inline void do_spi_clk_fast(void __iomem *base, unsigned bit1, ++ unsigned bit2) ++{ ++ unsigned bval = (spi_clk_low | ++ ((bit1 & 1) ? AR71XX_SPI_IOC_DO : 0) | ++ ((bit2 & 1) ? AR71XX_SPI_IOC_CS2 : 0)); ++ do_spi_delay(); ++ __raw_writel(bval, base + AR71XX_SPI_REG_IOC); ++ do_spi_delay(); ++ __raw_writel(bval | AR71XX_SPI_IOC_CLK, base + AR71XX_SPI_REG_IOC); ++} ++ ++static void do_spi_byte_fast(void __iomem *base, unsigned char byte) ++{ ++ do_spi_clk_fast(base, byte >> 7, byte >> 6); ++ do_spi_clk_fast(base, byte >> 5, byte >> 4); ++ do_spi_clk_fast(base, byte >> 3, byte >> 2); ++ do_spi_clk_fast(base, byte >> 1, byte >> 0); ++ ++ pr_debug("spi_byte_fast sent 0x%02x got 0x%02x\n", ++ (unsigned)byte, ++ (unsigned char) __raw_readl(base + AR71XX_SPI_REG_RDS)); ++} ++ ++static int rb4xx_spi_txrx(void __iomem *base, struct spi_transfer *t) ++{ ++ const unsigned char *tx_ptr = t->tx_buf; ++ unsigned char *rx_ptr = t->rx_buf; ++ unsigned i; ++ ++ pr_debug("spi_txrx len %u tx %u rx %u\n", ++ t->len, ++ (t->tx_buf ? 1 : 0), ++ (t->rx_buf ? 1 : 0)); ++ ++ for (i = 0; i < t->len; ++i) { ++ unsigned char sdata = tx_ptr ? tx_ptr[i] : 0; ++ ++ if (t->tx_nbits == SPI_NBITS_DUAL) ++ do_spi_byte_fast(base, sdata); ++ else ++ do_spi_byte(base, sdata); ++ ++ if (rx_ptr) ++ rx_ptr[i] = __raw_readl(base + AR71XX_SPI_REG_RDS) & 0xff; ++ } ++ ++ return i; ++} ++ ++static int rb4xx_spi_msg(struct rb4xx_spi *rbspi, struct spi_message *m) ++{ ++ struct spi_transfer *t = NULL; ++ void __iomem *base = rbspi->base; ++ ++ m->status = 0; ++ if (list_empty(&m->transfers)) ++ return -1; ++ ++ __raw_writel(AR71XX_SPI_FS_GPIO, base + AR71XX_SPI_REG_FS); ++ __raw_writel(SPI_CTRL_FASTEST, base + AR71XX_SPI_REG_CTRL); ++ do_spi_init(m->spi); ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ int len; ++ ++ len = rb4xx_spi_txrx(base, t); ++ if (len != t->len) { ++ m->status = -EMSGSIZE; ++ break; ++ } ++ m->actual_length += len; ++ ++ if (t->cs_change) { ++ if (list_is_last(&t->transfer_list, &m->transfers)) { ++ /* wait for continuation */ ++ return m->spi->chip_select; ++ } ++ do_spi_finish(base); ++ ndelay(100); ++ } ++ } ++ ++ do_spi_finish(base); ++ __raw_writel(rbspi->spi_ctrl_flash, base + AR71XX_SPI_REG_CTRL); ++ __raw_writel(0, base + AR71XX_SPI_REG_FS); ++ return -1; ++} ++ ++static void rb4xx_spi_process_queue_locked(struct rb4xx_spi *rbspi, ++ unsigned long *flags) ++{ ++ int cs = rbspi->cs_wait; ++ ++ rbspi->busy = 1; ++ while (!list_empty(&rbspi->queue)) { ++ struct spi_message *m; ++ ++ list_for_each_entry(m, &rbspi->queue, queue) ++ if (cs < 0 || cs == m->spi->chip_select) ++ break; ++ ++ if (&m->queue == &rbspi->queue) ++ break; ++ ++ list_del_init(&m->queue); ++ spin_unlock_irqrestore(&rbspi->lock, *flags); ++ ++ cs = rb4xx_spi_msg(rbspi, m); ++ m->complete(m->context); ++ ++ spin_lock_irqsave(&rbspi->lock, *flags); ++ } ++ ++ rbspi->cs_wait = cs; ++ rbspi->busy = 0; ++ ++ if (cs >= 0) { ++ /* TODO: add timer to unlock cs after 1s inactivity */ ++ } ++} ++ ++static int rb4xx_spi_transfer(struct spi_device *spi, ++ struct spi_message *m) ++{ ++ struct rb4xx_spi *rbspi = spi_master_get_devdata(spi->master); ++ unsigned long flags; ++ ++ m->actual_length = 0; ++ m->status = -EINPROGRESS; ++ ++ spin_lock_irqsave(&rbspi->lock, flags); ++ list_add_tail(&m->queue, &rbspi->queue); ++ if (rbspi->busy || ++ (rbspi->cs_wait >= 0 && rbspi->cs_wait != m->spi->chip_select)) { ++ /* job will be done later */ ++ spin_unlock_irqrestore(&rbspi->lock, flags); ++ return 0; ++ } ++ ++ /* process job in current context */ ++ rb4xx_spi_process_queue_locked(rbspi, &flags); ++ spin_unlock_irqrestore(&rbspi->lock, flags); ++ ++ return 0; ++} ++ ++static int rb4xx_spi_setup(struct spi_device *spi) ++{ ++ struct rb4xx_spi *rbspi = spi_master_get_devdata(spi->master); ++ unsigned long flags; ++ ++ if (spi->mode & ~(SPI_CS_HIGH | SPI_TX_DUAL)) { ++ dev_err(&spi->dev, "mode %x not supported\n", ++ (unsigned) spi->mode); ++ return -EINVAL; ++ } ++ ++ if (spi->bits_per_word != 8 && spi->bits_per_word != 0) { ++ dev_err(&spi->dev, "bits_per_word %u not supported\n", ++ (unsigned) spi->bits_per_word); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&rbspi->lock, flags); ++ if (rbspi->cs_wait == spi->chip_select && !rbspi->busy) { ++ rbspi->cs_wait = -1; ++ rb4xx_spi_process_queue_locked(rbspi, &flags); ++ } ++ spin_unlock_irqrestore(&rbspi->lock, flags); ++ ++ return 0; ++} ++ ++static unsigned get_spi_ctrl(struct rb4xx_spi *rbspi, unsigned hz_max, ++ const char *name) ++{ ++ unsigned div; ++ ++ div = (rbspi->ahb_freq - 1) / (2 * hz_max); ++ ++ /* ++ * CPU has a bug at (div == 0) - first bit read is random ++ */ ++ if (div == 0) ++ ++div; ++ ++ if (name) { ++ unsigned ahb_khz = (rbspi->ahb_freq + 500) / 1000; ++ unsigned div_real = 2 * (div + 1); ++ pr_debug("rb4xx: %s SPI clock %u kHz (AHB %u kHz / %u)\n", ++ name, ++ ahb_khz / div_real, ++ ahb_khz, div_real); ++ } ++ ++ return SPI_CTRL_FASTEST + div; ++} ++ ++static int rb4xx_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct rb4xx_spi *rbspi; ++ struct resource *r; ++ int err = 0; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*rbspi)); ++ if (master == NULL) { ++ dev_err(&pdev->dev, "no memory for spi_master\n"); ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ master->bus_num = 0; ++ master->num_chipselect = 3; ++ master->mode_bits = SPI_TX_DUAL; ++ master->setup = rb4xx_spi_setup; ++ master->transfer = rb4xx_spi_transfer; ++ ++ rbspi = spi_master_get_devdata(master); ++ ++ rbspi->ahb_clk = clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(rbspi->ahb_clk)) { ++ err = PTR_ERR(rbspi->ahb_clk); ++ goto err_put_master; ++ } ++ ++ err = clk_prepare_enable(rbspi->ahb_clk); ++ if (err) ++ goto err_clk_put; ++ ++ rbspi->ahb_freq = clk_get_rate(rbspi->ahb_clk); ++ if (!rbspi->ahb_freq) { ++ err = -EINVAL; ++ goto err_clk_disable; ++ } ++ ++ platform_set_drvdata(pdev, rbspi); ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ err = -ENOENT; ++ goto err_clk_disable; ++ } ++ ++ rbspi->base = ioremap(r->start, r->end - r->start + 1); ++ if (!rbspi->base) { ++ err = -ENXIO; ++ goto err_clk_disable; ++ } ++ ++ rbspi->master = master; ++ rbspi->spi_ctrl_flash = get_spi_ctrl(rbspi, SPI_FLASH_HZ, "FLASH"); ++ rbspi->spi_ctrl_fread = get_spi_ctrl(rbspi, SPI_CPLD_HZ, "CPLD"); ++ rbspi->cs_wait = -1; ++ ++ spin_lock_init(&rbspi->lock); ++ INIT_LIST_HEAD(&rbspi->queue); ++ ++ err = spi_register_master(master); ++ if (err) { ++ dev_err(&pdev->dev, "failed to register SPI master\n"); ++ goto err_iounmap; ++ } ++ ++ return 0; ++ ++err_iounmap: ++ iounmap(rbspi->base); ++err_clk_disable: ++ clk_disable_unprepare(rbspi->ahb_clk); ++err_clk_put: ++ clk_put(rbspi->ahb_clk); ++err_put_master: ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(master); ++err_out: ++ return err; ++} ++ ++static int rb4xx_spi_remove(struct platform_device *pdev) ++{ ++ struct rb4xx_spi *rbspi = platform_get_drvdata(pdev); ++ ++ iounmap(rbspi->base); ++ clk_disable_unprepare(rbspi->ahb_clk); ++ clk_put(rbspi->ahb_clk); ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(rbspi->master); ++ ++ return 0; ++} ++ ++static struct platform_driver rb4xx_spi_drv = { ++ .probe = rb4xx_spi_probe, ++ .remove = rb4xx_spi_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init rb4xx_spi_init(void) ++{ ++ return platform_driver_register(&rb4xx_spi_drv); ++} ++subsys_initcall(rb4xx_spi_init); ++ ++static void __exit rb4xx_spi_exit(void) ++{ ++ platform_driver_unregister(&rb4xx_spi_drv); ++} ++ ++module_exit(rb4xx_spi_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c b/target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c +new file mode 100644 +index 0000000000..b712e71875 +--- /dev/null ++++ b/target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c +@@ -0,0 +1,621 @@ ++/* ++ * SPI driver for the Vitesse VSC7385 ethernet switch ++ * ++ * Copyright (C) 2009 Gabor Juhos ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * 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 ++#include ++#include ++#include ++ ++#define DRV_NAME "spi-vsc7385" ++#define DRV_DESC "Vitesse VSC7385 Gbit ethernet switch driver" ++#define DRV_VERSION "0.1.0" ++ ++#define VSC73XX_BLOCK_MAC 0x1 ++#define VSC73XX_BLOCK_2 0x2 ++#define VSC73XX_BLOCK_MII 0x3 ++#define VSC73XX_BLOCK_4 0x4 ++#define VSC73XX_BLOCK_5 0x5 ++#define VSC73XX_BLOCK_SYSTEM 0x7 ++ ++#define VSC73XX_SUBBLOCK_PORT_0 0 ++#define VSC73XX_SUBBLOCK_PORT_1 1 ++#define VSC73XX_SUBBLOCK_PORT_2 2 ++#define VSC73XX_SUBBLOCK_PORT_3 3 ++#define VSC73XX_SUBBLOCK_PORT_4 4 ++#define VSC73XX_SUBBLOCK_PORT_MAC 6 ++ ++/* MAC Block registers */ ++#define VSC73XX_MAC_CFG 0x0 ++#define VSC73XX_ADVPORTM 0x19 ++#define VSC73XX_RXOCT 0x50 ++#define VSC73XX_TXOCT 0x51 ++#define VSC73XX_C_RX0 0x52 ++#define VSC73XX_C_RX1 0x53 ++#define VSC73XX_C_RX2 0x54 ++#define VSC73XX_C_TX0 0x55 ++#define VSC73XX_C_TX1 0x56 ++#define VSC73XX_C_TX2 0x57 ++#define VSC73XX_C_CFG 0x58 ++ ++/* MAC_CFG register bits */ ++#define VSC73XX_MAC_CFG_WEXC_DIS (1 << 31) ++#define VSC73XX_MAC_CFG_PORT_RST (1 << 29) ++#define VSC73XX_MAC_CFG_TX_EN (1 << 28) ++#define VSC73XX_MAC_CFG_SEED_LOAD (1 << 27) ++#define VSC73XX_MAC_CFG_FDX (1 << 18) ++#define VSC73XX_MAC_CFG_GIGE (1 << 17) ++#define VSC73XX_MAC_CFG_RX_EN (1 << 16) ++#define VSC73XX_MAC_CFG_VLAN_DBLAWR (1 << 15) ++#define VSC73XX_MAC_CFG_VLAN_AWR (1 << 14) ++#define VSC73XX_MAC_CFG_100_BASE_T (1 << 13) ++#define VSC73XX_MAC_CFG_TX_IPG(x) (((x) & 0x1f) << 6) ++#define VSC73XX_MAC_CFG_MAC_RX_RST (1 << 5) ++#define VSC73XX_MAC_CFG_MAC_TX_RST (1 << 4) ++#define VSC73XX_MAC_CFG_BIT2 (1 << 2) ++#define VSC73XX_MAC_CFG_CLK_SEL(x) ((x) & 0x3) ++ ++/* ADVPORTM register bits */ ++#define VSC73XX_ADVPORTM_IFG_PPM (1 << 7) ++#define VSC73XX_ADVPORTM_EXC_COL_CONT (1 << 6) ++#define VSC73XX_ADVPORTM_EXT_PORT (1 << 5) ++#define VSC73XX_ADVPORTM_INV_GTX (1 << 4) ++#define VSC73XX_ADVPORTM_ENA_GTX (1 << 3) ++#define VSC73XX_ADVPORTM_DDR_MODE (1 << 2) ++#define VSC73XX_ADVPORTM_IO_LOOPBACK (1 << 1) ++#define VSC73XX_ADVPORTM_HOST_LOOPBACK (1 << 0) ++ ++/* MII Block registers */ ++#define VSC73XX_MII_STAT 0x0 ++#define VSC73XX_MII_CMD 0x1 ++#define VSC73XX_MII_DATA 0x2 ++ ++/* System Block registers */ ++#define VSC73XX_ICPU_SIPAD 0x01 ++#define VSC73XX_ICPU_CLOCK_DELAY 0x05 ++#define VSC73XX_ICPU_CTRL 0x10 ++#define VSC73XX_ICPU_ADDR 0x11 ++#define VSC73XX_ICPU_SRAM 0x12 ++#define VSC73XX_ICPU_MBOX_VAL 0x15 ++#define VSC73XX_ICPU_MBOX_SET 0x16 ++#define VSC73XX_ICPU_MBOX_CLR 0x17 ++#define VSC73XX_ICPU_CHIPID 0x18 ++#define VSC73XX_ICPU_GPIO 0x34 ++ ++#define VSC73XX_ICPU_CTRL_CLK_DIV (1 << 8) ++#define VSC73XX_ICPU_CTRL_SRST_HOLD (1 << 7) ++#define VSC73XX_ICPU_CTRL_BOOT_EN (1 << 3) ++#define VSC73XX_ICPU_CTRL_EXT_ACC_EN (1 << 2) ++#define VSC73XX_ICPU_CTRL_CLK_EN (1 << 1) ++#define VSC73XX_ICPU_CTRL_SRST (1 << 0) ++ ++#define VSC73XX_ICPU_CHIPID_ID_SHIFT 12 ++#define VSC73XX_ICPU_CHIPID_ID_MASK 0xffff ++#define VSC73XX_ICPU_CHIPID_REV_SHIFT 28 ++#define VSC73XX_ICPU_CHIPID_REV_MASK 0xf ++#define VSC73XX_ICPU_CHIPID_ID_7385 0x7385 ++#define VSC73XX_ICPU_CHIPID_ID_7395 0x7395 ++ ++#define VSC73XX_CMD_MODE_READ 0 ++#define VSC73XX_CMD_MODE_WRITE 1 ++#define VSC73XX_CMD_MODE_SHIFT 4 ++#define VSC73XX_CMD_BLOCK_SHIFT 5 ++#define VSC73XX_CMD_BLOCK_MASK 0x7 ++#define VSC73XX_CMD_SUBBLOCK_MASK 0xf ++ ++#define VSC7385_CLOCK_DELAY ((3 << 4) | 3) ++#define VSC7385_CLOCK_DELAY_MASK ((3 << 4) | 3) ++ ++#define VSC73XX_ICPU_CTRL_STOP (VSC73XX_ICPU_CTRL_SRST_HOLD | \ ++ VSC73XX_ICPU_CTRL_BOOT_EN | \ ++ VSC73XX_ICPU_CTRL_EXT_ACC_EN) ++ ++#define VSC73XX_ICPU_CTRL_START (VSC73XX_ICPU_CTRL_CLK_DIV | \ ++ VSC73XX_ICPU_CTRL_BOOT_EN | \ ++ VSC73XX_ICPU_CTRL_CLK_EN | \ ++ VSC73XX_ICPU_CTRL_SRST) ++ ++#define VSC7385_ADVPORTM_MASK (VSC73XX_ADVPORTM_IFG_PPM | \ ++ VSC73XX_ADVPORTM_EXC_COL_CONT | \ ++ VSC73XX_ADVPORTM_EXT_PORT | \ ++ VSC73XX_ADVPORTM_INV_GTX | \ ++ VSC73XX_ADVPORTM_ENA_GTX | \ ++ VSC73XX_ADVPORTM_DDR_MODE | \ ++ VSC73XX_ADVPORTM_IO_LOOPBACK | \ ++ VSC73XX_ADVPORTM_HOST_LOOPBACK) ++ ++#define VSC7385_ADVPORTM_INIT (VSC73XX_ADVPORTM_EXT_PORT | \ ++ VSC73XX_ADVPORTM_ENA_GTX | \ ++ VSC73XX_ADVPORTM_DDR_MODE) ++ ++#define VSC7385_MAC_CFG_RESET (VSC73XX_MAC_CFG_PORT_RST | \ ++ VSC73XX_MAC_CFG_MAC_RX_RST | \ ++ VSC73XX_MAC_CFG_MAC_TX_RST) ++ ++#define VSC73XX_MAC_CFG_INIT (VSC73XX_MAC_CFG_TX_EN | \ ++ VSC73XX_MAC_CFG_FDX | \ ++ VSC73XX_MAC_CFG_GIGE | \ ++ VSC73XX_MAC_CFG_RX_EN) ++ ++#define VSC73XX_RESET_DELAY 100 ++ ++struct vsc7385 { ++ struct spi_device *spi; ++ struct mutex lock; ++ struct vsc7385_platform_data *pdata; ++}; ++ ++static int vsc7385_is_addr_valid(u8 block, u8 subblock) ++{ ++ switch (block) { ++ case VSC73XX_BLOCK_MAC: ++ switch (subblock) { ++ case 0 ... 4: ++ case 6: ++ return 1; ++ } ++ break; ++ ++ case VSC73XX_BLOCK_2: ++ case VSC73XX_BLOCK_SYSTEM: ++ switch (subblock) { ++ case 0: ++ return 1; ++ } ++ break; ++ ++ case VSC73XX_BLOCK_MII: ++ case VSC73XX_BLOCK_4: ++ case VSC73XX_BLOCK_5: ++ switch (subblock) { ++ case 0 ... 1: ++ return 1; ++ } ++ break; ++ } ++ ++ return 0; ++} ++ ++static inline u8 vsc7385_make_addr(u8 mode, u8 block, u8 subblock) ++{ ++ u8 ret; ++ ++ ret = (block & VSC73XX_CMD_BLOCK_MASK) << VSC73XX_CMD_BLOCK_SHIFT; ++ ret |= (mode & 1) << VSC73XX_CMD_MODE_SHIFT; ++ ret |= subblock & VSC73XX_CMD_SUBBLOCK_MASK; ++ ++ return ret; ++} ++ ++static int vsc7385_read(struct vsc7385 *vsc, u8 block, u8 subblock, u8 reg, ++ u32 *value) ++{ ++ u8 cmd[4]; ++ u8 buf[4]; ++ struct spi_transfer t[2]; ++ struct spi_message m; ++ int err; ++ ++ if (!vsc7385_is_addr_valid(block, subblock)) ++ return -EINVAL; ++ ++ spi_message_init(&m); ++ ++ memset(&t, 0, sizeof(t)); ++ ++ t[0].tx_buf = cmd; ++ t[0].len = sizeof(cmd); ++ spi_message_add_tail(&t[0], &m); ++ ++ t[1].rx_buf = buf; ++ t[1].len = sizeof(buf); ++ spi_message_add_tail(&t[1], &m); ++ ++ cmd[0] = vsc7385_make_addr(VSC73XX_CMD_MODE_READ, block, subblock); ++ cmd[1] = reg; ++ cmd[2] = 0; ++ cmd[3] = 0; ++ ++ mutex_lock(&vsc->lock); ++ err = spi_sync(vsc->spi, &m); ++ mutex_unlock(&vsc->lock); ++ ++ if (err) ++ return err; ++ ++ *value = (((u32) buf[0]) << 24) | (((u32) buf[1]) << 16) | ++ (((u32) buf[2]) << 8) | ((u32) buf[3]); ++ ++ return 0; ++} ++ ++ ++static int vsc7385_write(struct vsc7385 *vsc, u8 block, u8 subblock, u8 reg, ++ u32 value) ++{ ++ u8 cmd[2]; ++ u8 buf[4]; ++ struct spi_transfer t[2]; ++ struct spi_message m; ++ int err; ++ ++ if (!vsc7385_is_addr_valid(block, subblock)) ++ return -EINVAL; ++ ++ spi_message_init(&m); ++ ++ memset(&t, 0, sizeof(t)); ++ ++ t[0].tx_buf = cmd; ++ t[0].len = sizeof(cmd); ++ spi_message_add_tail(&t[0], &m); ++ ++ t[1].tx_buf = buf; ++ t[1].len = sizeof(buf); ++ spi_message_add_tail(&t[1], &m); ++ ++ cmd[0] = vsc7385_make_addr(VSC73XX_CMD_MODE_WRITE, block, subblock); ++ cmd[1] = reg; ++ ++ buf[0] = (value >> 24) & 0xff; ++ buf[1] = (value >> 16) & 0xff; ++ buf[2] = (value >> 8) & 0xff; ++ buf[3] = value & 0xff; ++ ++ mutex_lock(&vsc->lock); ++ err = spi_sync(vsc->spi, &m); ++ mutex_unlock(&vsc->lock); ++ ++ return err; ++} ++ ++static inline int vsc7385_write_verify(struct vsc7385 *vsc, u8 block, ++ u8 subblock, u8 reg, u32 value, ++ u32 read_mask, u32 read_val) ++{ ++ struct spi_device *spi = vsc->spi; ++ u32 t; ++ int err; ++ ++ err = vsc7385_write(vsc, block, subblock, reg, value); ++ if (err) ++ return err; ++ ++ err = vsc7385_read(vsc, block, subblock, reg, &t); ++ if (err) ++ return err; ++ ++ if ((t & read_mask) != read_val) { ++ dev_err(&spi->dev, "register write error\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static inline int vsc7385_set_clock_delay(struct vsc7385 *vsc, u32 val) ++{ ++ return vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_CLOCK_DELAY, val); ++} ++ ++static inline int vsc7385_get_clock_delay(struct vsc7385 *vsc, u32 *val) ++{ ++ return vsc7385_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_CLOCK_DELAY, val); ++} ++ ++static inline int vsc7385_icpu_stop(struct vsc7385 *vsc) ++{ ++ return vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_ICPU_CTRL, ++ VSC73XX_ICPU_CTRL_STOP); ++} ++ ++static inline int vsc7385_icpu_start(struct vsc7385 *vsc) ++{ ++ return vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_ICPU_CTRL, ++ VSC73XX_ICPU_CTRL_START); ++} ++ ++static inline int vsc7385_icpu_reset(struct vsc7385 *vsc) ++{ ++ int rc; ++ ++ rc = vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_ICPU_ADDR, ++ 0x0000); ++ if (rc) ++ dev_err(&vsc->spi->dev, ++ "could not reset microcode, err=%d\n", rc); ++ ++ return rc; ++} ++ ++static int vsc7385_upload_ucode(struct vsc7385 *vsc) ++{ ++ struct spi_device *spi = vsc->spi; ++ const struct firmware *firmware; ++ char *ucode_name; ++ unsigned char *dp; ++ unsigned int curVal; ++ int i; ++ int diffs; ++ int rc; ++ ++ ucode_name = (vsc->pdata->ucode_name) ? vsc->pdata->ucode_name ++ : "vsc7385_ucode.bin"; ++ rc = request_firmware(&firmware, ucode_name, &spi->dev); ++ if (rc) { ++ dev_err(&spi->dev, "request_firmware failed, err=%d\n", ++ rc); ++ return rc; ++ } ++ ++ rc = vsc7385_icpu_stop(vsc); ++ if (rc) ++ goto out; ++ ++ rc = vsc7385_icpu_reset(vsc); ++ if (rc) ++ goto out; ++ ++ dev_info(&spi->dev, "uploading microcode...\n"); ++ ++ dp = (unsigned char *) firmware->data; ++ for (i = 0; i < firmware->size; i++) { ++ rc = vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_SRAM, *dp++); ++ if (rc) { ++ dev_err(&spi->dev, "could not load microcode, err=%d\n", ++ rc); ++ goto out; ++ } ++ } ++ ++ rc = vsc7385_icpu_reset(vsc); ++ if (rc) ++ goto out; ++ ++ dev_info(&spi->dev, "verifying microcode...\n"); ++ ++ dp = (unsigned char *) firmware->data; ++ diffs = 0; ++ for (i = 0; i < firmware->size; i++) { ++ rc = vsc7385_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_SRAM, &curVal); ++ if (rc) { ++ dev_err(&spi->dev, "could not read microcode %d\n", ++ rc); ++ goto out; ++ } ++ ++ if (curVal > 0xff) { ++ dev_err(&spi->dev, "bad val read: %04x : %02x %02x\n", ++ i, *dp, curVal); ++ rc = -EIO; ++ goto out; ++ } ++ ++ if ((curVal & 0xff) != *dp) { ++ diffs++; ++ dev_err(&spi->dev, "verify error: %04x : %02x %02x\n", ++ i, *dp, curVal); ++ ++ if (diffs > 4) ++ break; ++ } ++ dp++; ++ } ++ ++ if (diffs) { ++ dev_err(&spi->dev, "microcode verification failed\n"); ++ rc = -EIO; ++ goto out; ++ } ++ ++ dev_info(&spi->dev, "microcode uploaded\n"); ++ ++ rc = vsc7385_icpu_start(vsc); ++ ++out: ++ release_firmware(firmware); ++ return rc; ++} ++ ++static int vsc7385_setup(struct vsc7385 *vsc) ++{ ++ struct vsc7385_platform_data *pdata = vsc->pdata; ++ u32 t; ++ int err; ++ ++ err = vsc7385_write_verify(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_CLOCK_DELAY, ++ VSC7385_CLOCK_DELAY, ++ VSC7385_CLOCK_DELAY_MASK, ++ VSC7385_CLOCK_DELAY); ++ if (err) ++ goto err; ++ ++ err = vsc7385_write_verify(vsc, VSC73XX_BLOCK_MAC, ++ VSC73XX_SUBBLOCK_PORT_MAC, VSC73XX_ADVPORTM, ++ VSC7385_ADVPORTM_INIT, ++ VSC7385_ADVPORTM_MASK, ++ VSC7385_ADVPORTM_INIT); ++ if (err) ++ goto err; ++ ++ err = vsc7385_write(vsc, VSC73XX_BLOCK_MAC, VSC73XX_SUBBLOCK_PORT_MAC, ++ VSC73XX_MAC_CFG, VSC7385_MAC_CFG_RESET); ++ if (err) ++ goto err; ++ ++ t = VSC73XX_MAC_CFG_INIT; ++ t |= VSC73XX_MAC_CFG_TX_IPG(pdata->mac_cfg.tx_ipg); ++ t |= VSC73XX_MAC_CFG_CLK_SEL(pdata->mac_cfg.clk_sel); ++ if (pdata->mac_cfg.bit2) ++ t |= VSC73XX_MAC_CFG_BIT2; ++ ++ err = vsc7385_write(vsc, VSC73XX_BLOCK_MAC, VSC73XX_SUBBLOCK_PORT_MAC, ++ VSC73XX_MAC_CFG, t); ++ if (err) ++ goto err; ++ ++ return 0; ++ ++err: ++ return err; ++} ++ ++static int vsc7385_detect(struct vsc7385 *vsc) ++{ ++ struct spi_device *spi = vsc->spi; ++ u32 t; ++ u32 id; ++ u32 rev; ++ int err; ++ ++ err = vsc7385_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_MBOX_VAL, &t); ++ if (err) { ++ dev_err(&spi->dev, "unable to read mailbox, err=%d\n", err); ++ return err; ++ } ++ ++ if (t == 0xffffffff) { ++ dev_dbg(&spi->dev, "assert chip reset\n"); ++ if (vsc->pdata->reset) ++ vsc->pdata->reset(); ++ ++ } ++ ++ err = vsc7385_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_CHIPID, &t); ++ if (err) { ++ dev_err(&spi->dev, "unable to read chip id, err=%d\n", err); ++ return err; ++ } ++ ++ id = (t >> VSC73XX_ICPU_CHIPID_ID_SHIFT) & VSC73XX_ICPU_CHIPID_ID_MASK; ++ switch (id) { ++ case VSC73XX_ICPU_CHIPID_ID_7385: ++ case VSC73XX_ICPU_CHIPID_ID_7395: ++ break; ++ default: ++ dev_err(&spi->dev, "unsupported chip, id=%04x\n", id); ++ return -ENODEV; ++ } ++ ++ rev = (t >> VSC73XX_ICPU_CHIPID_REV_SHIFT) & ++ VSC73XX_ICPU_CHIPID_REV_MASK; ++ dev_info(&spi->dev, "VSC%04X (rev. %d) switch found\n", id, rev); ++ ++ return 0; ++} ++ ++static int vsc7385_probe(struct spi_device *spi) ++{ ++ struct vsc7385 *vsc; ++ struct vsc7385_platform_data *pdata; ++ int err; ++ ++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION"\n"); ++ ++ pdata = spi->dev.platform_data; ++ if (!pdata) { ++ dev_err(&spi->dev, "no platform data specified\n"); ++ return -ENODEV; ++ } ++ ++ vsc = kzalloc(sizeof(*vsc), GFP_KERNEL); ++ if (!vsc) { ++ dev_err(&spi->dev, "no memory for private data\n"); ++ return -ENOMEM; ++ } ++ ++ mutex_init(&vsc->lock); ++ vsc->pdata = pdata; ++ vsc->spi = spi_dev_get(spi); ++ dev_set_drvdata(&spi->dev, vsc); ++ ++ spi->mode = SPI_MODE_0; ++ spi->bits_per_word = 8; ++ err = spi_setup(spi); ++ if (err) { ++ dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); ++ goto err_drvdata; ++ } ++ ++ err = vsc7385_detect(vsc); ++ if (err) { ++ dev_err(&spi->dev, "no chip found, err=%d\n", err); ++ goto err_drvdata; ++ } ++ ++ err = vsc7385_upload_ucode(vsc); ++ if (err) ++ goto err_drvdata; ++ ++ err = vsc7385_setup(vsc); ++ if (err) ++ goto err_drvdata; ++ ++ return 0; ++ ++err_drvdata: ++ dev_set_drvdata(&spi->dev, NULL); ++ kfree(vsc); ++ return err; ++} ++ ++static int vsc7385_remove(struct spi_device *spi) ++{ ++ struct vsc7385_data *vsc; ++ ++ vsc = dev_get_drvdata(&spi->dev); ++ dev_set_drvdata(&spi->dev, NULL); ++ kfree(vsc); ++ ++ return 0; ++} ++ ++static struct spi_driver vsc7385_driver = { ++ .driver = { ++ .name = DRV_NAME, ++ .bus = &spi_bus_type, ++ .owner = THIS_MODULE, ++ }, ++ .probe = vsc7385_probe, ++ .remove = vsc7385_remove, ++}; ++ ++static int __init vsc7385_init(void) ++{ ++ return spi_register_driver(&vsc7385_driver); ++} ++module_init(vsc7385_init); ++ ++static void __exit vsc7385_exit(void) ++{ ++ spi_unregister_driver(&vsc7385_driver); ++} ++module_exit(vsc7385_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); ++ +diff --git a/target/linux/ar71xx/files/include/linux/leds-nu801.h b/target/linux/ar71xx/files/include/linux/leds-nu801.h +new file mode 100644 +index 0000000000..0fc310d277 +--- /dev/null ++++ b/target/linux/ar71xx/files/include/linux/leds-nu801.h +@@ -0,0 +1,38 @@ ++#ifndef __LEDS_NU801_H__ ++#define __LEDS_NU801_H__ ++ ++/* ++ * Definitions for LED driver for NU801 ++ * ++ * Kevin Paul Herbert ++ * Copyright (c) 2012, Meraki, 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 ++ ++struct led_nu801_template { ++ const char *device_name; /* Name of the platform device */ ++ const char *name; /* Name of this LED chain */ ++ int num_leds; /* Number of LEDs in the chain */ ++ unsigned cki; /* GPIO pin for CKI */ ++ unsigned sdi; /* GPIO pin for SDI */ ++ int lei; /* GPIO pin for LEI; < 0 if none */ ++ u32 ndelay; /* Delay in nanoseconds */ ++ enum led_brightness init_brightness[3]; /* Default rgb state */ ++#ifdef CONFIG_LEDS_TRIGGERS ++ const char *default_trigger; /* default trigger */ ++#endif ++ const char *led_colors[3]; /* rgb color order */ ++}; ++ ++struct led_nu801_platform_data { ++ int num_controllers; /* Numnber of controllers */ ++ struct led_nu801_template *template; /* Template per controller */ ++}; ++ ++#endif /* __LEDS_NU801_H__ */ +diff --git a/target/linux/ar71xx/files/include/linux/nxp_74hc153.h b/target/linux/ar71xx/files/include/linux/nxp_74hc153.h +new file mode 100644 +index 0000000000..20b8845e53 +--- /dev/null ++++ b/target/linux/ar71xx/files/include/linux/nxp_74hc153.h +@@ -0,0 +1,24 @@ ++/* ++ * NXP 74HC153 - Dual 4-input multiplexer defines ++ * ++ * Copyright (C) 2010 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 _NXP_74HC153_H ++#define _NXP_74HC153_H ++ ++#define NXP_74HC153_DRIVER_NAME "nxp-74hc153" ++ ++struct nxp_74hc153_platform_data { ++ unsigned gpio_base; ++ unsigned gpio_pin_s0; ++ unsigned gpio_pin_s1; ++ unsigned gpio_pin_1y; ++ unsigned gpio_pin_2y; ++}; ++ ++#endif /* _NXP_74HC153_H */ +diff --git a/target/linux/ar71xx/files/include/linux/platform/ar934x_nfc.h b/target/linux/ar71xx/files/include/linux/platform/ar934x_nfc.h +new file mode 100644 +index 0000000000..371aaee7f8 +--- /dev/null ++++ b/target/linux/ar71xx/files/include/linux/platform/ar934x_nfc.h +@@ -0,0 +1,39 @@ ++/* ++ * Platform data definition for the built-in NAND controller of the ++ * Atheros AR934x SoCs ++ * ++ * Copyright (C) 2011-2012 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 _AR934X_NFC_PLATFORM_H ++#define _AR934X_NFC_PLATFORM_H ++ ++#define AR934X_NFC_DRIVER_NAME "ar934x-nfc" ++ ++struct mtd_info; ++struct mtd_partition; ++ ++enum ar934x_nfc_ecc_mode { ++ AR934X_NFC_ECC_SOFT = 0, ++ AR934X_NFC_ECC_HW, ++ AR934X_NFC_ECC_SOFT_BCH, ++}; ++ ++struct ar934x_nfc_platform_data { ++ const char *name; ++ struct mtd_partition *parts; ++ int nr_parts; ++ ++ bool swap_dma; ++ enum ar934x_nfc_ecc_mode ecc_mode; ++ ++ void (*hw_reset)(bool active); ++ void (*select_chip)(int chip_no); ++ int (*scan_fixup)(struct mtd_info *mtd); ++}; ++ ++#endif /* _AR934X_NFC_PLATFORM_H */ +diff --git a/target/linux/ar71xx/files/include/linux/platform_data/gpio-latch.h b/target/linux/ar71xx/files/include/linux/platform_data/gpio-latch.h +new file mode 100644 +index 0000000000..0450e679ec +--- /dev/null ++++ b/target/linux/ar71xx/files/include/linux/platform_data/gpio-latch.h +@@ -0,0 +1,14 @@ ++#ifndef _GPIO_LATCH_H_ ++#define _GPIO_LATCH_H_ ++ ++#define GPIO_LATCH_DRIVER_NAME "gpio-latch" ++ ++struct gpio_latch_platform_data { ++ int base; ++ int num_gpios; ++ int *gpios; ++ int le_gpio_index; ++ bool le_active_low; ++}; ++ ++#endif /* _GPIO_LATCH_H_ */ +diff --git a/target/linux/ar71xx/files/include/linux/platform_data/rb91x_nand.h b/target/linux/ar71xx/files/include/linux/platform_data/rb91x_nand.h +new file mode 100644 +index 0000000000..5f17fb8148 +--- /dev/null ++++ b/target/linux/ar71xx/files/include/linux/platform_data/rb91x_nand.h +@@ -0,0 +1,16 @@ ++#ifndef _RB91X_NAND_H_ ++#define _RB91X_NAND_H_ ++ ++#define RB91X_NAND_DRIVER_NAME "rb91x-nand" ++ ++struct rb91x_nand_platform_data { ++ int gpio_nce; /* chip enable, active low */ ++ int gpio_ale; /* address latch enable */ ++ int gpio_cle; /* command latch enable */ ++ int gpio_rdy; ++ int gpio_read; ++ int gpio_nrw; /* read/write enable, active low */ ++ int gpio_nle; /* latch enable, active low */ ++}; ++ ++#endif /* _RB91X_NAND_H_ */ +\ No newline at end of file +diff --git a/target/linux/ar71xx/files/include/linux/spi/vsc7385.h b/target/linux/ar71xx/files/include/linux/spi/vsc7385.h +new file mode 100644 +index 0000000000..1072ad7941 +--- /dev/null ++++ b/target/linux/ar71xx/files/include/linux/spi/vsc7385.h +@@ -0,0 +1,19 @@ ++/* ++ * Platform data definition for the Vitesse VSC7385 ethernet switch driver ++ * ++ * Copyright (C) 2009 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. ++ */ ++ ++struct vsc7385_platform_data { ++ void (*reset)(void); ++ char *ucode_name; ++ struct { ++ u32 tx_ipg:5; ++ u32 bit2:1; ++ u32 clk_sel:3; ++ } mac_cfg; ++}; +diff --git a/target/linux/ar71xx/generic/config-default b/target/linux/ar71xx/generic/config-default +new file mode 100644 +index 0000000000..25b58ae91e +--- /dev/null ++++ b/target/linux/ar71xx/generic/config-default +@@ -0,0 +1,227 @@ ++CONFIG_ATH79_DEV_AP9X_PCI=y ++CONFIG_ATH79_DEV_ETH=y ++CONFIG_ATH79_DEV_GPIO_BUTTONS=y ++CONFIG_ATH79_DEV_LEDS_GPIO=y ++CONFIG_ATH79_DEV_M25P80=y ++CONFIG_ATH79_DEV_NFC=y ++CONFIG_ATH79_DEV_SPI=y ++CONFIG_ATH79_DEV_USB=y ++CONFIG_ATH79_DEV_WMAC=y ++CONFIG_ATH79_MACH_A60=y ++CONFIG_ATH79_MACH_ALFA_AP120C=y ++CONFIG_ATH79_MACH_ALFA_AP96=y ++CONFIG_ATH79_MACH_ALFA_NX=y ++CONFIG_ATH79_MACH_ALL0258N=y ++CONFIG_ATH79_MACH_ALL0315N=y ++CONFIG_ATH79_MACH_ANTMINER_S1=y ++CONFIG_ATH79_MACH_ANTMINER_S3=y ++CONFIG_ATH79_MACH_ANTROUTER_R1=y ++CONFIG_ATH79_MACH_AP121=y ++CONFIG_ATH79_MACH_AP121F=y ++CONFIG_ATH79_MACH_AP132=y ++CONFIG_ATH79_MACH_AP136=y ++CONFIG_ATH79_MACH_AP143=y ++CONFIG_ATH79_MACH_AP147=y ++CONFIG_ATH79_MACH_AP152=y ++CONFIG_ATH79_MACH_AP531B0=y ++CONFIG_ATH79_MACH_AP90Q=y ++CONFIG_ATH79_MACH_AP91_5G=y ++CONFIG_ATH79_MACH_AP96=y ++CONFIG_ATH79_MACH_ARCHER_C25_V1=y ++CONFIG_ATH79_MACH_ARCHER_C58_V1=y ++CONFIG_ATH79_MACH_ARCHER_C59_V1=y ++CONFIG_ATH79_MACH_ARCHER_C60_V1=y ++CONFIG_ATH79_MACH_ARCHER_C60_V2=y ++CONFIG_ATH79_MACH_ARCHER_C7=y ++CONFIG_ATH79_MACH_ARDUINO_YUN=y ++CONFIG_ATH79_MACH_AW_NR580=y ++CONFIG_ATH79_MACH_BHU_BXU2000N2_A=y ++CONFIG_ATH79_MACH_BSB=y ++CONFIG_ATH79_MACH_C55=y ++CONFIG_ATH79_MACH_CAP324=y ++CONFIG_ATH79_MACH_CAP4200AG=y ++CONFIG_ATH79_MACH_CARAMBOLA2=y ++CONFIG_ATH79_MACH_CF_E316N_V2=y ++CONFIG_ATH79_MACH_CF_E320N_V2=y ++CONFIG_ATH79_MACH_CF_E355AC=y ++CONFIG_ATH79_MACH_CF_E375AC=y ++CONFIG_ATH79_MACH_CF_E380AC_V1=y ++CONFIG_ATH79_MACH_CF_E380AC_V2=y ++CONFIG_ATH79_MACH_CF_E520N=y ++CONFIG_ATH79_MACH_CF_E530N=y ++CONFIG_ATH79_MACH_CPE505N=y ++CONFIG_ATH79_MACH_CPE510=y ++CONFIG_ATH79_MACH_CPE830=y ++CONFIG_ATH79_MACH_CPE870=y ++CONFIG_ATH79_MACH_CR3000=y ++CONFIG_ATH79_MACH_CR5000=y ++CONFIG_ATH79_MACH_DAP_1330_A1=y ++CONFIG_ATH79_MACH_DAP_2695_A1=y ++CONFIG_ATH79_MACH_DB120=y ++CONFIG_ATH79_MACH_DGL_5500_A1=y ++CONFIG_ATH79_MACH_DHP_1565_A1=y ++CONFIG_ATH79_MACH_DIR_505_A1=y ++CONFIG_ATH79_MACH_DIR_825_B1=y ++CONFIG_ATH79_MACH_DIR_825_C1=y ++CONFIG_ATH79_MACH_DIR_869_A1=y ++CONFIG_ATH79_MACH_DLAN_HOTSPOT=y ++CONFIG_ATH79_MACH_DLAN_PRO_1200_AC=y ++CONFIG_ATH79_MACH_DLAN_PRO_500_WP=y ++CONFIG_ATH79_MACH_DR342=y ++CONFIG_ATH79_MACH_DR344=y ++CONFIG_ATH79_MACH_DR531=y ++CONFIG_ATH79_MACH_DRAGINO2=y ++CONFIG_ATH79_MACH_E1700AC_V2=y ++CONFIG_ATH79_MACH_E2100L=y ++CONFIG_ATH79_MACH_E558_V2=y ++CONFIG_ATH79_MACH_E600G_V2=y ++CONFIG_ATH79_MACH_E750A_V4=y ++CONFIG_ATH79_MACH_E750G_V8=y ++CONFIG_ATH79_MACH_EAP120=y ++CONFIG_ATH79_MACH_EAP300V2=y ++CONFIG_ATH79_MACH_EAP7660D=y ++CONFIG_ATH79_MACH_EL_M150=y ++CONFIG_ATH79_MACH_EL_MINI=y ++CONFIG_ATH79_MACH_EPG5000=y ++CONFIG_ATH79_MACH_ESR1750=y ++CONFIG_ATH79_MACH_ESR900=y ++CONFIG_ATH79_MACH_EW_BALIN=y ++CONFIG_ATH79_MACH_EW_DORIN=y ++CONFIG_ATH79_MACH_FRITZ300E=y ++CONFIG_ATH79_MACH_FRITZ4020=y ++CONFIG_ATH79_MACH_FRITZ450E=y ++CONFIG_ATH79_MACH_GL_AR150=y ++CONFIG_ATH79_MACH_GL_AR300=y ++CONFIG_ATH79_MACH_GL_AR300M=y ++CONFIG_ATH79_MACH_GL_AR750=y ++CONFIG_ATH79_MACH_GL_AR750S=y ++CONFIG_ATH79_MACH_GL_DOMINO=y ++CONFIG_ATH79_MACH_GL_INET=y ++CONFIG_ATH79_MACH_GL_MIFI=y ++CONFIG_ATH79_MACH_GL_USB150=y ++CONFIG_ATH79_MACH_GS_MINIBOX_V32=y ++CONFIG_ATH79_MACH_GS_OOLITE_V1=y ++CONFIG_ATH79_MACH_GS_OOLITE_V5_2=y ++CONFIG_ATH79_MACH_HIWIFI_HC6361=y ++CONFIG_ATH79_MACH_HORNET_UB=y ++CONFIG_ATH79_MACH_JA76PF=y ++CONFIG_ATH79_MACH_JWAP003=y ++CONFIG_ATH79_MACH_JWAP230=y ++CONFIG_ATH79_MACH_KOALA=y ++CONFIG_ATH79_MACH_LAN_TURTLE=y ++CONFIG_ATH79_MACH_LIMA=y ++CONFIG_ATH79_MACH_MC_MAC1200R=y ++CONFIG_ATH79_MACH_MR12=y ++CONFIG_ATH79_MACH_MR16=y ++CONFIG_ATH79_MACH_MR1750=y ++CONFIG_ATH79_MACH_MR600=y ++CONFIG_ATH79_MACH_MR900=y ++CONFIG_ATH79_MACH_MYNET_N600=y ++CONFIG_ATH79_MACH_MYNET_N750=y ++CONFIG_ATH79_MACH_MYNET_REXT=y ++CONFIG_ATH79_MACH_MZK_W04NU=y ++CONFIG_ATH79_MACH_MZK_W300NH=y ++CONFIG_ATH79_MACH_N5Q=y ++CONFIG_ATH79_MACH_NBG6716=y ++CONFIG_ATH79_MACH_OM2P=y ++CONFIG_ATH79_MACH_OM5P=y ++CONFIG_ATH79_MACH_OM5P_AC=y ++CONFIG_ATH79_MACH_OM5P_ACv2=y ++CONFIG_ATH79_MACH_OMY_G1=y ++CONFIG_ATH79_MACH_OMY_X1=y ++CONFIG_ATH79_MACH_ONION_OMEGA=y ++CONFIG_ATH79_MACH_PB42=y ++CONFIG_ATH79_MACH_PB44=y ++CONFIG_ATH79_MACH_PQI_AIR_PEN=y ++CONFIG_ATH79_MACH_QIHOO_C301=y ++CONFIG_ATH79_MACH_R36A=y ++CONFIG_ATH79_MACH_R602N=y ++CONFIG_ATH79_MACH_RE355=y ++CONFIG_ATH79_MACH_RE450=y ++CONFIG_ATH79_MACH_RME_EG200=y ++CONFIG_ATH79_MACH_RUT9XX=y ++CONFIG_ATH79_MACH_RW2458N=y ++CONFIG_ATH79_MACH_SC1750=y ++CONFIG_ATH79_MACH_SC300M=y ++CONFIG_ATH79_MACH_SC450=y ++CONFIG_ATH79_MACH_SMART_300=y ++CONFIG_ATH79_MACH_SOM9331=y ++CONFIG_ATH79_MACH_SR3200=y ++CONFIG_ATH79_MACH_T830=y ++CONFIG_ATH79_MACH_TELLSTICK_ZNET_LITE=y ++CONFIG_ATH79_MACH_TEW_673GRU=y ++CONFIG_ATH79_MACH_TEW_732BR=y ++CONFIG_ATH79_MACH_TEW_823DRU=y ++CONFIG_ATH79_MACH_TL_MR3X20=y ++CONFIG_ATH79_MACH_TL_MR6400=y ++CONFIG_ATH79_MACH_TL_WDR3500=y ++CONFIG_ATH79_MACH_TL_WDR4300=y ++CONFIG_ATH79_MACH_TL_WDR6500_V2=y ++CONFIG_ATH79_MACH_TL_WPA8630=y ++CONFIG_ATH79_MACH_TL_WR1043ND=y ++CONFIG_ATH79_MACH_TL_WR1043ND_V2=y ++CONFIG_ATH79_MACH_TL_WR1043ND_V4=y ++CONFIG_ATH79_MACH_TL_WR1043N_V5=y ++CONFIG_ATH79_MACH_TL_WR2543N=y ++CONFIG_ATH79_MACH_TL_WR703N=y ++CONFIG_ATH79_MACH_TL_WR720N_V3=y ++CONFIG_ATH79_MACH_TL_WR810N=y ++CONFIG_ATH79_MACH_TL_WR810N_V2=y ++CONFIG_ATH79_MACH_TL_WR841N_V8=y ++CONFIG_ATH79_MACH_TL_WR841N_V9=y ++CONFIG_ATH79_MACH_TL_WR902AC_V1=y ++CONFIG_ATH79_MACH_TL_WR942N_V1=y ++CONFIG_ATH79_MACH_TS_D084=y ++CONFIG_ATH79_MACH_TUBE2H=y ++CONFIG_ATH79_MACH_UBNT=y ++CONFIG_ATH79_MACH_UBNT_UNIFIAC=y ++CONFIG_ATH79_MACH_UBNT_XM=y ++CONFIG_ATH79_MACH_WAM250=y ++CONFIG_ATH79_MACH_WEIO=y ++CONFIG_ATH79_MACH_WHR_HP_G300N=y ++CONFIG_ATH79_MACH_WIFI_PINEAPPLE_NANO=y ++CONFIG_ATH79_MACH_WLAE_AG300N=y ++CONFIG_ATH79_MACH_WLR8100=y ++CONFIG_ATH79_MACH_WNDAP360=y ++CONFIG_ATH79_MACH_WNDR3700=y ++CONFIG_ATH79_MACH_WNR2200=y ++CONFIG_ATH79_MACH_WP543=y ++CONFIG_ATH79_MACH_WPE72=y ++CONFIG_ATH79_MACH_WPJ342=y ++CONFIG_ATH79_MACH_WPJ344=y ++CONFIG_ATH79_MACH_WPJ531=y ++CONFIG_ATH79_MACH_WPJ558=y ++CONFIG_ATH79_MACH_WPJ563=y ++CONFIG_ATH79_MACH_WRT160NL=y ++CONFIG_ATH79_MACH_WRT400N=y ++CONFIG_ATH79_MACH_WRTNODE2Q=y ++CONFIG_ATH79_MACH_WZR_450HP2=y ++CONFIG_ATH79_MACH_WZR_HP_AG300H=y ++CONFIG_ATH79_MACH_WZR_HP_G300NH=y ++CONFIG_ATH79_MACH_WZR_HP_G300NH2=y ++CONFIG_ATH79_MACH_WZR_HP_G450H=y ++CONFIG_ATH79_MACH_XD3200=y ++CONFIG_ATH79_MACH_ZCN_1523H=y ++CONFIG_ATH79_NVRAM=y ++CONFIG_ATH79_PCI_ATH9K_FIXUP=y ++CONFIG_BLK_MQ_PCI=y ++CONFIG_GPIO_PCA953X=y ++# CONFIG_GPIO_PCA953X_IRQ is not set ++CONFIG_HW_HAS_PCI=y ++# CONFIG_LEDS_WNDR3700_USB is not set ++CONFIG_MYLOADER=y ++CONFIG_PCI=y ++CONFIG_PCI_AR724X=y ++CONFIG_PCI_DISABLE_COMMON_QUIRKS=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_SERIAL_AR933X=y ++CONFIG_SERIAL_AR933X_CONSOLE=y ++CONFIG_SERIAL_AR933X_NR_UARTS=2 ++CONFIG_SOC_AR71XX=y ++CONFIG_SOC_AR724X=y ++CONFIG_SOC_AR913X=y ++CONFIG_SOC_AR933X=y ++CONFIG_SOC_AR934X=y ++CONFIG_SOC_QCA953X=y ++CONFIG_SOC_QCA955X=y ++CONFIG_SOC_QCA956X=y +diff --git a/target/linux/ar71xx/generic/profiles/00-default.mk b/target/linux/ar71xx/generic/profiles/00-default.mk +new file mode 100644 +index 0000000000..18fd385cc3 +--- /dev/null ++++ b/target/linux/ar71xx/generic/profiles/00-default.mk +@@ -0,0 +1,18 @@ ++# ++# Copyright (C) 2009 OpenWrt.org ++# ++# This is free software, licensed under the GNU General Public License v2. ++# See /LICENSE for more information. ++# ++ ++define Profile/Default ++ NAME:=Default Profile (all drivers) ++ PACKAGES:= \ ++ kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport ++ PRIORITY := 1 ++endef ++ ++define Profile/Default/Description ++ Default package set compatible with most boards. ++endef ++$(eval $(call Profile,Default)) +diff --git a/target/linux/ar71xx/generic/target.mk b/target/linux/ar71xx/generic/target.mk +new file mode 100644 +index 0000000000..0a26110d27 +--- /dev/null ++++ b/target/linux/ar71xx/generic/target.mk +@@ -0,0 +1,10 @@ ++BOARDNAME:=Generic ++FEATURES += squashfs ++ ++DEFAULT_PACKAGES += wpad-basic ++ ++define Target/Description ++ Build firmware images for generic Atheros AR71xx/AR913x/AR934x based boards. ++endef ++ ++ +diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile +new file mode 100644 +index 0000000000..dea8338ddd +--- /dev/null ++++ b/target/linux/ar71xx/image/Makefile +@@ -0,0 +1,69 @@ ++# ++# Copyright (C) 2008-2011 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)/image.mk ++ ++KERNEL_LOADADDR = 0x80060000 ++ ++DEVICE_VARS += BOARDNAME CMDLINE CONSOLE LOADER_TYPE ++ ++ifeq ($(SUBTARGET),generic) ++include ./generic.mk ++include ./generic-legacy-devices.mk ++include ./generic-tp-link.mk ++include ./generic-ubnt.mk ++endif ++ifeq ($(SUBTARGET),tiny) ++include ./tiny.mk ++include ./tiny-tp-link.mk ++include ./tiny-legacy-devices.mk ++include ./tiny-senao.mk ++endif ++ifeq ($(SUBTARGET),nand) ++include ./nand.mk ++endif ++ifeq ($(SUBTARGET),mikrotik) ++include ./mikrotik.mk ++endif ++include ./legacy.mk ++ ++define Build/loader-common ++ rm -rf $@.src ++ $(MAKE) -C lzma-loader \ ++ PKG_BUILD_DIR="$@.src" \ ++ TARGET_DIR="$(dir $@)" LOADER_NAME="$(notdir $@)" \ ++ BOARD="$(BOARDNAME)" \ ++ LZMA_TEXT_START=0x80a00000 LOADADDR=0x80060000 \ ++ $(1) compile loader.$(LOADER_TYPE) ++ mv "$@.$(LOADER_TYPE)" "$@" ++ rm -rf $@.src ++endef ++ ++define Build/loader-kernel ++ $(call Build/loader-common,LOADER_DATA="$@") ++endef ++ ++define Build/loader-kernel-cmdline ++ $(call Build/loader-common,LOADER_DATA="$@" KERNEL_CMDLINE="$(CMDLINE)") ++endef ++ ++define Device/Default ++ BOARDNAME := ++ DEVICE_PROFILE = $$(BOARDNAME) ++ PROFILES = Default Minimal $$(DEVICE_PROFILE) ++ MTDPARTS := ++ BLOCKSIZE := 64k ++ CONSOLE := ttyS0,115200 ++ CMDLINE = $$(if $$(BOARDNAME),board=$$(BOARDNAME)) $$(if $$(MTDPARTS),mtdparts=$$(MTDPARTS)) $$(if $$(CONSOLE),console=$$(CONSOLE)) ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImage lzma ++ COMPILE := ++ IMAGES := sysupgrade.bin ++ IMAGE/sysupgrade.bin = append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) ++endef ++ ++$(eval $(call BuildImage)) +diff --git a/target/linux/ar71xx/image/common-tp-link.mk b/target/linux/ar71xx/image/common-tp-link.mk +new file mode 100644 +index 0000000000..99acd7e584 +--- /dev/null ++++ b/target/linux/ar71xx/image/common-tp-link.mk +@@ -0,0 +1,108 @@ ++DEVICE_VARS += LOADER_FLASH_OFFS TPLINK_BOARD_ID TPLINK_FLASHLAYOUT TPLINK_HEADER_VERSION TPLINK_HWID TPLINK_HWREV ++ ++# Arguments: ++define Build/loader-okli ++ dd if=$(KDIR)/loader-$(word 1,$(1)).$(LOADER_TYPE) bs=$(word 2,$(1)) conv=sync of="$@.new" ++ cat "$@" >> "$@.new" ++ mv "$@.new" "$@" ++endef ++ ++define Build/loader-okli-compile ++ $(call Build/loader-common,FLASH_OFFS=$(LOADER_FLASH_OFFS) FLASH_MAX=0 KERNEL_CMDLINE="$(CMDLINE)") ++endef ++ ++# combine kernel and rootfs into one image ++# mktplinkfw ++# is "sysupgrade" or "factory" ++# ++# -a align the rootfs start on an bytes boundary ++# -j add jffs2 end-of-filesystem markers ++# -s strip padding from end of the image ++# -X reserve bytes in the firmware image (hexval prefixed with 0x) ++define Build/mktplinkfw ++ -$(STAGING_DIR_HOST)/bin/mktplinkfw \ ++ -H $(TPLINK_HWID) -W $(TPLINK_HWREV) -F $(TPLINK_FLASHLAYOUT) -N OpenWrt -V $(REVISION) \ ++ -m $(TPLINK_HEADER_VERSION) \ ++ -k $(IMAGE_KERNEL) \ ++ -r $@ \ ++ -o $@.new \ ++ -j -X 0x40000 \ ++ -a $(call rootfs_align,$(FILESYSTEM)) \ ++ $(wordlist 2,$(words $(1)),$(1)) \ ++ $(if $(findstring sysupgrade,$(word 1,$(1))),-s) && mv $@.new $@ || rm -f $@ ++endef ++ ++define Build/uImageArcher ++ mkimage -A $(LINUX_KARCH) \ ++ -O linux -T kernel \ ++ -C $(1) -a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ ++ -n '$(call toupper,$(LINUX_KARCH)) OpenWrt Linux-$(LINUX_VERSION)' -d $@ $@.new ++ @mv $@.new $@ ++endef ++ ++ ++define Device/tplink ++ TPLINK_HWREV := 0x1 ++ TPLINK_HEADER_VERSION := 1 ++ IMAGES := sysupgrade.bin factory.bin ++endef ++ ++define Device/tplink-lzma ++ $(Device/tplink) ++ KERNEL := kernel-bin | patch-cmdline | lzma ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++ IMAGE/sysupgrade.bin := append-rootfs | mktplinkfw sysupgrade ++ IMAGE/factory.bin := append-rootfs | mktplinkfw factory ++endef ++ ++define Device/tplink-nolzma ++ $(Device/tplink) ++ LOADER_TYPE := gz ++ LOADER_FLASH_OFFS := 0x22000 ++ COMPILE := loader-$(1).gz ++ COMPILE/loader-$(1).gz := loader-okli-compile ++ KERNEL_NAME := vmlinux.bin.lzma ++ KERNEL := kernel-bin | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 7680 ++ KERNEL_INITRAMFS_NAME := vmlinux-initramfs.bin.lzma ++ KERNEL_INITRAMFS := kernel-bin | loader-kernel-cmdline | tplink-v1-header ++ IMAGE/sysupgrade.bin := append-rootfs | mktplinkfw sysupgrade ++ IMAGE/factory.bin := append-rootfs | mktplinkfw factory ++endef ++ ++define Device/tplink-safeloader ++ $(Device/tplink) ++ KERNEL := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade | \ ++ append-metadata | check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++endef ++ ++define Device/tplink-4m ++ $(Device/tplink-nolzma) ++ TPLINK_FLASHLAYOUT := 4M ++ IMAGE_SIZE := 3904k ++endef ++ ++define Device/tplink-8m ++ $(Device/tplink-nolzma) ++ TPLINK_FLASHLAYOUT := 8M ++ IMAGE_SIZE := 7936k ++endef ++ ++define Device/tplink-4mlzma ++ $(Device/tplink-lzma) ++ TPLINK_FLASHLAYOUT := 4Mlzma ++ IMAGE_SIZE := 3904k ++endef ++ ++define Device/tplink-8mlzma ++ $(Device/tplink-lzma) ++ TPLINK_FLASHLAYOUT := 8Mlzma ++ IMAGE_SIZE := 7936k ++endef ++ ++define Device/tplink-16mlzma ++ $(Device/tplink-lzma) ++ TPLINK_FLASHLAYOUT := 16Mlzma ++ IMAGE_SIZE := 15872k ++endef +diff --git a/target/linux/ar71xx/image/generic-legacy-devices.mk b/target/linux/ar71xx/image/generic-legacy-devices.mk +new file mode 100644 +index 0000000000..cbe039cd29 +--- /dev/null ++++ b/target/linux/ar71xx/image/generic-legacy-devices.mk +@@ -0,0 +1,423 @@ ++define LegacyDevice/A60 ++ DEVICE_TITLE := OpenMesh A40/A60 ++ DEVICE_PACKAGES := om-watchdog kmod-ath10k-ct ath10k-firmware-qca988x-ct \ ++ mod-usb-core kmod-usb2 ++endef ++LEGACY_DEVICES += A60 ++ ++define LegacyDevice/ALFANX ++ DEVICE_TITLE := ALFA Network N2/N5 board ++endef ++LEGACY_DEVICES += ALFANX ++ ++define LegacyDevice/HORNETUB ++ DEVICE_TITLE := ALFA Network Hornet-UB board (8MB flash, 32MB ram) ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += HORNETUB ++ ++define LegacyDevice/TUBE2H8M ++ DEVICE_TITLE := ALFA Network Tube2H board (8MB flash) ++endef ++LEGACY_DEVICES += TUBE2H8M ++ ++define LegacyDevice/AP96 ++ DEVICE_TITLE := Atheros AP96 reference board ++ DEVICE_PACKAGES := kmod-usb2 ++endef ++LEGACY_DEVICES += AP96 ++ ++define LegacyDevice/WNDAP360 ++ DEVICE_TITLE := NETGEAR WNDAP360 ++endef ++LEGACY_DEVICES += WNDAP360 ++ ++define LegacyDevice/ALFAAP120C ++ DEVICE_TITLE := ALFA Network AP120C board ++endef ++LEGACY_DEVICES += ALFAAP120C ++ ++define LegacyDevice/ALFAAP96 ++ DEVICE_TITLE := ALFA Network AP96 board ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-rtc-pcf2123 ++endef ++LEGACY_DEVICES += ALFAAP96 ++ ++define LegacyDevice/ALL0258N ++ DEVICE_TITLE := Allnet ALL0258N ++ DEVICE_PACKAGES := rssileds ++endef ++LEGACY_DEVICES += ALL0258N ++ ++define LegacyDevice/ALL0315N ++ DEVICE_TITLE := Allnet ALL0315N ++ DEVICE_PACKAGES := rssileds ++endef ++LEGACY_DEVICES += ALL0315N ++ ++define LegacyDevice/AP121_8M ++ DEVICE_TITLE := Atheros AP121 reference board (8MB flash) ++ DEVICE_PACKAGES := kmod-usb2 ++endef ++LEGACY_DEVICES += AP121_8M ++ ++define LegacyDevice/AP121_16M ++ DEVICE_TITLE := Atheros AP121 reference board (16MB flash) ++ DEVICE_PACKAGES := kmod-usb2 ++endef ++LEGACY_DEVICES += AP121_16M ++ ++define LegacyDevice/AP132 ++ DEVICE_TITLE := Atheros AP132 reference board ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += AP132 ++ ++define LegacyDevice/AP135 ++ DEVICE_TITLE := Atheros AP135 reference board ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += AP135 ++ ++define LegacyDevice/AP136_010 ++ DEVICE_TITLE := Atheros AP136-010 reference board ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += AP136_010 ++ ++define LegacyDevice/AP136_020 ++ DEVICE_TITLE := Atheros AP136-020 reference board ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += AP136_020 ++ ++define LegacyDevice/AP143_8M ++ DEVICE_TITLE := Qualcomm Atheros AP143 reference board (8MB flash) ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += AP143_8M ++ ++define LegacyDevice/AP143_16M ++ DEVICE_TITLE := Qualcomm Atheros AP143 reference board (16MB flash) ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += AP143_16M ++ ++define LegacyDevice/AP147_010 ++ DEVICE_TITLE := Qualcomm Atheros AP147-010 reference board ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += AP147_010 ++ ++define LegacyDevice/AP152_16M ++ DEVICE_TITLE := Qualcomm Atheros AP152 reference board (16MB flash) ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += AP152_16M ++ ++define LegacyDevice/BXU2000N2 ++ DEVICE_TITLE := BHU BXU2000n-2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += BXU2000N2 ++ ++define LegacyDevice/CAP4200AG ++ DEVICE_TITLE := Senao CAP4200AG ++endef ++LEGACY_DEVICES += CAP4200AG ++ ++define LegacyDevice/DB120 ++ DEVICE_TITLE := Atheros DB120 reference board ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++endef ++LEGACY_DEVICES += DB120 ++ ++define LegacyDevice/HORNETUBx2 ++ DEVICE_TITLE := ALFA Network Hornet-UB-x2 board (16MB flash, 64MB ram) ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += HORNETUBx2 ++ ++define LegacyDevice/TUBE2H16M ++ DEVICE_TITLE := ALFA Network Tube2H board (16MB flash) ++endef ++LEGACY_DEVICES += TUBE2H16M ++ ++define LegacyDevice/DIR505A1 ++ DEVICE_TITLE := D-Link DIR-505 rev. A1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += DIR505A1 ++ ++define LegacyDevice/DGL5500A1 ++ DEVICE_TITLE := D-Link DGL-5500 rev. A1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath10k-ct ath10k-firmware-qca988x-ct ++endef ++LEGACY_DEVICES += DGL5500A1 ++ ++define LegacyDevice/TEW823DRU ++ DEVICE_TITLE := TRENDNet TEW-823DRU ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath10k-ct ath10k-firmware-qca988x-ct ++endef ++LEGACY_DEVICES += TEW823DRU ++ ++define LegacyDevice/DHP1565A1 ++ DEVICE_TITLE := D-Link DHP-1565 rev. A1 ++ DEVICE_PACKAGES := kmod-usb2 ++endef ++LEGACY_DEVICES += DHP1565A1 ++ ++define LegacyDevice/DIR825C1 ++ DEVICE_TITLE := D-Link DIR-825 rev. C1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += DIR825C1 ++ ++define LegacyDevice/DIR835A1 ++ DEVICE_TITLE := D-Link DIR-835 rev. A1 ++ DEVICE_PACKAGES := kmod-usb2 ++endef ++LEGACY_DEVICES += DIR835A1 ++ ++define LegacyDevice/TEW732BR ++ DEVICE_TITLE := TRENDNet TEW-732BR ++endef ++LEGACY_DEVICES += TEW732BR ++ ++define LegacyDevice/WRT160NL ++ DEVICE_TITLE := Linksys WRT160NL ++ DEVICE_PACKAGES := kmod-usb2 ++endef ++LEGACY_DEVICES += WRT160NL ++ ++define LegacyDevice/MYNETREXT ++ DEVICE_TITLE := Western Digital My Net Wi-Fi Range Extender ++ DEVICE_PACKAGES := rssileds ++endef ++LEGACY_DEVICES += MYNETREXT ++ ++define LegacyDevice/DIR825B1 ++ DEVICE_TITLE := D-Link DIR-825 rev. B1 ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += DIR825B1 ++ ++define LegacyDevice/TEW673GRU ++ DEVICE_TITLE := TRENDNet TEW-673GRU ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += TEW673GRU ++ ++define LegacyDevice/DLRTDEV01 ++ DEVICE_TITLE := PowerCloud Systems dlrtdev01 model ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += DLRTDEV01 ++ ++define LegacyDevice/dLAN_Hotspot ++ DEVICE_TITLE := devolo dLAN Hotspot ++endef ++LEGACY_DEVICES += dLAN_Hotspot ++ ++define LegacyDevice/dLAN_pro_500_wp ++ DEVICE_TITLE := devolo dLAN pro 500 Wireless+ ++endef ++LEGACY_DEVICES += dLAN_pro_500_wp ++ ++define LegacyDevice/dLAN_pro_1200_ac ++ DEVICE_TITLE := devolo dLAN pro 1200+ WiFi ac ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++endef ++LEGACY_DEVICES += dLAN_pro_1200_ac ++ ++define LegacyDevice/ESR900 ++ DEVICE_TITLE := EnGenius ESR900 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += ESR900 ++ ++define LegacyDevice/ESR1750 ++ DEVICE_TITLE := EnGenius ESR1750 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage kmod-ath10k-ct ath10k-firmware-qca988x-ct ++endef ++LEGACY_DEVICES += ESR1750 ++ ++define LegacyDevice/EPG5000 ++ DEVICE_TITLE := EnGenius EPG5000 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage kmod-ath10k-ct ath10k-firmware-qca988x-ct ++endef ++LEGACY_DEVICES += EPG5000 ++ ++define LegacyDevice/WP543_8M ++ DEVICE_TITLE := Compex WP543/WPJ543 (8MB flash) ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += WP543_8M ++ ++define LegacyDevice/WP543_16M ++ DEVICE_TITLE := Compex WP543/WPJ543 (16MB flash) ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += WP543_16M ++ ++define LegacyDevice/WPE72_8M ++ DEVICE_TITLE := Compex WPE72/WPE72NX (8MB flash) ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += WPE72_8M ++ ++define LegacyDevice/WPE72_16M ++ DEVICE_TITLE := Compex WPE72/WPE72NX (16MB flash) ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += WPE72_16M ++ ++define LegacyDevice/WNR2200 ++ DEVICE_TITLE := NETGEAR WNR2200 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WNR2200 ++ ++define LegacyDevice/OM2P ++ DEVICE_TITLE := OpenMesh OM2P/OM2P-HS/OM2P-LC ++ DEVICE_PACKAGES := om-watchdog ++endef ++LEGACY_DEVICES += OM2P ++ ++define LegacyDevice/OM5P ++ DEVICE_TITLE := OpenMesh OM5P/OM5P-AN ++ DEVICE_PACKAGES := om-watchdog ++endef ++LEGACY_DEVICES += OM5P ++ ++define LegacyDevice/OM5PAC ++ DEVICE_TITLE := OpenMesh OM5P-AC ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct om-watchdog ++endef ++LEGACY_DEVICES += OM5PAC ++ ++define LegacyDevice/MR600 ++ DEVICE_TITLE := OpenMesh MR600 ++ DEVICE_PACKAGES := om-watchdog ++endef ++LEGACY_DEVICES += MR600 ++ ++define LegacyDevice/MR900 ++ DEVICE_TITLE := OpenMesh MR900 ++ DEVICE_PACKAGES := om-watchdog ++endef ++LEGACY_DEVICES += MR900 ++ ++define LegacyDevice/MR1750 ++ DEVICE_TITLE := OpenMesh MR1750 ++ DEVICE_PACKAGES := om-watchdog kmod-ath10k-ct ath10k-firmware-qca988x-ct ++endef ++LEGACY_DEVICES += MR1750 ++ ++define LegacyDevice/ALL0305 ++ DEVICE_TITLE := Allnet ALL0305 ++ DEVICE_PACKAGES := fconfig kmod-ath5k -kmod-ath9k ++endef ++LEGACY_DEVICES += ALL0305 ++ ++define LegacyDevice/EAP7660D ++ DEVICE_TITLE := Senao EAP7660D ++endef ++LEGACY_DEVICES += EAP7660D ++ ++define LegacyDevice/JA76PF ++ DEVICE_TITLE := jjPlus JA76PF ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-hwmon-core kmod-i2c-core kmod-hwmon-lm75 ++endef ++LEGACY_DEVICES += JA76PF ++ ++define LegacyDevice/JA76PF2 ++ DEVICE_TITLE := jjPlus JA76PF2 ++endef ++LEGACY_DEVICES += JA76PF2 ++ ++define LegacyDevice/JWAP003 ++ DEVICE_TITLE := jjPlus JWAP003 ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += JWAP003 ++ ++define LegacyDevice/PB42 ++ DEVICE_TITLE := Atheros PB42 reference board ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += PB42 ++ ++define LegacyDevice/PB44 ++ DEVICE_TITLE := Atheros PB44 reference board ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 \ ++ vsc7385-ucode-pb44 vsc7395-ucode-pb44 ++endef ++LEGACY_DEVICES += PB44 ++ ++define LegacyDevice/MZKW04NU ++ DEVICE_TITLE := Planex MZK-W04NU ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += MZKW04NU ++ ++define LegacyDevice/MZKW300NH ++ DEVICE_TITLE := Planex MZK-W300NH ++endef ++LEGACY_DEVICES += MZKW300NH ++ ++define LegacyDevice/EAP300V2 ++ DEVICE_TITLE := EnGenius EAP300V2 ++endef ++LEGACY_DEVICES += EAP300V2 ++ ++define LegacyDevice/WRT400N ++ DEVICE_TITLE := Linksys WRT400N ++endef ++LEGACY_DEVICES += WRT400N ++ ++define LegacyDevice/WZRHPG300NH ++ DEVICE_TITLE := Buffalo WZR-HP-G300NH ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WZRHPG300NH ++ ++define LegacyDevice/WZRHPG300NH2 ++ DEVICE_TITLE := Buffalo WZR-HP-G300NH2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WZRHPG300NH2 ++ ++define LegacyDevice/WZRHPAG300H ++ DEVICE_TITLE := Buffalo WZR-HP-AG300H ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WZRHPAG300H ++ ++define LegacyDevice/WZRHPG450H ++ DEVICE_TITLE := Buffalo WZR-HP-G450H ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WZRHPG450H ++ ++define LegacyDevice/WZR600DHP ++ DEVICE_TITLE := Buffalo WZR-600DHP ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WZR600DHP ++ ++define LegacyDevice/WZR450HP2 ++ DEVICE_TITLE := Buffalo WZR-450HP2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WZR450HP2 ++ ++define LegacyDevice/ZCN1523H28 ++ DEVICE_TITLE := Zcomax ZCN-1523H-2-8 ++endef ++LEGACY_DEVICES += ZCN1523H28 ++ ++define LegacyDevice/ZCN1523H516 ++ DEVICE_TITLE := Zcomax ZCN-1523H-5-16 ++endef ++LEGACY_DEVICES += ZCN1523H516 +diff --git a/target/linux/ar71xx/image/generic-tp-link.mk b/target/linux/ar71xx/image/generic-tp-link.mk +new file mode 100644 +index 0000000000..dac5ad2850 +--- /dev/null ++++ b/target/linux/ar71xx/image/generic-tp-link.mk +@@ -0,0 +1,544 @@ ++include ./common-tp-link.mk ++ ++ ++define Device/archer-cxx ++ $(Device/tplink-safeloader) ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImageArcher lzma ++endef ++ ++define Device/archer-c25-v1 ++ $(Device/archer-cxx) ++ DEVICE_TITLE := TP-LINK Archer C25 v1 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9887-ct ++ BOARDNAME := ARCHER-C25-V1 ++ TPLINK_BOARD_ID := ARCHER-C25-V1 ++ DEVICE_PROFILE := ARCHERC25V1 ++ IMAGE_SIZE := 7808k ++ MTDPARTS := spi0.0:128k(factory-uboot)ro,64k(u-boot)ro,7808k(firmware),128k(config)ro,64k(art)ro ++ SUPPORTED_DEVICES := archer-c25-v1 ++endef ++TARGET_DEVICES += archer-c25-v1 ++ ++define Device/archer-c58-v1 ++ $(Device/archer-cxx) ++ DEVICE_TITLE := TP-LINK Archer C58 v1 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9888-ct ++ BOARDNAME := ARCHER-C58-V1 ++ TPLINK_BOARD_ID := ARCHER-C58-V1 ++ DEVICE_PROFILE := ARCHERC58V1 ++ IMAGE_SIZE := 7936k ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,7936k(firmware),64k(tplink)ro,64k(art)ro ++ SUPPORTED_DEVICES := archer-c58-v1 ++endef ++TARGET_DEVICES += archer-c58-v1 ++ ++define Device/archer-c59-v1 ++ $(Device/archer-cxx) ++ DEVICE_TITLE := TP-LINK Archer C59 v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca9888-ct ++ BOARDNAME := ARCHER-C59-V1 ++ TPLINK_BOARD_ID := ARCHER-C59-V1 ++ DEVICE_PROFILE := ARCHERC59V1 ++ IMAGE_SIZE := 14528k ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,14528k(firmware),1664k(tplink)ro,64k(art)ro ++ SUPPORTED_DEVICES := archer-c59-v1 ++endef ++TARGET_DEVICES += archer-c59-v1 ++ ++define Device/archer-c59-v2 ++ $(Device/archer-c59-v1) ++ DEVICE_TITLE := TP-LINK Archer C59 v2 ++ BOARDNAME := ARCHER-C59-V2 ++ TPLINK_BOARD_ID := ARCHER-C59-V2 ++ DEVICE_PROFILE := ARCHERC59V2 ++ IMAGE_SIZE := 14400k ++ MTDPARTS := spi0.0:128k(factory-boot)ro,64k(u-boot)ro,64k(mac)ro,14400k(firmware),1664k(tplink)ro,64k@0xff0000(art)ro ++ SUPPORTED_DEVICES := archer-c59-v2 ++endef ++TARGET_DEVICES += archer-c59-v2 ++ ++define Device/archer-c60-v1 ++ $(Device/archer-cxx) ++ DEVICE_TITLE := TP-LINK Archer C60 v1 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9888-ct ++ BOARDNAME := ARCHER-C60-V1 ++ TPLINK_BOARD_ID := ARCHER-C60-V1 ++ DEVICE_PROFILE := ARCHERC60V1 ++ IMAGE_SIZE := 7936k ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,7936k(firmware),64k(tplink)ro,64k(art)ro ++ SUPPORTED_DEVICES := archer-c60-v1 ++endef ++TARGET_DEVICES += archer-c60-v1 ++ ++define Device/archer-c60-v2 ++ $(Device/archer-c60-v1) ++ DEVICE_TITLE := TP-LINK Archer C60 v2 ++ BOARDNAME := ARCHER-C60-V2 ++ TPLINK_BOARD_ID := ARCHER-C60-V2 ++ DEVICE_PROFILE := ARCHERC60V2 ++ IMAGE_SIZE := 7808k ++ MTDPARTS := spi0.0:192k(u-boot)ro,7808k(firmware),128k(tplink)ro,64k(art)ro ++ SUPPORTED_DEVICES := archer-c60-v2 ++endef ++TARGET_DEVICES += archer-c60-v2 ++ ++define Device/archer-c5-v1 ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := TP-LINK Archer C5 v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := ARCHER-C5 ++ DEVICE_PROFILE := ARCHERC7 ++ TPLINK_HWID := 0xc5000001 ++endef ++TARGET_DEVICES += archer-c5-v1 ++ ++define Device/archer-c7-v1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK Archer C7 v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := ARCHER-C7 ++ DEVICE_PROFILE := ARCHERC7 ++ TPLINK_HWID := 0x75000001 ++endef ++TARGET_DEVICES += archer-c7-v1 ++ ++define Device/archer-c7-v2 ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := TP-LINK Archer C7 v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := ARCHER-C7-V2 ++ DEVICE_PROFILE := ARCHERC7 ++ TPLINK_HWID := 0xc7000002 ++ IMAGES := sysupgrade.bin factory.bin factory-us.bin factory-eu.bin ++ IMAGE/factory-us.bin := append-rootfs | mktplinkfw factory -C US ++ IMAGE/factory-eu.bin := append-rootfs | mktplinkfw factory -C EU ++endef ++TARGET_DEVICES += archer-c7-v2 ++ ++define Device/archer-c7-v2-il ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := TP-LINK Archer C7 v2 (IL) ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := ARCHER-C7-V2 ++ DEVICE_PROFILE := ARCHERC7 ++ TPLINK_HWID := 0xc7000002 ++ TPLINK_HWREV := 0x494c0001 ++endef ++TARGET_DEVICES += archer-c7-v2-il ++ ++define Device/tl-wdr7500-v3 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK Archer C7 v3 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := ARCHER-C7 ++ DEVICE_PROFILE := ARCHERC7 ++ TPLINK_HWID := 0x75000003 ++endef ++TARGET_DEVICES += tl-wdr7500-v3 ++ ++define Device/archer-c7-v4 ++ $(Device/archer-cxx) ++ DEVICE_TITLE := TP-LINK Archer C7 v4 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := ARCHER-C7-V4 ++ TPLINK_BOARD_ID := ARCHER-C7-V4 ++ IMAGE_SIZE := 15104k ++ MTDPARTS := spi0.0:128k(factory-uboot)ro,128k(u-boot)ro,15104k(firmware),960k(config)ro,64k(art)ro ++ SUPPORTED_DEVICES := archer-c7-v4 ++endef ++TARGET_DEVICES += archer-c7-v4 ++ ++define Device/archer-c7-v5 ++ $(Device/archer-c7-v4) ++ DEVICE_TITLE := TP-LINK Archer C7 v5 ++ BOARDNAME := ARCHER-C7-V5 ++ TPLINK_BOARD_ID := ARCHER-C7-V5 ++ IMAGE_SIZE := 15360k ++ MTDPARTS := spi0.0:128k(factory-uboot)ro,128k(u-boot)ro,64k@0x50000(art)ro,128k@0x60000(info)ro,15360k@0xc0000(firmware) ++ SUPPORTED_DEVICES := archer-c7-v5 ++endef ++TARGET_DEVICES += archer-c7-v5 ++ ++define Device/cpe510-520-v1 ++ DEVICE_TITLE := TP-LINK CPE510/520 v1 ++ BOARDNAME := CPE510 ++ TPLINK_BOARD_ID := CPE510 ++ LOADER_TYPE := elf ++ LOADER_FLASH_OFFS := 0x43000 ++ COMPILE := loader-$(1).elf ++ COMPILE/loader-$(1).elf := loader-okli-compile ++ KERNEL := kernel-bin | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 ++ IMAGES += factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++ DEVICE_PACKAGES := rssileds ++ MTDPARTS := spi0.0:128k(u-boot)ro,64k(partition-table)ro,64k(product-info)ro,2048k(kernel),5632k(rootfs),192k(config)ro,64k(ART)ro,7680k@0x40000(firmware) ++ IMAGE_SIZE := 7680k ++endef ++TARGET_DEVICES += cpe510-520-v1 ++ ++define Device/cpe510-v2 ++ $(Device/cpe510-520-v1) ++ DEVICE_TITLE := TP-LINK CPE510 v2 ++ BOARDNAME := CPE510V2 ++ TPLINK_BOARD_ID := CPE510V2 ++endef ++TARGET_DEVICES += cpe510-v2 ++ ++define Device/cpe210-220-v1 ++ $(Device/cpe510-520-v1) ++ DEVICE_TITLE := TP-LINK CPE210/220 v1 ++ BOARDNAME := CPE210 ++ TPLINK_BOARD_ID := CPE210 ++endef ++TARGET_DEVICES += cpe210-220-v1 ++ ++define Device/cpe210-v2 ++ $(Device/tplink-safeloader) ++ DEVICE_TITLE := TP-LINK CPE210 v2 ++ BOARDNAME := CPE210V2 ++ TPLINK_BOARD_ID := CPE210V2 ++ TPLINK_HWID := 0x0 ++ TPLINK_HWREV := 0 ++ MTDPARTS := spi0.0:128k(u-boot)ro,64k(partition-table)ro,64k(product-info)ro,7680k(firmware),192k(config)ro,64k(ART)ro ++ IMAGE_SIZE := 7680k ++ KERNEL := kernel-bin | patch-cmdline | lzma | tplink-v1-header -O ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++ DEVICE_PACKAGES := rssileds ++endef ++TARGET_DEVICES += cpe210-v2 ++ ++define Device/cpe210-v3 ++ $(Device/tplink-safeloader) ++ DEVICE_TITLE := TP-LINK CPE210 v3 ++ BOARDNAME := CPE210V3 ++ TPLINK_BOARD_ID := CPE210V3 ++ TPLINK_HWID := 0x0 ++ TPLINK_HWREV := 0 ++ MTDPARTS := spi0.0:128k(u-boot)ro,64k(partition-table)ro,64k(product-info)ro,7680k(firmware),192k(config)ro,64k(ART)ro ++ IMAGE_SIZE := 7680k ++ KERNEL := kernel-bin | patch-cmdline | lzma | tplink-v1-header -O ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++ DEVICE_PACKAGES := rssileds ++endef ++TARGET_DEVICES += cpe210-v3 ++ ++define Device/wbs210-v1 ++ $(Device/cpe510-520-v1) ++ DEVICE_TITLE := TP-LINK WBS210 v1 ++ BOARDNAME := WBS210 ++ TPLINK_BOARD_ID := WBS210 ++endef ++TARGET_DEVICES += wbs210-v1 ++ ++define Device/wbs510-v1 ++ $(Device/cpe510-520-v1) ++ DEVICE_TITLE := TP-LINK WBS510 v1 ++ BOARDNAME := WBS510 ++ TPLINK_BOARD_ID := WBS510 ++endef ++TARGET_DEVICES += wbs510-v1 ++ ++define Device/eap120-v1 ++ DEVICE_TITLE := TP-LINK EAP120 v1 ++ MTDPARTS := spi0.0:128k(u-boot)ro,64k(partition-table)ro,64k(product-info)ro,1536k(kernel),14336k(rootfs),192k(config)ro,64k(ART)ro,15872k@0x40000(firmware) ++ IMAGE_SIZE := 15872k ++ BOARDNAME := EAP120 ++ TPLINK_BOARD_ID := EAP120 ++ DEVICE_PROFILE := EAP120 ++ LOADER_TYPE := elf ++ KERNEL := kernel-bin | patch-cmdline | lzma | loader-kernel ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++endef ++TARGET_DEVICES += eap120-v1 ++ ++define Device/re355-v1 ++ $(Device/tplink-safeloader) ++ DEVICE_TITLE := TP-LINK RE355 v1 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ MTDPARTS := spi0.0:128k(u-boot)ro,6016k(firmware),64k(partition-table)ro,64k(product-info)ro,1856k(config)ro,64k(art)ro ++ IMAGE_SIZE := 7936k ++ BOARDNAME := RE355 ++ TPLINK_BOARD_ID := RE355 ++ DEVICE_PROFILE := RE355 ++ TPLINK_HWID := 0x0 ++ TPLINK_HWREV := 0 ++ KERNEL := kernel-bin | patch-cmdline | lzma | tplink-v1-header -O ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++endef ++TARGET_DEVICES += re355-v1 ++ ++define Device/re450-v1 ++ $(Device/tplink-safeloader) ++ DEVICE_TITLE := TP-LINK RE450 v1 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ MTDPARTS := spi0.0:128k(u-boot)ro,6016k(firmware),64k(partition-table)ro,64k(product-info)ro,1856k(config)ro,64k(art)ro ++ IMAGE_SIZE := 7936k ++ BOARDNAME := RE450 ++ TPLINK_BOARD_ID := RE450 ++ DEVICE_PROFILE := RE450 ++ TPLINK_HWID := 0x0 ++ TPLINK_HWREV := 0 ++ KERNEL := kernel-bin | patch-cmdline | lzma | tplink-v1-header -O ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++endef ++TARGET_DEVICES += re450-v1 ++ ++define Device/tl-mr6400-v1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-MR6400 v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-net kmod-usb-net-rndis kmod-usb-serial kmod-usb-serial-option adb-enablemodem ++ BOARDNAME := TL-MR6400 ++ DEVICE_PROFILE := TLMR6400 ++ TPLINK_HWID := 0x64000001 ++endef ++TARGET_DEVICES += tl-mr6400-v1 ++ ++define Device/tl-wdr3500-v1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WDR3500 v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WDR3500 ++ DEVICE_PROFILE := TLWDR4300 ++ TPLINK_HWID := 0x35000001 ++endef ++TARGET_DEVICES += tl-wdr3500-v1 ++ ++define Device/tl-wdr3600-v1 ++ $(Device/tl-wdr3500-v1) ++ DEVICE_TITLE := TP-LINK TL-WDR3600 v1 ++ BOARDNAME := TL-WDR4300 ++ TPLINK_HWID := 0x36000001 ++ IMAGE/factory.bin := append-rootfs | mktplinkfw factory -C US ++endef ++TARGET_DEVICES += tl-wdr3600-v1 ++ ++define Device/tl-wdr4300-v1 ++ $(Device/tl-wdr3600-v1) ++ DEVICE_TITLE := TP-LINK TL-WDR4300 v1 ++ TPLINK_HWID := 0x43000001 ++endef ++TARGET_DEVICES += tl-wdr4300-v1 ++ ++define Device/tl-wdr4300-v1-il ++ $(Device/tl-wdr3500-v1) ++ DEVICE_TITLE := TP-LINK TL-WDR4300 v1 (IL) ++ BOARDNAME := TL-WDR4300 ++ TPLINK_HWID := 0x43008001 ++endef ++TARGET_DEVICES += tl-wdr4300-v1-il ++ ++define Device/tl-wdr4310-v1 ++ $(Device/tl-wdr4300-v1-il) ++ DEVICE_TITLE := TP-LINK TL-WDR4310 v1 ++ TPLINK_HWID := 0x43100001 ++endef ++TARGET_DEVICES += tl-wdr4310-v1 ++ ++define Device/tl-wdr4900-v2 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WDR4900 v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WDR4900-v2 ++ DEVICE_PROFILE := TLWDR4900V2 ++ TPLINK_HWID := 0x49000002 ++endef ++TARGET_DEVICES += tl-wdr4900-v2 ++ ++define Device/tl-wdr6500-v2 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WDR6500 v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImage lzma ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | uImage lzma | tplink-v1-header ++ BOARDNAME := TL-WDR6500-v2 ++ DEVICE_PROFILE := TLWDR6500V2 ++ TPLINK_HWID := 0x65000002 ++ TPLINK_HEADER_VERSION := 2 ++endef ++TARGET_DEVICES += tl-wdr6500-v2 ++ ++define Device/mw4530r-v1 ++ $(Device/tl-wdr4300-v1) ++ DEVICE_TITLE := Mercury MW4530R v1 ++ TPLINK_HWID := 0x45300001 ++endef ++TARGET_DEVICES += mw4530r-v1 ++ ++define Device/tl-wpa8630-v1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WPA8630 v1 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := TL-WPA8630 ++ DEVICE_PROFILE := TL-WPA8630 ++ TPLINK_HWID := 0x86300001 ++endef ++TARGET_DEVICES += tl-wpa8630-v1 ++ ++define Device/tl-wr1043n-v5 ++ $(Device/archer-cxx) ++ DEVICE_TITLE := TP-LINK TL-WR1043N v5 ++ BOARDNAME := TL-WR1043N-v5 ++ SUPPORTED_DEVICES := tl-wr1043n-v5 ++ DEVICE_PROFILE := TLWR1043 ++ MTDPARTS := spi0.0:128k(factory-uboot)ro,128k(u-boot)ro,15104k(firmware),128k(product-info)ro,640k(config)ro,64k(partition-table)ro,128k(logs)ro,64k(art)ro ++ IMAGE_SIZE := 15104k ++ TPLINK_BOARD_ID := TLWR1043NV5 ++endef ++TARGET_DEVICES += tl-wr1043n-v5 ++ ++define Device/tl-wr1043nd-v1 ++ $(Device/tplink-8m) ++ DEVICE_TITLE := TP-LINK TL-WR1043N/ND v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WR1043ND ++ DEVICE_PROFILE := TLWR1043 ++ TPLINK_HWID := 0x10430001 ++endef ++TARGET_DEVICES += tl-wr1043nd-v1 ++ ++define Device/tl-wr1043nd-v2 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR1043N/ND v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WR1043ND-v2 ++ DEVICE_PROFILE := TLWR1043 ++ TPLINK_HWID := 0x10430002 ++endef ++TARGET_DEVICES += tl-wr1043nd-v2 ++ ++define Device/tl-wr1043nd-v3 ++ $(Device/tl-wr1043nd-v2) ++ DEVICE_TITLE := TP-LINK TL-WR1043N/ND v3 ++ TPLINK_HWID := 0x10430003 ++endef ++TARGET_DEVICES += tl-wr1043nd-v3 ++ ++define Device/tl-wr1043nd-v4 ++ $(Device/tplink-safeloader) ++ DEVICE_TITLE := TP-LINK TL-WR1043N/ND v4 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WR1043ND-v4 ++ DEVICE_PROFILE := TLWR1043 ++ TPLINK_HWID := 0x10430004 ++ MTDPARTS := spi0.0:128k(u-boot)ro,15552k(firmware),128k(product-info)ro,320k(config)ro,64k(partition-table)ro,128k(logs)ro,64k(ART)ro ++ IMAGE_SIZE := 15552k ++ TPLINK_BOARD_ID := TLWR1043NDV4 ++ KERNEL := kernel-bin | patch-cmdline | lzma | tplink-v1-header -O ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++endef ++TARGET_DEVICES += tl-wr1043nd-v4 ++ ++define Device/tl-wr2543-v1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR2543N/ND v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WR2543N ++ DEVICE_PROFILE := TLWR2543 ++ TPLINK_HWID := 0x25430001 ++ IMAGE/sysupgrade.bin := append-rootfs | mktplinkfw sysupgrade -v 3.13.99 ++ IMAGE/factory.bin := append-rootfs | mktplinkfw factory -v 3.13.99 ++endef ++TARGET_DEVICES += tl-wr2543-v1 ++ ++define Device/tl-wr710n-v1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR710N v1 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := TL-WR710N ++ DEVICE_PROFILE := TLWR710 ++ TPLINK_HWID := 0x07100001 ++ CONSOLE := ttyATH0,115200 ++ IMAGE/factory.bin := append-rootfs | mktplinkfw factory -C US ++endef ++TARGET_DEVICES += tl-wr710n-v1 ++ ++define Device/tl-wr710n-v2.1 ++ $(Device/tl-wr710n-v1) ++ DEVICE_TITLE := TP-LINK TL-WR710N v2.1 ++ TPLINK_HWID := 0x07100002 ++ TPLINK_HWREV := 0x00000002 ++endef ++TARGET_DEVICES += tl-wr710n-v2.1 ++ ++define Device/tl-wr810n-v1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR810N v1 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := TL-WR810N ++ DEVICE_PROFILE := TLWR810 ++ TPLINK_HWID := 0x08100001 ++endef ++TARGET_DEVICES += tl-wr810n-v1 ++ ++define Device/tl-wr810n-v2 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR810N v2 ++ BOARDNAME := TL-WR810N-v2 ++ DEVICE_PROFILE := TLWR810 ++ TPLINK_HWID := 0x08100002 ++endef ++TARGET_DEVICES += tl-wr810n-v2 ++ ++define Device/tl-wr842n-v1 ++ $(Device/tplink-8m) ++ DEVICE_TITLE := TP-LINK TL-WR842N/ND v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-MR3420 ++ DEVICE_PROFILE := TLWR842 ++ TPLINK_HWID := 0x08420001 ++endef ++TARGET_DEVICES += tl-wr842n-v1 ++ ++define Device/tl-wr842n-v2 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR842N/ND v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WR842N-v2 ++ DEVICE_PROFILE := TLWR842 ++ TPLINK_HWID := 0x8420002 ++endef ++TARGET_DEVICES += tl-wr842n-v2 ++ ++define Device/tl-wr842n-v3 ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR842N/ND v3 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WR842N-v3 ++ DEVICE_PROFILE := TLWR842 ++ TPLINK_HWID := 0x08420003 ++endef ++TARGET_DEVICES += tl-wr842n-v3 ++ ++define Device/tl-wr902ac-v1 ++ $(Device/tplink-safeloader) ++ DEVICE_TITLE := TP-LINK TL-WR902AC v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport \ ++ kmod-ath10k-ct ath10k-firmware-qca9887-ct -swconfig -uboot-envtools ++ BOARDNAME := TL-WR902AC-V1 ++ DEVICE_PROFILE := TLWR902 ++ TPLINK_BOARD_ID := TL-WR902AC-V1 ++ TPLINK_HWID := 0x0 ++ TPLINK_HWREV := 0 ++ SUPPORTED_DEVICES := tl-wr902ac-v1 ++ IMAGE_SIZE := 7360k ++ MTDPARTS := spi0.0:128k(u-boot)ro,7360k(firmware),640k(tplink)ro,64k(art)ro ++ KERNEL := kernel-bin | patch-cmdline | lzma | tplink-v1-header -O ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++endef ++TARGET_DEVICES += tl-wr902ac-v1 ++ ++define Device/tl-wr942n-v1 ++ $(Device/archer-cxx) ++ DEVICE_TITLE := TP-LINK TL-WR942N v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WR942N-V1 ++ TPLINK_BOARD_ID := TLWR942NV1 ++ DEVICE_PROFILE := TLWR942 ++ IMAGE_SIZE := 14464k ++ MTDPARTS := spi0.0:128k(u-boot)ro,14464k(firmware),64k(product-info)ro,64k(partition-table)ro,256k(oem-config)ro,1344k(oem-vars)ro,64k(ART)ro ++ SUPPORTED_DEVICES := tl-wr942n-v1 ++endef ++TARGET_DEVICES += tl-wr942n-v1 +diff --git a/target/linux/ar71xx/image/generic-ubnt.mk b/target/linux/ar71xx/image/generic-ubnt.mk +new file mode 100644 +index 0000000000..539f0d82b3 +--- /dev/null ++++ b/target/linux/ar71xx/image/generic-ubnt.mk +@@ -0,0 +1,319 @@ ++DEVICE_VARS += UBNT_BOARD UBNT_CHIP UBNT_TYPE UBNT_VERSION UBNT_REVISION ++ ++# On M (XW) devices the U-Boot as of version 1.1.4-s1039 doesn't like ++# VERSION_DIST being on the place of major(?) version number, so we need to ++# use some number. ++UBNT_REVISION := $(VERSION_DIST)-$(REVISION) ++ ++# mkubntimage is using the kernel image direct ++# routerboard creates partitions out of the ubnt header ++define Build/mkubntimage ++ -$(STAGING_DIR_HOST)/bin/mkfwimage \ ++ -B $(UBNT_BOARD) -v $(UBNT_TYPE).$(UBNT_CHIP).v6.0.0-$(VERSION_DIST)-$(REVISION) \ ++ -k $(IMAGE_KERNEL) \ ++ -r $@ \ ++ -o $@ ++endef ++ ++# all UBNT XM device expect the kernel image to have 1024k while flash, when ++# booting the image, the size doesn't matter. ++define Build/mkubntimage-split ++ -[ -f $@ ] && ( \ ++ dd if=$@ of=$@.old1 bs=1024k count=1; \ ++ dd if=$@ of=$@.old2 bs=1024k skip=1; \ ++ $(STAGING_DIR_HOST)/bin/mkfwimage \ ++ -B $(UBNT_BOARD) -v $(UBNT_TYPE).$(UBNT_CHIP).v$(UBNT_VERSION)-$(UBNT_REVISION) \ ++ -k $@.old1 \ ++ -r $@.old2 \ ++ -o $@; \ ++ rm $@.old1 $@.old2 ) ++endef ++ ++define Build/mkubntimage2 ++ -$(STAGING_DIR_HOST)/bin/mkfwimage2 -f 0x9f000000 \ ++ -v $(UBNT_TYPE).$(UBNT_CHIP).v6.0.0-$(VERSION_DIST)-$(REVISION) \ ++ -p jffs2:0x50000:0xf60000:0:0:$@ \ ++ -o $@.new ++ @mv $@.new $@ ++endef ++ ++ ++# UBNT_BOARD e.g. one of (XS2, XS5, RS, XM) ++# UBNT_TYPE e.g. one of (BZ, XM, XW) ++# UBNT_CHIP e.g. one of (ar7240, ar933x, ar934x) ++# UBNT_VERSION e.g. one of (6.0.0, 8.5.0) ++define Device/ubnt ++ DEVICE_PACKAGES := kmod-usb2 ++ DEVICE_PROFILE := UBNT ++ IMAGE_SIZE := 7552k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,7552k(firmware),256k(cfg)ro,64k(EEPROM)ro ++ UBNT_BOARD := XM ++ UBNT_VERSION := 6.0.0 ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory.bin := $$(IMAGE/sysupgrade.bin) | mkubntimage-split ++endef ++ ++define Device/ubnt-xm ++ $(Device/ubnt) ++ DEVICE_PACKAGES += kmod-usb-ohci ++ UBNT_TYPE := XM ++ UBNT_CHIP := ar7240 ++ KERNEL := kernel-bin | patch-cmdline | relocate-kernel | lzma | uImage lzma ++endef ++ ++define Device/ubnt-xw ++ $(Device/ubnt) ++ UBNT_TYPE := XW ++ UBNT_CHIP := ar934x ++ UBNT_VERSION := 6.0.4 ++ UBNT_REVISION := 42.$(UBNT_REVISION) ++endef ++ ++define Device/ubnt-bz ++ $(Device/ubnt) ++ UBNT_TYPE := BZ ++ UBNT_CHIP := ar7240 ++endef ++ ++define Device/rw2458n ++ $(Device/ubnt-xm) ++ DEVICE_TITLE := Ubiquiti RW2458N ++ BOARDNAME := RW2458N ++endef ++TARGET_DEVICES += rw2458n ++ ++define Device/ubnt-airrouter ++ $(Device/ubnt-xm) ++ DEVICE_TITLE := Ubiquiti AirRouter ++ BOARDNAME := UBNT-AR ++endef ++TARGET_DEVICES += ubnt-airrouter ++ ++define Device/ubnt-bullet-m ++ $(Device/ubnt-xm) ++ DEVICE_TITLE := Ubiquiti Bullet-M ++ DEVICE_PACKAGES += rssileds ++ BOARDNAME := UBNT-BM ++endef ++TARGET_DEVICES += ubnt-bullet-m ++ ++define Device/ubnt-rocket-m ++ $(Device/ubnt-xm) ++ DEVICE_TITLE := Ubiquiti Rocket-M ++ DEVICE_PACKAGES += rssileds ++ BOARDNAME := UBNT-RM ++endef ++TARGET_DEVICES += ubnt-rocket-m ++ ++define Device/ubnt-nano-m ++ $(Device/ubnt-xm) ++ DEVICE_TITLE := Ubiquiti Nano-M ++ DEVICE_PACKAGES += rssileds ++ BOARDNAME := UBNT-NM ++endef ++TARGET_DEVICES += ubnt-nano-m ++ ++define Device/ubnt-unifi ++ $(Device/ubnt-bz) ++ DEVICE_TITLE := Ubiquiti UniFi ++ BOARDNAME := UBNT-UF ++ DEVICE_PROFILE += UBNTUNIFI ++endef ++TARGET_DEVICES += ubnt-unifi ++ ++define Device/ubnt-unifiac ++ DEVICE_PACKAGES := kmod-usb2 ++ DEVICE_PROFILE := UBNT ++ IMAGE_SIZE := 7744k ++ MTDPARTS := spi0.0:384k(u-boot)ro,64k(u-boot-env)ro,7744k(firmware),7744k(ubnt-airos)ro,128k(bs),256k(cfg)ro,64k(EEPROM)ro ++ IMAGES := sysupgrade.bin ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) ++endef ++ ++define Device/ubnt-unifiac-lite ++ $(Device/ubnt-unifiac) ++ DEVICE_TITLE := Ubiquiti UniFi AC-Lite ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ DEVICE_PROFILE += UBNTUNIFIACLITE ++ BOARDNAME := UBNT-UF-AC-LITE ++endef ++TARGET_DEVICES += ubnt-unifiac-lite ++ ++define Device/ubnt-unifiac-lr ++ $(Device/ubnt-unifiac-lite) ++ DEVICE_TITLE := Ubiquiti UniFi AC-LR ++endef ++TARGET_DEVICES += ubnt-unifiac-lr ++ ++define Device/ubnt-unifiac-mesh ++ $(Device/ubnt-unifiac-lite) ++ DEVICE_TITLE := Ubiquiti UniFi AC-Mesh ++endef ++TARGET_DEVICES += ubnt-unifiac-mesh ++ ++define Device/ubnt-unifiac-pro ++ $(Device/ubnt-unifiac) ++ DEVICE_TITLE := Ubiquiti UniFi AC-Pro ++ DEVICE_PACKAGES += kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ DEVICE_PROFILE += UBNTUNIFIACPRO ++ BOARDNAME := UBNT-UF-AC-PRO ++endef ++TARGET_DEVICES += ubnt-unifiac-pro ++ ++define Device/ubnt-unifiac-mesh-pro ++ $(Device/ubnt-unifiac-pro) ++ DEVICE_TITLE := Ubiquiti UniFi AC-Mesh-Pro ++endef ++TARGET_DEVICES += ubnt-unifiac-mesh-pro ++ ++define Device/ubnt-unifi-outdoor ++ $(Device/ubnt-bz) ++ DEVICE_TITLE := Ubiquiti UniFi Outdoor ++ BOARDNAME := UBNT-U20 ++ DEVICE_PROFILE += UBNTUNIFIOUTDOOR ++endef ++TARGET_DEVICES += ubnt-unifi-outdoor ++ ++define Device/ubnt-nano-m-xw ++ $(Device/ubnt-xw) ++ DEVICE_TITLE := Ubiquiti Nano M XW ++ DEVICE_PACKAGES += rssileds ++ BOARDNAME := UBNT-NM-XW ++endef ++TARGET_DEVICES += ubnt-nano-m-xw ++ ++define Device/ubnt-lbe-m5 ++ $(Device/ubnt-xw) ++ DEVICE_TITLE := Ubiquiti Litebeam M5 ++ BOARDNAME := UBNT-LBE-M5 ++endef ++TARGET_DEVICES += ubnt-lbe-m5 ++ ++define Device/ubnt-loco-m-xw ++ $(Device/ubnt-xw) ++ DEVICE_TITLE := Ubiquiti Loco XW ++ DEVICE_PACKAGES += rssileds ++ BOARDNAME := UBNT-LOCO-XW ++endef ++TARGET_DEVICES += ubnt-loco-m-xw ++ ++define Device/ubnt-bullet-m-xw ++ $(Device/ubnt-xw) ++ DEVICE_TITLE := Ubiquiti Bullet-M XW ++ DEVICE_PACKAGES += rssileds ++ BOARDNAME := UBNT-BM-XW ++endef ++TARGET_DEVICES += ubnt-bullet-m-xw ++ ++define Device/ubnt-rocket-m-xw ++ $(Device/ubnt-xw) ++ DEVICE_TITLE := Ubiquiti Rocket M XW ++ DEVICE_PACKAGES += rssileds ++ BOARDNAME := UBNT-RM-XW ++endef ++TARGET_DEVICES += ubnt-rocket-m-xw ++ ++define Device/ubnt-rocket-m-ti ++ $(Device/ubnt-xw) ++ DEVICE_TITLE := Ubiquiti Rocket M TI ++ DEVICE_PACKAGES += rssileds ++ BOARDNAME := UBNT-RM-TI ++ UBNT_TYPE := TI ++endef ++TARGET_DEVICES += ubnt-rocket-m-ti ++ ++define Device/ubnt-air-gateway ++ $(Device/ubnt-xm) ++ DEVICE_TITLE := Ubiquiti Air Gateway ++ BOARDNAME := UBNT-AGW ++ UBNT_TYPE := AirGW ++ UBNT_CHIP := ar933x ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += ubnt-air-gateway ++ ++define Device/ubnt-air-gateway-pro ++ $(Device/ubnt-xm) ++ DEVICE_TITLE := Ubiquiti Air Gateway Pro ++ BOARDNAME := UBNT-AGWP ++ UBNT_TYPE := AirGWP ++ UBNT_CHIP := ar934x ++endef ++TARGET_DEVICES += ubnt-air-gateway-pro ++ ++define Device/ubdev01 ++ $(Device/ubnt-xm) ++ DEVICE_TITLE := Ubiquiti ubDEV01 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,7488k(firmware),64k(certs),256k(cfg)ro,64k(EEPROM)ro ++ BOARDNAME := UBNT-UF ++ UBNT_BOARD := UBDEV01 ++endef ++TARGET_DEVICES += ubdev01 ++ ++define Device/ubnt-routerstation ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++ DEVICE_PROFILE := UBNT ++ IMAGE_SIZE := 16128k ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/factory.bin := append-rootfs | pad-rootfs | mkubntimage ++ IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs | combined-image | check-size $$$$(IMAGE_SIZE) ++ KERNEL := kernel-bin | patch-cmdline | lzma | pad-to $$(BLOCKSIZE) ++endef ++ ++define Device/ubnt-rs ++ $(Device/ubnt-routerstation) ++ DEVICE_TITLE := Ubiquiti RouterStation ++ BOARDNAME := UBNT-RS ++ DEVICE_PROFILE += UBNTRS ++ UBNT_BOARD := RS ++ UBNT_TYPE := RSx ++ UBNT_CHIP := ar7100 ++endef ++TARGET_DEVICES += ubnt-rs ++ ++define Device/ubnt-rspro ++ $(Device/ubnt-routerstation) ++ DEVICE_TITLE := Ubiquiti RouterStation Pro ++ BOARDNAME := UBNT-RSPRO ++ DEVICE_PROFILE += UBNTRSPRO ++ UBNT_BOARD := RSPRO ++ UBNT_TYPE := RSPRO ++ UBNT_CHIP := ar7100pro ++endef ++TARGET_DEVICES += ubnt-rspro ++ ++define Device/ubnt-ls-sr71 ++ $(Device/ubnt-routerstation) ++ DEVICE_TITLE := Ubiquiti LS-SR71 ++ BOARDNAME := UBNT-LS-SR71 ++ UBNT_BOARD := LS-SR71 ++ UBNT_TYPE := LS-SR71 ++ UBNT_CHIP := ar7100 ++endef ++TARGET_DEVICES += ubnt-ls-sr71 ++ ++define Device/ubnt-uap-pro ++ DEVICE_TITLE := Ubiquiti UAP Pro ++ KERNEL_SIZE := 2048k ++ IMAGE_SIZE := 15744k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,2048k(kernel),13696k(rootfs),256k(cfg)ro,64k(EEPROM)ro,15744k@0x50000(firmware) ++ UBNT_TYPE := BZ ++ UBNT_CHIP := ar934x ++ BOARDNAME := UAP-PRO ++ DEVICE_PROFILE := UBNT UAPPRO ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImage lzma | jffs2 kernel0 ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory.bin := $$(IMAGE/sysupgrade.bin) | mkubntimage2 ++endef ++TARGET_DEVICES += ubnt-uap-pro ++ ++define Device/ubnt-unifi-outdoor-plus ++ $(Device/ubnt-uap-pro) ++ DEVICE_TITLE := Ubiquiti UniFi Outdoor Plus ++ UBNT_CHIP := ar7240 ++ BOARDNAME := UBNT-UOP ++ DEVICE_PROFILE := UBNT ++endef ++TARGET_DEVICES += ubnt-unifi-outdoor-plus +diff --git a/target/linux/ar71xx/image/generic.mk b/target/linux/ar71xx/image/generic.mk +new file mode 100644 +index 0000000000..27e2a5fc22 +--- /dev/null ++++ b/target/linux/ar71xx/image/generic.mk +@@ -0,0 +1,1352 @@ ++DEVICE_VARS += DAP_SIGNATURE NETGEAR_BOARD_ID NETGEAR_HW_ID NETGEAR_KERNEL_MAGIC ROOTFS_SIZE ++DEVICE_VARS += SEAMA_SIGNATURE SEAMA_MTDBLOCK ++ ++define Build/alfa-network-rootfs-header ++ mkimage \ ++ -A mips -O linux -T filesystem -C lzma -a 0 -e 0 \ ++ -n 'RootfsImage' -d $@ $@.new ++ @mv $@.new $@ ++endef ++ ++define Build/append-md5sum-bin ++ $(STAGING_DIR_HOST)/bin/mkhash md5 $@ | sed 's/../\\\\x&/g' |\ ++ xargs echo -ne >> $@ ++endef ++ ++define Build/mkwrggimg ++ $(STAGING_DIR_HOST)/bin/mkwrggimg -b \ ++ -i $@ -o $@.imghdr -d /dev/mtdblock/1 \ ++ -m $(BOARDNAME) -s $(DAP_SIGNATURE) \ ++ -v $(VERSION_DIST) -B $(REVISION) ++ mv $@.imghdr $@ ++endef ++ ++define Build/mkdapimg2 ++ $(STAGING_DIR_HOST)/bin/mkdapimg2 \ ++ -i $@ -o $@.new \ ++ -s $(DAP_SIGNATURE) \ ++ -v $(VERSION_DIST)-$(firstword $(subst +, ,$(firstword $(subst -, ,$(REVISION))))) \ ++ -r Default \ ++ $(if $(1),-k $(1)) ++ mv $@.new $@ ++endef ++ ++define Build/netgear-squashfs ++ rm -rf $@.fs $@.squashfs ++ mkdir -p $@.fs/image ++ cp $@ $@.fs/image/uImage ++ $(STAGING_DIR_HOST)/bin/mksquashfs-lzma \ ++ $@.fs $@.squashfs \ ++ -noappend -root-owned -be -b 65536 \ ++ $(if $(SOURCE_DATE_EPOCH),-fixed-time $(SOURCE_DATE_EPOCH)) ++ ++ dd if=/dev/zero bs=1k count=1 >> $@.squashfs ++ mkimage \ ++ -A mips -O linux -T filesystem -C none \ ++ -M $(NETGEAR_KERNEL_MAGIC) \ ++ -a 0xbf070000 -e 0xbf070000 \ ++ -n 'MIPS $(VERSION_DIST) Linux-$(LINUX_VERSION)' \ ++ -d $@.squashfs $@ ++ rm -rf $@.squashfs $@.fs ++endef ++ ++define Build/netgear-uImage ++ $(call Build/uImage,$(1) -M $(NETGEAR_KERNEL_MAGIC)) ++endef ++ ++define Build/relocate-kernel ++ rm -rf $@.relocate ++ $(CP) ../../generic/image/relocate $@.relocate ++ $(MAKE) -j1 -C $@.relocate KERNEL_ADDR=$(KERNEL_LOADADDR) CROSS_COMPILE=$(TARGET_CROSS) ++ ( \ ++ dd if=$@.relocate/loader.bin bs=32 conv=sync && \ ++ perl -e '@s = stat("$@"); print pack("N", @s[7])' && \ ++ cat "$@" \ ++ ) > "$@.new" ++ mv "$@.new" "$@" ++ rm -rf $@.relocate ++endef ++ ++define Build/teltonika-fw-fake-checksum ++ # Teltonika U-Boot web based firmware upgrade/recovery routine compares ++ # 16 bytes from md5sum1[16] field in TP-Link v1 header (offset: 76 bytes ++ # from begin of the firmware file) with 16 bytes stored just before ++ # 0xdeadc0de marker. Values are only compared, MD5 sum is not verified. ++ let \ ++ offs="$$(stat -c%s $@) - 20"; \ ++ dd if=$@ bs=1 count=16 skip=76 |\ ++ dd of=$@ bs=1 count=16 seek=$$offs conv=notrunc ++endef ++ ++define Build/uImageHiWiFi ++ # Field ih_name needs to start with "tw150v1" ++ mkimage -A $(LINUX_KARCH) \ ++ -O linux -T kernel \ ++ -C $(1) -a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ ++ -n 'tw150v1 $(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION)' -d $@ $@.new ++ @mv $@.new $@ ++endef ++ ++define Build/wrgg-pad-rootfs ++ $(STAGING_DIR_HOST)/bin/padjffs2 $(IMAGE_ROOTFS) -c 64 >>$@ ++endef ++ ++ ++define Device/ap121f ++ DEVICE_TITLE := ALFA Network AP121F ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage -swconfig ++ BOARDNAME := AP121F ++ IMAGE_SIZE := 16064k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:192k(u-boot)ro,64k(u-boot-env),64k(art)ro,-(firmware) ++ SUPPORTED_DEVICES := ap121f ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += ap121f ++ ++define Device/ap531b0 ++ DEVICE_TITLE := Rockeetech AP531B0 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := AP531B0 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += ap531b0 ++ ++define Device/ap90q ++ DEVICE_TITLE := YunCore AP80Q/AP90Q ++ BOARDNAME := AP90Q ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += ap90q ++ ++define Device/ap91-5g ++ DEVICE_TITLE := ALFA Network AP91-5G ++ DEVICE_PACKAGES := rssileds -swconfig ++ BOARDNAME := AP91-5G ++ IMAGE_SIZE := 7744k ++ KERNEL_SIZE := 1600k ++ ROOTFS_SIZE := 6144k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),6144k(rootfs),1600k(kernel),64k(config)ro,64k(art)ro,7744k@0x50000(firmware) ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/factory.bin := append-rootfs | pad-rootfs |\ ++ alfa-network-rootfs-header | append-kernel | check-size $$$$(IMAGE_SIZE) ++ IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs |\ ++ pad-to $$$$(ROOTFS_SIZE) | append-kernel | check-size $$$$(IMAGE_SIZE) ++endef ++ ++define Device/arduino-yun ++ DEVICE_TITLE := Arduino Yun ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := Yun ++ IMAGE_SIZE := 15936k ++ CONSOLE := ttyATH0,250000 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),15936k(firmware),64k(nvram),64k(art)ro ++endef ++TARGET_DEVICES += arduino-yun ++ ++define Device/bsb ++ DEVICE_TITLE := Smart Electronics Black Swift board ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := BSB ++ IMAGE_SIZE := 16000k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:128k(u-boot)ro,64k(u-boot-env)ro,16128k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += bsb ++ ++define Device/carambola2 ++ DEVICE_TITLE := 8devices Carambola2 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := CARAMBOLA2 ++ IMAGE_SIZE := 16000k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += carambola2 ++ ++define Device/cf-e316n-v2 ++ DEVICE_TITLE := COMFAST CF-E316N v2 ++ DEVICE_PACKAGES := -swconfig -uboot-envtools ++ BOARDNAME := CF-E316N-V2 ++ IMAGE_SIZE := 16192k ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(art)ro,16192k(firmware),64k(art-backup)ro ++endef ++TARGET_DEVICES += cf-e316n-v2 ++ ++define Device/cf-e320n-v2 ++ $(Device/cf-e316n-v2) ++ DEVICE_TITLE := COMFAST CF-E320N v2 ++ DEVICE_PACKAGES += kmod-usb2 ++ BOARDNAME := CF-E320N-V2 ++endef ++TARGET_DEVICES += cf-e320n-v2 ++ ++define Device/cf-e355ac-v1 ++ DEVICE_TITLE := COMFAST CF-E355AC v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath10k-ct ath10k-firmware-qca988x-ct \ ++ -swconfig -uboot-envtools ++ BOARDNAME := CF-E355AC-V1 ++ IMAGE_SIZE := 16192k ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(art)ro,16192k(firmware),64k(art-backup)ro ++endef ++TARGET_DEVICES += cf-e355ac-v1 ++ ++define Device/cf-e355ac-v2 ++ $(Device/cf-e355ac-v1) ++ DEVICE_TITLE := COMFAST CF-E355AC v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath10k-ct ath10k-firmware-qca9888-ct \ ++ -swconfig -uboot-envtools ++ BOARDNAME := CF-E355AC-V2 ++endef ++TARGET_DEVICES += cf-e355ac-v2 ++ ++define Device/cf-e375ac ++ DEVICE_TITLE := COMFAST CF-E375AC ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath10k-ct ath10k-firmware-qca9888-ct \ ++ -uboot-envtools ++ BOARDNAME := CF-E375AC ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(art)ro,16000k(firmware),64k(art-backup)ro ++endef ++TARGET_DEVICES += cf-e375ac ++ ++define Device/cf-e380ac-v1 ++ DEVICE_TITLE := COMFAST CF-E380AC v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath10k-ct ath10k-firmware-qca988x-ct \ ++ -swconfig -uboot-envtools ++ BOARDNAME := CF-E380AC-V1 ++ IMAGE_SIZE := 16128k ++ MTDPARTS := spi0.0:128k(u-boot)ro,64k(art)ro,16128k(firmware),64k(art-backup)ro ++endef ++TARGET_DEVICES += cf-e380ac-v1 ++ ++define Device/cf-e380ac-v2 ++ $(Device/cf-e380ac-v1) ++ DEVICE_TITLE := COMFAST CF-E380AC v2 ++ BOARDNAME := CF-E380AC-V2 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(art)ro,16000k(firmware),64k(art-backup)ro ++endef ++TARGET_DEVICES += cf-e380ac-v2 ++ ++define Device/cf-e385ac ++ DEVICE_TITLE := COMFAST CF-E385AC ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath10k-ct ath10k-firmware-qca9984-ct \ ++ -uboot-envtools ++ BOARDNAME := CF-E385AC ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(art)ro,16000k(firmware),64k(art-backup)ro ++endef ++TARGET_DEVICES += cf-e385ac ++ ++define Device/cf-e520n ++ DEVICE_TITLE := COMFAST CF-E520N ++ DEVICE_PACKAGES := kmod-usb2 -swconfig -uboot-envtools ++ BOARDNAME := CF-E520N ++ IMAGE_SIZE := 8000k ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(art)ro,8000k(firmware),64k(art-backup)ro ++endef ++TARGET_DEVICES += cf-e520n ++ ++define Device/cf-e530n ++ $(Device/cf-e520n) ++ DEVICE_TITLE := COMFAST CF-E530N ++ BOARDNAME := CF-E530N ++endef ++TARGET_DEVICES += cf-e530n ++ ++define Device/cpe505n ++ DEVICE_TITLE := P&W CPE505N ++ BOARDNAME := CPE505N ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += cpe505n ++ ++define Device/cpe830 ++ $(Device/ap90q) ++ DEVICE_TITLE := YunCore CPE830 ++ DEVICE_PACKAGES := rssileds ++ BOARDNAME := CPE830 ++endef ++TARGET_DEVICES += cpe830 ++ ++define Device/cpe870 ++ DEVICE_TITLE := YunCore CPE870 ++ DEVICE_PACKAGES := rssileds ++ BOARDNAME := CPE870 ++ IMAGE_SIZE := 7936k ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(u-boot-env),7936k(firmware),64k(config)ro,64k(art)ro ++endef ++TARGET_DEVICES += cpe870 ++ ++define Device/dragino2 ++ BOARDNAME := DRAGINO2 ++ CONSOLE := ttyATH0,115200 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ DEVICE_TITLE := Dragino 2 (MS14) ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,16000k(firmware),64k(config)ro,64k(art)ro ++endef ++TARGET_DEVICES += dragino2 ++ ++define Device/e1700ac-v2-16M ++ DEVICE_TITLE := Qxwlan E1700AC v2 (16MB flash) ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct \ ++ kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := E1700AC-V2 ++ SUPPORTED_DEVICES := e1700ac-v2 ++ IMAGE_SIZE := 15936k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(pri-data)ro,64k(art)ro,-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += e1700ac-v2-16M ++ ++define Device/e1700ac-v2-8M ++ $(Device/e1700ac-v2-16M) ++ DEVICE_TITLE := Qxwlan E1700AC v2 (8MB flash) ++ IMAGE_SIZE := 7744k ++endef ++TARGET_DEVICES += e1700ac-v2-8M ++ ++define Device/e558-v2-16M ++ DEVICE_TITLE := Qxwlan E558 v2 (16MB flash) ++ DEVICE_PACKAGES := kmod-usb2 -swconfig ++ BOARDNAME := E558-V2 ++ SUPPORTED_DEVICES := e558-v2 ++ IMAGE_SIZE := 15936k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(pri-data)ro,64k(art),-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += e558-v2-16M ++ ++define Device/e558-v2-8M ++ $(Device/e558-v2-16M) ++ DEVICE_TITLE := Qxwlan E558 v2 (8MB flash) ++ IMAGE_SIZE := 7744k ++endef ++TARGET_DEVICES += e558-v2-8M ++ ++define Device/e600g-v2-16M ++ DEVICE_TITLE := Qxwlan E600G v2 (16MB flash) ++ DEVICE_PACKAGES := kmod-usb2 -swconfig ++ BOARDNAME := E600G-V2 ++ SUPPORTED_DEVICES := e600g-v2 ++ IMAGE_SIZE := 15936k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(pri-data)ro,64k(art)ro,-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += e600g-v2-16M ++ ++define Device/e600g-v2-8M ++ $(Device/e600g-v2-16M) ++ DEVICE_TITLE := Qxwlan E600G v2 (8MB flash) ++ IMAGE_SIZE := 7744k ++endef ++TARGET_DEVICES += e600g-v2-8M ++ ++define Device/e600gac-v2-16M ++ DEVICE_TITLE := Qxwlan E600GAC v2 (16MB flash) ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9887-ct \ ++ kmod-usb2 -swconfig ++ BOARDNAME := E600GAC-V2 ++ SUPPORTED_DEVICES := e600gac-v2 ++ IMAGE_SIZE := 15936k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(pri-data)ro,64k(art)ro,-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += e600gac-v2-16M ++ ++define Device/e600gac-v2-8M ++ $(Device/e600gac-v2-16M) ++ DEVICE_TITLE := Qxwlan E600GAC v2 (8MB flash) ++ IMAGE_SIZE := 7744k ++endef ++TARGET_DEVICES += e600gac-v2-8M ++ ++define Device/e750a-v4-16M ++ DEVICE_TITLE := Qxwlan E750A v4 (16MB flash) ++ DEVICE_PACKAGES := kmod-usb2 -swconfig ++ BOARDNAME := E750A-V4 ++ SUPPORTED_DEVICES := e750a-v4 ++ IMAGE_SIZE := 15936k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(pri-data)ro,64k(art),-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += e750a-v4-16M ++ ++define Device/e750a-v4-8M ++ $(Device/e750a-v4-16M) ++ DEVICE_TITLE := Qxwlan E750A v4 (8MB flash) ++ IMAGE_SIZE := 7744k ++endef ++TARGET_DEVICES += e750a-v4-8M ++ ++define Device/e750g-v8-16M ++ DEVICE_TITLE := Qxwlan E750G v8 (16MB flash) ++ DEVICE_PACKAGES := kmod-usb2 -swconfig ++ BOARDNAME := E750G-V8 ++ SUPPORTED_DEVICES := e750g-v8 ++ IMAGE_SIZE := 15936k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(pri-data)ro,64k(art),-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += e750g-v8-16M ++ ++define Device/e750g-v8-8M ++ $(Device/e750g-v8-16M) ++ DEVICE_TITLE := Qxwlan E750G v8 (8MB flash) ++ IMAGE_SIZE := 7744k ++endef ++TARGET_DEVICES += e750g-v8-8M ++ ++define Device/ew-balin ++ DEVICE_TITLE := Embedded Wireless Balin Platform ++ DEVICE_PACKAGES := kmod-usb-chipidea ++ BOARDNAME := EW-BALIN ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += ew-balin ++ ++define Device/ew-dorin ++ $(Device/ew-balin) ++ DEVICE_TITLE := Embedded Wireless Dorin Platform ++ BOARDNAME := EW-DORIN ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += ew-dorin ++ ++define Device/ew-dorin-router ++ $(Device/ew-dorin) ++ DEVICE_TITLE := Embedded Wireless Dorin Router Platform ++ BOARDNAME := EW-DORIN-ROUTER ++endef ++TARGET_DEVICES += ew-dorin-router ++ ++define Device/rme-eg200 ++ DEVICE_TITLE := eTactica EG-200 ++ DEVICE_PACKAGES := kmod-usb2 kmod-ledtrig-oneshot \ ++ kmod-usb-serial kmod-usb-serial-ftdi \ ++ kmod-usb-storage \ ++ kmod-fs-ext4 ++ BOARDNAME := RME-EG200 ++ IMAGE_SIZE := 16000k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += rme-eg200 ++ ++define Device/weio ++ DEVICE_TITLE := WeIO ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := WEIO ++ IMAGE_SIZE := 16000k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += weio ++ ++define Device/gl-ar150 ++ DEVICE_TITLE := GL.iNet GL-AR150 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := GL-AR150 ++ IMAGE_SIZE := 16000k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += gl-ar150 ++ ++define Device/gl-ar300 ++ DEVICE_TITLE := GL.iNet GL-AR300 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := GL-AR300 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += gl-ar300 ++ ++define Device/gl-ar300m ++ DEVICE_TITLE := GL.iNet GL-AR300M ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := GL-AR300M ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += gl-ar300m ++ ++define Device/gl-ar750 ++ DEVICE_TITLE := GL.iNet GL-AR750 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9887-ct \ ++ kmod-usb2 kmod-usb-storage ++ BOARDNAME := GL-AR750 ++ SUPPORTED_DEVICES := gl-ar750 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(art)ro,-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += gl-ar750 ++ ++define Device/gl-ar750s ++ DEVICE_TITLE := GL.iNet GL-AR750S ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9887-ct \ ++ kmod-usb2 kmod-usb-storage ++ BOARDNAME := GL-AR750S ++ SUPPORTED_DEVICES := gl-ar750s ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(art)ro,-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += gl-ar750s ++ ++define Device/gl-domino ++ DEVICE_TITLE := GL.iNet Domino Pi ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := DOMINO ++ IMAGE_SIZE := 16000k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += gl-domino ++ ++define Device/gl-mifi ++ DEVICE_TITLE := GL.iNet GL-MiFi ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := GL-MIFI ++ IMAGE_SIZE := 16000k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += gl-mifi ++ ++define Device/gl-usb150 ++ DEVICE_TITLE := GL.iNet GL-USB150 ++ DEVICE_PACKAGES := -swconfig ++ BOARDNAME := GL-USB150 ++ IMAGE_SIZE := 16000k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++ SUPPORTED_DEVICES := gl-usb150 ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += gl-usb150 ++ ++define Device/lan-turtle ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := Hak5 LAN Turtle ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage \ ++ -kmod-ath9k -swconfig -uboot-envtools -wpad-basic ++ BOARDNAME := LAN-TURTLE ++ DEVICE_PROFILE := LANTURTLE ++ TPLINK_HWID := 0x5348334c ++ CONSOLE := ttyATH0,115200 ++ IMAGES := sysupgrade.bin ++endef ++TARGET_DEVICES += lan-turtle ++ ++define Device/lima ++ DEVICE_TITLE := 8devices Lima ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := LIMA ++ IMAGE_SIZE := 15616k ++ MTDPARTS := spi0.0:256k(u-boot)ro,256k(u-boot-env)ro,256k(art)ro,-(firmware) ++endef ++TARGET_DEVICES += lima ++ ++define Device/mr12 ++ DEVICE_TITLE := Meraki MR12 ++ DEVICE_PACKAGES := kmod-spi-gpio ++ BOARDNAME := MR12 ++ ROOTFS_SIZE := 13440k ++ IMAGE_SIZE := 15680k ++ MTDPARTS := spi0.0:256k(u-boot)ro,256k(u-boot-env)ro,13440k(rootfs),2240k(kernel),64k(mac),128k(art)ro,15680k@0x80000(firmware) ++ IMAGE/kernel.bin := append-kernel ++ IMAGE/rootfs.bin := append-rootfs | pad-rootfs ++ IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs | pad-to $$$$(ROOTFS_SIZE) | append-kernel | check-size $$$$(IMAGE_SIZE) ++ IMAGES := kernel.bin rootfs.bin sysupgrade.bin ++endef ++TARGET_DEVICES += mr12 ++ ++define Device/mr16 ++ $(Device/mr12) ++ DEVICE_TITLE := Meraki MR16 ++ BOARDNAME := MR16 ++endef ++TARGET_DEVICES += mr16 ++ ++define Device/dr342 ++ DEVICE_TITLE := Wallys DR342 ++ DEVICE_PACKAGES := kmod-usb2 -swconfig ++ BOARDNAME := DR342 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:192k(u-boot)ro,64k(u-boot-env),64k(partition-table)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += dr342 ++ ++define Device/dr344 ++ DEVICE_TITLE := Wallys DR344 ++ BOARDNAME := DR344 ++ KERNEL_SIZE := 1408k ++ ROOTFS_SIZE := 6336k ++ IMAGE_SIZE := 7744k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6336k(rootfs),1408k(kernel),64k(nvram),64k(art)ro,7744k@0x50000(firmware) ++ IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs | pad-to $$$$(ROOTFS_SIZE) | append-kernel | check-size $$$$(IMAGE_SIZE) ++endef ++ ++define Device/dr531 ++ DEVICE_TITLE := Wallys DR531 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := DR531 ++ IMAGE_SIZE := 7808k ++ MTDPARTS := spi0.0:192k(u-boot)ro,64k(u-boot-env),64k(partition-table)ro,7808k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += dr531 ++ ++define Device/wndr3700 ++ DEVICE_TITLE := NETGEAR WNDR3700 ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport kmod-leds-wndr3700-usb ++ BOARDNAME := WNDR3700 ++ NETGEAR_KERNEL_MAGIC := 0x33373030 ++ NETGEAR_BOARD_ID := WNDR3700 ++ IMAGE_SIZE := 7680k ++ MTDPARTS := spi0.0:320k(u-boot)ro,128k(u-boot-env)ro,7680k(firmware),64k(art)ro ++ IMAGES := sysupgrade.bin factory.img factory-NA.img ++ KERNEL := kernel-bin | patch-cmdline | lzma -d20 | netgear-uImage lzma ++ IMAGE/default := append-kernel | pad-to $$$$(BLOCKSIZE) | netgear-squashfs | append-rootfs | pad-rootfs ++ IMAGE/sysupgrade.bin := $$(IMAGE/default) | check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory.img := $$(IMAGE/default) | netgear-dni | check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory-NA.img := $$(IMAGE/default) | netgear-dni NA | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += wndr3700 ++ ++define Device/wndr3700v2 ++ $(Device/wndr3700) ++ DEVICE_TITLE := NETGEAR WNDR3700 v2 ++ NETGEAR_BOARD_ID := WNDR3700v2 ++ NETGEAR_KERNEL_MAGIC := 0x33373031 ++ NETGEAR_HW_ID := 29763654+16+64 ++ IMAGE_SIZE := 15872k ++ MTDPARTS := spi0.0:320k(u-boot)ro,128k(u-boot-env)ro,15872k(firmware),64k(art)ro ++ IMAGES := sysupgrade.bin factory.img ++endef ++TARGET_DEVICES += wndr3700v2 ++ ++define Device/wndr3800 ++ $(Device/wndr3700v2) ++ DEVICE_TITLE := NETGEAR WNDR3800 ++ NETGEAR_BOARD_ID := WNDR3800 ++ NETGEAR_HW_ID := 29763654+16+128 ++endef ++TARGET_DEVICES += wndr3800 ++ ++define Device/wndr3800ch ++ $(Device/wndr3800) ++ DEVICE_TITLE := NETGEAR WNDR3800 (Ch) ++ NETGEAR_BOARD_ID := WNDR3800CH ++endef ++TARGET_DEVICES += wndr3800ch ++ ++define Device/wndrmac ++ $(Device/wndr3700v2) ++ DEVICE_TITLE := NETGEAR WNDRMAC ++ NETGEAR_BOARD_ID := WNDRMAC ++endef ++TARGET_DEVICES += wndrmac ++ ++define Device/wndrmacv2 ++ $(Device/wndr3800) ++ DEVICE_TITLE := NETGEAR WNDRMAC v2 ++ NETGEAR_BOARD_ID := WNDRMACv2 ++endef ++TARGET_DEVICES += wndrmacv2 ++ ++define Device/cap324 ++ DEVICE_TITLE := PowerCloud Systems CAP324 ++ BOARDNAME := CAP324 ++ DEVICE_PROFILE := CAP324 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += cap324 ++ ++define Device/cr3000 ++ DEVICE_TITLE := PowerCloud Systems CR3000 ++ BOARDNAME := CR3000 ++ DEVICE_PROFILE := CR3000 ++ IMAGE_SIZE := 7808k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,7808k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += cr3000 ++ ++define Device/cr5000 ++ DEVICE_TITLE := PowerCloud Systems CR5000 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := CR5000 ++ DEVICE_PROFILE := CR5000 ++ IMAGE_SIZE := 7808k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,7808k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += cr5000 ++ ++define Device/packet-squirrel ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := Hak5 Packet Squirrel ++ DEVICE_PACKAGES := kmod-usb2 \ ++ -kmod-ath9k -swconfig -uboot-envtools -wpad-basic ++ BOARDNAME := PACKET-SQUIRREL ++ DEVICE_PROFILE := PACKETSQUIRREL ++ TPLINK_HWID := 0x5351524c ++ CONSOLE := ttyATH0,115200 ++ IMAGES := sysupgrade.bin ++endef ++TARGET_DEVICES += packet-squirrel ++ ++define Device/pqi-air-pen ++ DEVICE_TITLE := PQI Air Pen ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++ BOARDNAME := PQI-AIR-PEN ++ IMAGE_SIZE := 7744k ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,64k(art)ro,64k(NVRAM)ro,7680k(firmware),64k(CONF) ++endef ++TARGET_DEVICES += pqi-air-pen ++ ++define Device/antminer-s1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := Antminer-S1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-crypto-manager kmod-i2c-gpio-custom kmod-usb-hid ++ BOARDNAME := ANTMINER-S1 ++ DEVICE_PROFILE := ANTMINERS1 ++ TPLINK_HWID := 0x04440101 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += antminer-s1 ++ ++define Device/antminer-s3 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := Antminer-S3 ++ DEVICE_PACKAGES := kmod-usb2 kmod-crypto-manager kmod-i2c-gpio-custom kmod-usb-hid ++ BOARDNAME := ANTMINER-S3 ++ DEVICE_PROFILE := ANTMINERS3 ++ TPLINK_HWID := 0x04440301 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += antminer-s3 ++ ++define Device/antrouter-r1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := Antrouter-R1 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := ANTROUTER-R1 ++ DEVICE_PROFILE := ANTROUTERR1 ++ TPLINK_HWID := 0x44440101 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += antrouter-r1 ++ ++define Device/el-m150 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := EasyLink EL-M150 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := EL-M150 ++ DEVICE_PROFILE := ELM150 ++ TPLINK_HWID := 0x01500101 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += el-m150 ++ ++define Device/el-mini ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := EasyLink EL-MINI ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := EL-MINI ++ DEVICE_PROFILE := ELMINI ++ TPLINK_HWID := 0x01530001 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += el-mini ++ ++define Device/gl-inet-6408A-v1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := GL.iNet 6408 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := GL-INET ++ DEVICE_PROFILE := GLINET ++ TPLINK_HWID := 0x08000001 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += gl-inet-6408A-v1 ++ ++define Device/gl-inet-6416A-v1 ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := GL.iNet 6416 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := GL-INET ++ DEVICE_PROFILE := GLINET ++ TPLINK_HWID := 0x08000001 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += gl-inet-6416A-v1 ++ ++define Device/jwap230 ++ DEVICE_TITLE := jjPlus JWAP230 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := JWAP230 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += jwap230 ++ ++define Device/koala ++ DEVICE_TITLE := OCEDO Koala ++ BOARDNAME := KOALA ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ IMAGE_SIZE := 7424k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),7424k(firmware),1536k(kernel2),5888k(rootfs2),1088k(data)ro,64k(id)ro,64k(art)ro ++endef ++TARGET_DEVICES += koala ++ ++define Device/r36a ++ DEVICE_TITLE := ALFA Network R36A ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport -swconfig ++ BOARDNAME := R36A ++ SUPPORTED_DEVICES := r36a ++ IMAGE_SIZE := 15872k ++ MTDPARTS := spi0.0:384k(u-boot)ro,64k(u-boot-env),64k(art)ro,-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += r36a ++ ++define Device/r602n ++ DEVICE_TITLE := P&W R602N ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := R602N ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += r602n ++ ++define Device/rut900 ++ DEVICE_TITLE := Teltonika RUT900 ++ DEVICE_PACKAGES := kmod-usb2 -uboot-envtools ++ BOARDNAME := RUT900 ++ SUPPORTED_DEVICES := rut900 ++ IMAGE_SIZE := 15552k ++ MTDPARTS := spi0.0:128k(u-boot)ro,64k(config)ro,64k(art)ro,15552k(firmware),576k(event-log)ro ++ TPLINK_HWID := 0x35000001 ++ TPLINK_HWREV := 0x1 ++ TPLINK_HEADER_VERSION := 1 ++ KERNEL := kernel-bin | patch-cmdline | lzma | tplink-v1-header ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | uImage lzma ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/factory.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs |\ ++ pad-rootfs | teltonika-fw-fake-checksum | append-string master |\ ++ append-md5sum-bin | check-size $$$$(IMAGE_SIZE) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata |\ ++ check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += rut900 ++ ++define Device/mc-mac1200r ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := Mercury MAC1200R ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := MC-MAC1200R ++ DEVICE_PROFILE := MAC1200R ++ TPLINK_HWID := 0x12000001 ++endef ++TARGET_DEVICES += mc-mac1200r ++ ++define Device/minibox-v1 ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := GainStrong MiniBox V1.0 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := MINIBOX-V1 ++ DEVICE_PROFILE := MINIBOXV1 ++ TPLINK_HWID := 0x3C000201 ++ CONSOLE := ttyATH0,115200 ++ IMAGES := sysupgrade.bin ++endef ++TARGET_DEVICES += minibox-v1 ++ ++define Device/minibox-v3.2 ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := Gainstrong MiniBox V3.2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca9887-ct -swconfig ++ BOARDNAME := MINIBOX-V3.2 ++ DEVICE_PROFILE := MINIBOXV32 ++ TPLINK_HWID := 0x3C00010C ++endef ++TARGET_DEVICES += minibox-v3.2 ++ ++define Device/oolite-v1 ++ $(Device/minibox-v1) ++ DEVICE_TITLE := GainStrong Oolite V1.0 ++ BOARDNAME := OOLITE-V1 ++ DEVICE_PROFILE := OOLITEV1 ++ TPLINK_HWID := 0x3C000101 ++endef ++TARGET_DEVICES += oolite-v1 ++ ++define Device/oolite-v5.2 ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := GainStrong Oolite V5.2 ++ DEVICE_PACKAGES := ath10k-firmware-qca9887-ct kmod-ath10k-ct kmod-usb2 ++ BOARDNAME := OOLITE-V5-2 ++ DEVICE_PROFILE := OOLITEV52 ++ TPLINK_HWID := 0x3C00010B ++ IMAGES := sysupgrade.bin ++endef ++TARGET_DEVICES += oolite-v5.2 ++ ++define Device/oolite-v5.2-dev ++ $(Device/oolite-v5.2) ++ DEVICE_TITLE := GainStrong Oolite V5.2-Dev (development board) ++ BOARDNAME := OOLITE-V5-2-DEV ++ DEVICE_PROFILE := OOLITEV52DEV ++endef ++TARGET_DEVICES += oolite-v5.2-dev ++ ++define Device/omy-g1 ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := OMYlink OMY-G1 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := OMY-G1 ++ DEVICE_PROFILE := OMYG1 ++ TPLINK_HWID := 0x06660101 ++endef ++TARGET_DEVICES += omy-g1 ++ ++define Device/omy-x1 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := OMYlink OMY-X1 ++ BOARDNAME := OMY-X1 ++ DEVICE_PROFILE := OMYX1 ++ TPLINK_HWID := 0x06660201 ++endef ++TARGET_DEVICES += omy-x1 ++ ++define Device/onion-omega ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := Onion Omega ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage kmod-i2c-core kmod-i2c-gpio-custom kmod-spi-bitbang kmod-spi-dev kmod-spi-gpio kmod-spi-gpio-custom kmod-usb-serial ++ BOARDNAME := ONION-OMEGA ++ DEVICE_PROFILE := OMEGA ++ TPLINK_HWID := 0x04700001 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += onion-omega ++ ++define Device/sc1750 ++ DEVICE_TITLE := Abicom SC1750 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := SC1750 ++ IMAGE_SIZE := 15744k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),15744k(firmware),128k(APConfig),128k(kplog),64k(ART) ++endef ++TARGET_DEVICES += sc1750 ++ ++define Device/sc300m ++ DEVICE_TITLE := Abicom SC300M ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := SC300M ++ IMAGE_SIZE := 15744k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),15744k(firmware),128k(APConfig),128k(kplog),64k(ART) ++endef ++TARGET_DEVICES += sc300m ++ ++define Device/sc450 ++ DEVICE_TITLE := Abicom SC450 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := SC450 ++ IMAGE_SIZE := 15744k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),15744k(firmware),128k(APConfig),128k(kplog),64k(ART) ++endef ++TARGET_DEVICES += sc450 ++ ++define Device/smart-300 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := NC-LINK SMART-300 ++ BOARDNAME := SMART-300 ++ DEVICE_PROFILE := SMART-300 ++ TPLINK_HWID := 0x93410001 ++endef ++TARGET_DEVICES += smart-300 ++ ++define Device/som9331 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := OpenEmbed SOM9331 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage kmod-i2c-core kmod-i2c-gpio-custom kmod-spi-bitbang kmod-spi-dev kmod-spi-gpio kmod-spi-gpio-custom kmod-usb-serial ++ BOARDNAME := SOM9331 ++ DEVICE_PROFILE := SOM9331 ++ TPLINK_HWID := 0x04800054 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += som9331 ++ ++define Device/sr3200 ++ DEVICE_TITLE := YunCore SR3200 ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := SR3200 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++endef ++TARGET_DEVICES += sr3200 ++ ++define Device/xd3200 ++ $(Device/sr3200) ++ DEVICE_TITLE := YunCore XD3200 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := XD3200 ++endef ++TARGET_DEVICES += xd3200 ++ ++define Device/t830 ++ DEVICE_TITLE := YunCore T830 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := T830 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro ++ SUPPORTED_DEVICES := t830 ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += t830 ++ ++define Device/tellstick-znet-lite ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := TellStick ZNet Lite ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-acm kmod-usb-serial kmod-usb-serial-pl2303 ++ BOARDNAME := TELLSTICK-ZNET-LITE ++ DEVICE_PROFILE := TELLSTICKZNETLITE ++ TPLINK_HWID := 0x00726001 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tellstick-znet-lite ++ ++define Device/ts-d084 ++ $(Device/tplink-8mlzma) ++ DEVICE_TITLE := PISEN TS-D084 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := TS-D084 ++ DEVICE_PROFILE := TSD084 ++ TPLINK_HWID := 0x07030101 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += ts-d084 ++ ++define Device/n5q ++ DEVICE_TITLE := ALFA Network N5Q ++ DEVICE_PACKAGES := rssileds -swconfig ++ BOARDNAME := N5Q ++ SUPPORTED_DEVICES := n5q ++ IMAGE_SIZE := 15872k ++ MTDPARTS := spi0.0:384k(u-boot)ro,64k(u-boot-env),64k(art)ro,-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += n5q ++ ++define Device/NBG6616 ++ DEVICE_TITLE := ZyXEL NBG6616 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-usb-storage kmod-rtc-pcf8563 kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := NBG6616 ++ KERNEL_SIZE := 2048k ++ IMAGE_SIZE := 15323k ++ MTDPARTS := spi0.0:192k(u-boot)ro,64k(env),64k(RFdata)ro,384k(zyxel_rfsd),384k(romd),64k(header),2048k(kernel),13184k(rootfs),15232k@0x120000(firmware) ++ CMDLINE += mem=128M ++ RAS_BOARD := NBG6616 ++ RAS_ROOTFS_SIZE := 14464k ++ RAS_VERSION := "$(VERSION_DIST) $(REVISION)" ++ IMAGES := factory.bin sysupgrade.bin ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImage lzma | jffs2 boot/vmlinux.lzma.uImage ++ IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | pad-to 64k | check-size $$$$(IMAGE_SIZE) | zyxel-ras-image ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) ++ # We cannot currently build a factory image. It is the sysupgrade image ++ # prefixed with a header (which is actually written into the MTD device). ++ # The header is 2kiB and is filled with 0xff. The format seems to be: ++ # 2 bytes: 0x0000 ++ # 2 bytes: checksum of the data partition (big endian) ++ # 4 bytes: length of the contained image file (big endian) ++ # 32 bytes: Firmware Version string (NUL terminated, 0xff padded) ++ # 2 bytes: 0x0000 ++ # 2 bytes: checksum over the header partition (big endian) ++ # 32 bytes: Model (e.g. "NBG6616", NUL termiated, 0xff padded) ++ # rest: 0xff padding ++ # ++ # The checksums are calculated by adding up all bytes and if a 16bit ++ # overflow occurs, one is added and the sum is masked to 16 bit: ++ # csum = csum + databyte; if (csum > 0xffff) { csum += 1; csum &= 0xffff }; ++ # Should the file have an odd number of bytes then the byte len-0x800 is ++ # used additionally. ++ # The checksum for the header is calcualted over the first 2048 bytes with ++ # the firmware checksum as the placeholder during calculation. ++ # ++ # The header is padded with 0xff to the erase block size of the device. ++endef ++TARGET_DEVICES += NBG6616 ++ ++define Device/c-55 ++ DEVICE_TITLE := AirTight Networks C-55 ++ DEVICE_PACKAGES := kmod-ath9k ++ BOARDNAME := C-55 ++ KERNEL_SIZE := 2048k ++ IMAGE_SIZE := 15872k ++ MTDPARTS := spi0.0:256k(u-boot)ro,128k(u-boot-env)ro,2048k(kernel),13824k(rootfs),13824k(opt)ro,2624k(failsafe)ro,64k(art)ro,15872k@0x60000(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += c-55 ++ ++define Device/hiwifi-hc6361 ++ DEVICE_TITLE := HiWiFi HC6361 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage \ ++ kmod-fs-ext4 kmod-nls-iso8859-1 e2fsprogs ++ BOARDNAME := HiWiFi-HC6361 ++ DEVICE_PROFILE := HIWIFI_HC6361 ++ IMAGE_SIZE := 16128k ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImageHiWiFi lzma ++ CONSOLE := ttyATH0,115200 ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(bdinfo)ro,16128k(firmware),64k(backup)ro,64k(art)ro ++endef ++TARGET_DEVICES += hiwifi-hc6361 ++ ++define Device/seama ++ LOADER_TYPE := bin ++ BLOCKSIZE := 64k ++ KERNEL := kernel-bin | patch-cmdline | relocate-kernel | lzma ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | lzma | seama ++ KERNEL_INITRAMFS_SUFFIX = $$(KERNEL_SUFFIX).seama ++ SEAMA_MTDBLOCK := 1 ++ IMAGES := sysupgrade.bin factory.bin ++ ++ # 64 bytes offset: ++ # - 28 bytes seama_header ++ # - 36 bytes of META data (4-bytes aligned) ++ IMAGE/default := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | append-rootfs ++ IMAGE/sysupgrade.bin := \ ++ $$(IMAGE/default) | seama | pad-rootfs | \ ++ check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory.bin := \ ++ $$(IMAGE/default) | seama | pad-rootfs | \ ++ seama-seal | check-size $$$$(IMAGE_SIZE) ++ SEAMA_SIGNATURE := ++endef ++ ++define Device/dir-869-a1 ++ $(Device/seama) ++ DEVICE_TITLE := D-Link DIR-869 rev. A1 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := DIR-869-A1 ++ IMAGE_SIZE := 15872k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,64k(devdata)ro,64k(devconf)ro,15872k(firmware),64k(radiocfg)ro ++ SEAMA_SIGNATURE := wrgac54_dlink.2015_dir869 ++ IMAGE/factory.bin := \ ++ $$(IMAGE/default) | pad-rootfs -x 64 | \ ++ seama | seama-seal -m "signature=$$$$(SEAMA_SIGNATURE)" | \ ++ check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += dir-869-a1 ++ ++define Device/mynet-n600 ++ $(Device/seama) ++ DEVICE_TITLE := Western Digital My Net N600 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := MYNET-N600 ++ IMAGE_SIZE := 15808k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,64k(devdata)ro,64k(devconf)ro,15872k(firmware),64k(radiocfg)ro ++ SEAMA_SIGNATURE := wrgnd16_wd_db600 ++endef ++TARGET_DEVICES += mynet-n600 ++ ++define Device/mynet-n750 ++ $(Device/seama) ++ DEVICE_TITLE := Western Digital My Net N750 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := MYNET-N750 ++ IMAGE_SIZE := 15808k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,64k(devdata)ro,64k(devconf)ro,15872k(firmware),64k(radiocfg)ro ++ SEAMA_SIGNATURE := wrgnd13_wd_av ++endef ++TARGET_DEVICES += mynet-n750 ++ ++define Device/qihoo-c301 ++ $(Device/seama) ++ DEVICE_TITLE := Qihoo C301 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := QIHOO-C301 ++ IMAGE_SIZE := 15744k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(devdata),64k(devconf),15744k(firmware),64k(warm_start),64k(action_image_config),64k(radiocfg)ro;spi0.1:15360k(upgrade2),1024k(privatedata) ++ SEAMA_SIGNATURE := wrgac26_qihoo360_360rg ++endef ++TARGET_DEVICES += qihoo-c301 ++ ++define Device/dap-1330-a1 ++ DEVICE_TITLE := D-Link DAP-1330 rev. A1 ++ DEVICE_PACKAGES := rssileds ++ BOARDNAME := DAP-1330-A1 ++ IMAGES := factory.img sysupgrade.bin ++ IMAGE_SIZE := 7936k ++ IMAGE/factory.img := append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) | mkdapimg2 917504 ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(art)ro,64k(mp)ro,64k(config)ro,7936k(firmware) ++ DAP_SIGNATURE := HONEYBEE-FIRMWARE-DAP-1330 ++endef ++TARGET_DEVICES += dap-1330-a1 ++ ++define Device/dap-2695-a1 ++ DEVICE_TITLE := D-Link DAP-2695 rev. A1 ++ DEVICE_PACKAGES := ath10k-firmware-qca988x-ct kmod-ath10k-ct ++ BOARDNAME := DAP-2695-A1 ++ IMAGES := factory.img sysupgrade.bin ++ IMAGE_SIZE := 15360k ++ IMAGE/factory.img := append-kernel | pad-offset 65536 160 | append-rootfs | wrgg-pad-rootfs | mkwrggimg | check-size $$$$(IMAGE_SIZE) ++ IMAGE/sysupgrade.bin := append-kernel | pad-offset 65536 160 | mkwrggimg | append-rootfs | wrgg-pad-rootfs | check-size $$$$(IMAGE_SIZE) ++ KERNEL := kernel-bin | patch-cmdline | relocate-kernel | lzma ++ KERNEL_INITRAMFS := $$(KERNEL) | mkwrggimg ++ MTDPARTS := spi0.0:256k(bootloader)ro,64k(bdcfg)ro,64k(rgdb)ro,64k(langpack)ro,15360k(firmware),448k(captival)ro,64k(certificate)ro,64k(radiocfg)ro ++ DAP_SIGNATURE := wapac02_dkbs_dap2695 ++endef ++TARGET_DEVICES += dap-2695-a1 ++ ++define Device/wam250 ++ DEVICE_TITLE := Samsung WAM250 ++ DEVICE_PACKAGES := kmod-usb2 -swconfig ++ BOARDNAME := WAM250 ++ IMAGE_SIZE := 15872k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),128k(nvram)ro,15872k(firmware),64k(art)ro ++ SUPPORTED_DEVICES := wam250 ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) |\ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += wam250 ++ ++define Device/wifi-pineapple-nano ++ $(Device/tplink-16mlzma) ++ DEVICE_TITLE := Hak5 WiFi Pineapple NANO ++ DEVICE_PACKAGES := kmod-ath9k-htc kmod-usb2 kmod-usb-storage \ ++ -swconfig -uboot-envtools ++ BOARDNAME := WIFI-PINEAPPLE-NANO ++ DEVICE_PROFILE := WIFIPINEAPPLENANO ++ TPLINK_HWID := 0x4e414e4f ++ CONSOLE := ttyATH0,115200 ++ IMAGES := sysupgrade.bin ++endef ++TARGET_DEVICES += wifi-pineapple-nano ++ ++define Device/wlr8100 ++ DEVICE_TITLE := Sitecom WLR-8100 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-usb3 \ ++ kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := WLR8100 ++ IMAGE_SIZE := 15424k ++ MTDPARTS := spi0.0:192k(u-boot)ro,64k(u-boot-env)ro,15424k(firmware),256k(manufacture)ro,64k(backup)ro,320k(storage)ro,64k(art)ro ++endef ++TARGET_DEVICES += wlr8100 ++ ++define Device/wpj-16m ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ MTDPARTS := spi0.0:192k(u-boot)ro,16128k(firmware),64k(art)ro ++ IMAGE_SIZE := 16128k ++endef ++ ++define Device/wpj342 ++ $(Device/wpj-16m) ++ DEVICE_TITLE := Compex WPJ342 (16MB flash) ++ BOARDNAME := WPJ342 ++endef ++TARGET_DEVICES += wpj342 ++ ++define Device/wpj344 ++ $(Device/wpj-16m) ++ DEVICE_TITLE := Compex WPJ344 (16MB flash) ++ BOARDNAME := WPJ344 ++ SUPPORTED_DEVICES := wpj344 ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += wpj344 ++ ++define Device/wpj531 ++ $(Device/wpj-16m) ++ DEVICE_TITLE := Compex WPJ531 (16MB flash) ++ BOARDNAME := WPJ531 ++endef ++TARGET_DEVICES += wpj531 ++ ++define Device/wpj558 ++ $(Device/wpj-16m) ++ DEVICE_TITLE := Compex WPJ558 (16MB flash) ++ BOARDNAME := WPJ558 ++ SUPPORTED_DEVICES := wpj558 ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += wpj558 ++ ++define Device/wpj563 ++ $(Device/wpj-16m) ++ DEVICE_TITLE := Compex WPJ563 (16MB flash) ++ BOARDNAME := WPJ563 ++endef ++TARGET_DEVICES += wpj563 ++ ++define Device/wrtnode2q ++ DEVICE_TITLE := WRTnode2Q ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage ++ BOARDNAME := WRTNODE2Q ++ IMAGE_SIZE := 16064k ++ MTDPARTS := spi0.0:192k(u-boot)ro,64k(u-boot-env),64k(art)ro,16064k(firmware),16384k@0x0(fullflash) ++endef ++TARGET_DEVICES += wrtnode2q ++ ++define Device/AVM ++ DEVICE_PACKAGES := fritz-tffs -uboot-envtools ++ KERNEL := kernel-bin | patch-cmdline | lzma | eva-image ++ KERNEL_INITRAMFS := $$(KERNEL) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to 64k | \ ++ append-squashfs-fakeroot-be | pad-to 256 | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++ ++define Device/fritz300e ++ $(call Device/AVM) ++ DEVICE_TITLE := AVM FRITZ!WLAN Repeater 300E ++ DEVICE_PACKAGES += rssileds -swconfig ++ BOARDNAME := FRITZ300E ++ SUPPORTED_DEVICES := fritz300e ++ IMAGE_SIZE := 15232k ++endef ++TARGET_DEVICES += fritz300e ++ ++define Device/fritz4020 ++ $(call Device/AVM) ++ DEVICE_TITLE := AVM FRITZ!Box 4020 ++ DEVICE_PACKAGES += kmod-usb2 kmod-usb-storage ++ BOARDNAME := FRITZ4020 ++ SUPPORTED_DEVICES := fritz4020 ++ IMAGE_SIZE := 15232k ++endef ++TARGET_DEVICES += fritz4020 ++ ++define Device/fritz450e ++ $(call Device/AVM) ++ DEVICE_TITLE := AVM FRITZ!WLAN Repeater 450E ++ DEVICE_PACKAGES += -swconfig ++ BOARDNAME := FRITZ450E ++ SUPPORTED_DEVICES := fritz450e ++ IMAGE_SIZE := 15232k ++endef ++TARGET_DEVICES += fritz450e +diff --git a/target/linux/ar71xx/image/legacy.mk b/target/linux/ar71xx/image/legacy.mk +new file mode 100644 +index 0000000000..926ce780b4 +--- /dev/null ++++ b/target/linux/ar71xx/image/legacy.mk +@@ -0,0 +1,1059 @@ ++rootfs_type=$(patsubst squashfs-%,squashfs,$(1)) ++ ++# $(1): rootfs type. ++# $(2): board name. ++define imgname ++$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(call rootfs_type,$(1)) ++endef ++ ++define rootfs_align ++$(patsubst %-256k,0x40000,$(patsubst %-128k,0x20000,$(patsubst %-64k,0x10000,$(patsubst squashfs%,0x4,$(patsubst root.%,%,$(1)))))) ++endef ++ ++define sysupname ++$(call imgname,$(1),$(2))-sysupgrade.bin ++endef ++ ++define factoryname ++$(call imgname,$(1),$(2))-factory.bin ++endef ++ ++COMMA:=, ++ ++define mkcmdline ++$(if $(1),board=$(1) )$(if $(2),console=$(2)$(COMMA)$(3)) ++endef ++ ++define mtdpartsize ++$(shell sz=`echo '$(2)' | sed -ne 's/.*[:$(COMMA)]\([0-9]*\)k[@]*[0-9a-zx]*($(1)).*/\1/p'`; [ -n "$$sz" ] && echo $$(($$sz * 1024))) ++endef ++ ++# $(1) : name of image build method to be used, e.g., AthLzma. ++# $(2) : name of the build template to be used, e.g. 64k, 64kraw, 128k, etc. ++# $(3) : name of the profile to be defined. ++# $(4) : board name. ++# $(5)~$(7) : arguments for $(mkcmdline) ++# board=$(1) console=$(2),$(3) ++# $(8)~$(14): extra arguments. ++define SingleProfile ++ # $(1): action name, e.g. loader, buildkernel, squashfs, etc. ++ define Image/Build/Profile/$(3) ++ $$(call Image/Build/Template/$(2)/$$(1),$(1),$(4),$$(call mkcmdline,$(5),$(6),$(7)),$(8),$(9),$(10),$(11),$(12),$(13),$(14)) ++ endef ++endef ++ ++LOADER_MAKE := $(NO_TRACE_MAKE) -C lzma-loader KDIR=$(KDIR) ++ ++VMLINUX:=$(BIN_DIR)/$(IMG_PREFIX)-vmlinux ++UIMAGE:=$(BIN_DIR)/$(IMG_PREFIX)-uImage ++ ++# $(1): input file. ++# $(2): output file. ++# $(3): extra arguments for lzma. ++define CompressLzma ++ $(STAGING_DIR_HOST)/bin/lzma e $(1) -lc1 -lp2 -pb2 $(3) $(2) ++endef ++ ++define PatchKernel ++ cp $(KDIR)/vmlinux$(3) $(KDIR_TMP)/vmlinux$(3)-$(1) ++ $(STAGING_DIR_HOST)/bin/patch-cmdline $(KDIR_TMP)/vmlinux$(3)-$(1) "$(strip $(2))" ++endef ++ ++define PatchKernel/initramfs ++ $(call PatchKernel,$(1),$(2),-initramfs) ++ cp $(KDIR_TMP)/vmlinux-initramfs-$(1) $(call imgname,initramfs,$(1)).bin ++endef ++ ++# $(1): board name. ++# $(2): kernel command line. ++# $(3): extra argumetns for lzma. ++# $(4): name suffix, e.g. "-initramfs". ++define PatchKernelLzma ++ cp $(KDIR)/vmlinux$(4) $(KDIR_TMP)/vmlinux$(4)-$(1) ++ $(STAGING_DIR_HOST)/bin/patch-cmdline $(KDIR_TMP)/vmlinux$(4)-$(1) "$(strip $(2))" ++ $(call CompressLzma,$(KDIR_TMP)/vmlinux$(4)-$(1),$(KDIR_TMP)/vmlinux$(4)-$(1).bin.lzma,$(3)) ++endef ++ ++define PatchKernelGzip ++ cp $(KDIR)/vmlinux$(3) $(KDIR_TMP)/vmlinux$(3)-$(1) ++ $(STAGING_DIR_HOST)/bin/patch-cmdline $(KDIR_TMP)/vmlinux$(3)-$(1) "$(strip $(2))" ++ gzip -9n -c $(KDIR_TMP)/vmlinux$(3)-$(1) > $(KDIR_TMP)/vmlinux$(3)-$(1).bin.gz ++endef ++ ++ifneq ($(SUBTARGET),mikrotik) ++# $(1): compression method of the data. ++# $(2): extra arguments. ++# $(3): input data file. ++# $(4): output file. ++define MkuImage ++ mkimage -A mips -O linux -T kernel -a 0x80060000 -C $(1) $(2) \ ++ -e 0x80060000 -n 'MIPS $(VERSION_DIST) Linux-$(LINUX_VERSION)' \ ++ -d $(3) $(4) ++endef ++ ++# $(1): board name. ++# $(2): kernel command line. ++# $(3): extra arguments for lzma. ++# $(4): name suffix, e.g. "-initramfs". ++# $(5): extra arguments for mkimage. ++define MkuImageLzma ++ $(call PatchKernelLzma,$(1),$(2),$(3),$(4)) ++ $(call MkuImage,lzma,$(5),$(KDIR_TMP)/vmlinux$(4)-$(1).bin.lzma,$(KDIR_TMP)/vmlinux$(4)-$(1).uImage) ++endef ++ ++define MkuImageLzma/initramfs ++ $(call PatchKernelLzma,$(1),$(2),$(3),-initramfs) ++ $(call MkuImage,lzma,$(4),$(KDIR_TMP)/vmlinux-initramfs-$(1).bin.lzma,$(call imgname,initramfs,$(1))-uImage.bin) ++endef ++ ++define MkuImageGzip ++ $(call PatchKernelGzip,$(1),$(2)) ++ $(call MkuImage,gzip,,$(KDIR_TMP)/vmlinux-$(1).bin.gz,$(KDIR_TMP)/vmlinux-$(1).uImage) ++endef ++ ++define MkuImageGzip/initramfs ++ $(call PatchKernelGzip,$(1),$(2),-initramfs) ++ $(call MkuImage,gzip,,$(KDIR_TMP)/vmlinux-initramfs-$(1).bin.gz,$(call imgname,initramfs,$(1))-uImage.bin) ++endef ++ ++define MkuImageOKLI ++ $(call MkuImage,lzma,-M 0x4f4b4c49,$(KDIR)/vmlinux.bin.lzma,$(KDIR_TMP)/vmlinux-$(1).okli) ++endef ++endif ++ ++# $(1): name of the 1st file. ++# $(2): size limit of the 1st file if it is greater than 262144, or ++# the erase size of the flash if it is greater than zero and less ++# than 262144 ++# $(3): name of the 2nd file. ++# $(4): size limit of the 2nd file if $(2) is greater than 262144, otherwise ++# it is the size limit of the output file ++# $(5): name of the output file. ++# $(6): padding size. ++define CatFiles ++ if [ $(2) -eq 0 ]; then \ ++ filename="$(3)"; fstype=$${filename##*\.}; \ ++ case "$${fstype}" in \ ++ *) bs=`stat -c%s $(1)`;; \ ++ esac; \ ++ ( dd if=$(1) bs=$${bs} conv=sync; cat $(3) ) > $(5); \ ++ if [ -n "$(6)" ]; then \ ++ case "$${fstype}" in \ ++ squashfs*) \ ++ padjffs2 $(5) $(6); \ ++ ;; \ ++ esac; \ ++ fi; \ ++ if [ `stat -c%s $(5)` -gt $(4) ]; then \ ++ echo "Warning: $(5) is too big (> $(4) bytes)" >&2; \ ++ rm -f $(5); \ ++ fi; \ ++ else if [ $(2) -gt 262144 ]; then \ ++ if [ `stat -c%s "$(1)"` -gt $(2) ]; then \ ++ echo "Warning: $(1) is too big (> $(2) bytes)" >&2; \ ++ else if [ `stat -c%s $(3)` -gt $(4) ]; then \ ++ echo "Warning: $(3) is too big (> $(4) bytes)" >&2; \ ++ else \ ++ ( dd if=$(1) bs=$(2) conv=sync; dd if=$(3) ) > $(5); \ ++ fi; fi; \ ++ else \ ++ ( dd if=$(1) bs=$(2) conv=sync; dd if=$(3) ) > $(5); \ ++ if [ `stat -c%s $(5)` -gt $(4) ]; then \ ++ echo "Warning: $(5) is too big (> $(4) bytes)" >&2; \ ++ rm -f $(5); \ ++ fi; \ ++ fi; fi ++endef ++ ++# $(1): rootfs type. ++# $(2): board name. ++# $(3): kernel image size limit. ++# $(4): rootfs image size limit. ++# $(5): padding argument for padjffs2. ++Sysupgrade/KR=$(call CatFiles,$(2),$(3),$(KDIR)/root.$(1),$(4),$(call sysupname,$(1),$(5))) ++Sysupgrade/KRuImage=$(call CatFiles,$(KDIR_TMP)/vmlinux-$(2).uImage,$(3),$(KDIR)/root.$(1),$(4),$(call sysupname,$(1),$(2)),$(5)) ++Sysupgrade/RKuImage=$(call CatFiles,$(KDIR)/root.$(1),$(4),$(KDIR_TMP)/vmlinux-$(2).uImage,$(3),$(call sysupname,$(1),$(2))) ++ ++# $(1): ubinize ini file ++# $(2): working directory ++# $(3): output file ++# $(4): physical erase block size ++# $(5): minimum I/O unit size ++# $(6): custom options ++define ubinize ++ $(CP) $(1) $(2) ++ ( cd $(2); $(STAGING_DIR_HOST)/bin/ubinize -o $(3) -p $(4) -m $(5) $(6) $(1)) ++endef ++ ++# ++# Embed lzma-compressed kernel inside lzma-loader. ++# ++# $(1), suffix of output filename, e.g. generic, lowercase board name, etc. ++# $(2), suffix of target file to build, e.g. bin, gz, elf ++# $(3), kernel command line to pass from lzma-loader to kernel ++# $(4), unused here ++# $(5), suffix of kernel filename, e.g. -initramfs, or empty ++define Image/BuildLoader ++ -rm -rf $(KDIR)/lzma-loader ++ $(LOADER_MAKE) LOADER=loader-$(1).$(2) KERNEL_CMDLINE="$(3)"\ ++ LZMA_TEXT_START=0x80a00000 LOADADDR=0x80060000 \ ++ LOADER_DATA="$(KDIR)/vmlinux$(5).bin.lzma" BOARD="$(1)" \ ++ compile loader.$(2) ++ -$(if $(5),$(CP) $(KDIR)/loader-$(1).$(2) $(KDIR)/loader-$(1)$(5).$(2)) ++endef ++ ++# ++# Build lzma-loader alone which will search for lzma-compressed kernel identified by ++# uImage header with magic "OKLI" at boot time. ++# ++# $(4), offset into the flash space to start searching uImage magic "OKLI". ++# $(5), size of search range starting at $(4). With 0 as the value, uImage ++# header is expected to be at precisely $(4) ++define Image/BuildLoaderAlone ++ -rm -rf $(KDIR)/lzma-loader ++ $(LOADER_MAKE) LOADER=loader-$(1).$(2) KERNEL_CMDLINE="$(3)" \ ++ LZMA_TEXT_START=0x80a00000 LOADADDR=0x80060000 \ ++ BOARD="$(1)" FLASH_OFFS=$(4) FLASH_MAX=$(5) \ ++ compile loader.$(2) ++endef ++ ++define Build/Clean ++ $(LOADER_MAKE) clean ++endef ++ ++alfa_ap120c_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,13312k(rootfs),1536k(kernel),1152k(unknown)ro,64k(art)ro;spi0.1:-(unknown) ++alfa_ap96_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,256k(u-boot-env)ro,13312k(rootfs),2048k(kernel),512k(caldata)ro,15360k@0x80000(firmware) ++alfa_mtdlayout_8M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6144k(rootfs),1600k(kernel),64k(nvram),64k(art)ro,7744k@0x50000(firmware) ++alfa_mtdlayout_16M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,15936k(firmware),64k(nvram),64k(art)ro ++all0258n_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env),6272k(firmware),1536k(failsafe),64k(art)ro ++all0315n_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,256k(u-boot-env),13568k(firmware),2048k(failsafe),256k(art)ro ++ap96_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(u-boot-env)ro,6144k(rootfs),1728k(kernel),64k(art)ro,7872k@0x40000(firmware) ++ap121_mtdlayout_8M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6144k(rootfs),1600k(kernel),64k(nvram),64k(art)ro,7744k@0x50000(firmware) ++ap121_mtdlayout_16M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,10944k(rootfs),4992k(kernel),64k(nvram),64k(art)ro,15936k@0x50000(firmware) ++ap132_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,1408k(kernel),6400k(rootfs),64k(art)ro,7808k@0x50000(firmware) ++ap135_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14528k(rootfs),1472k(kernel),64k(art)ro,16000k@0x50000(firmware) ++ap136_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6336k(rootfs),1408k(kernel),64k(mib0),64k(art)ro,7744k@0x50000(firmware) ++ap143_mtdlayout_8M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6336k(rootfs),1472k(kernel),64k(art)ro,7744k@0x50000(firmware) ++ap143_mtdlayout_16M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14528k(rootfs),1472k(kernel),64k(art)ro,16000k@0x50000(firmware) ++ap147_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14528k(rootfs),1472k(kernel),64k(art)ro,16000k@0x50000(firmware) ++ap152_mtdlayout_16M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14528k(rootfs),1472k(kernel),64k(art)ro,16000k@0x50000(firmware) ++bxu2000n2_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,1408k(kernel),8448k(rootfs),6016k(user),64k(cfg),64k(oem),64k(art)ro ++cameo_ap81_mtdlayout=mtdparts=spi0.0:128k(u-boot)ro,64k(config)ro,3840k(firmware),64k(art)ro ++cameo_ap91_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(nvram)ro,3712k(firmware),64k(mac)ro,64k(art)ro ++cameo_ap99_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(nvram)ro,3520k(firmware),64k(mac)ro,192k(lp)ro,64k(art)ro ++cameo_ap121_mtdlayout=mtdparts=spi0.0:64k(u-boot)ro,64k(art)ro,64k(mac)ro,64k(nvram)ro,192k(language)ro,3648k(firmware) ++cameo_ap121_mtdlayout_8M=mtdparts=spi0.0:64k(u-boot)ro,64k(art)ro,64k(mac)ro,64k(nvram)ro,256k(language)ro,7680k@0x80000(firmware) ++cameo_ap123_mtdlayout_4M=mtdparts=spi0.0:64k(u-boot)ro,64k(nvram)ro,3712k(firmware),192k(lang)ro,64k(art)ro ++cameo_db120_mtdlayout=mtdparts=spi0.0:64k(uboot)ro,64k(nvram)ro,15936k(firmware),192k(lang)ro,64k(mac)ro,64k(art)ro ++cameo_db120_mtdlayout_8M=mtdparts=spi0.0:64k(uboot)ro,64k(nvram)ro,7872k(firmware),128k(lang)ro,64k(art)ro ++cap4200ag_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env),320k(custom)ro,1536k(kernel),12096k(rootfs),2048k(failsafe),64k(art)ro,13632k@0xa0000(firmware) ++eap300v2_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env),320k(custom),13632k(firmware),2048k(failsafe),64k(art)ro ++db120_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6336k(rootfs),1408k(kernel),64k(nvram),64k(art)ro,7744k@0x50000(firmware) ++dgl_5500_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(nvram)ro,15296k(firmware),192k(lang)ro,512k(my-dlink)ro,64k(mac)ro,64k(art)ro ++dlan_hotspot_mtdlayout=mtdparts=spi0.0:128k(u-boot)ro,64k(Config1)ro,64k(Config2)ro,7872k@0x40000(firmware),64k(art)ro ++dlan_pro_500_wp_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,64k(Config1)ro,64k(Config2)ro,7680k@0x70000(firmware),64k(art)ro ++dlan_pro_1200_ac_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,64k(Config1)ro,64k(Config2)ro,15872k@0x70000(firmware),64k(art)ro ++cameo_ap94_mtdlayout=mtdparts=spi0.0:256k(uboot)ro,64k(config)ro,6208k(firmware),64k(caldata)ro,1600k(unknown)ro,64k@0x7f0000(caldata_copy) ++cameo_ap94_mtdlayout_fat=mtdparts=spi0.0:256k(uboot)ro,64k(config)ro,7808k(firmware),64k(caldata)ro,64k@0x660000(caldata_orig),6208k@0x50000(firmware_orig) ++esr900_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(u-boot-env)ro,1408k(kernel),13248k(rootfs),1024k(manufacture)ro,64k(backup)ro,320k(storage)ro,64k(caldata)ro,14656k@0x40000(firmware) ++esr1750_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(u-boot-env)ro,1408k(kernel),13248k(rootfs),1024k(manufacture)ro,64k(backup)ro,320k(storage)ro,64k(caldata)ro,14656k@0x40000(firmware) ++epg5000_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(u-boot-env)ro,1408k(kernel),13248k(rootfs),1024k(manufacture)ro,64k(backup)ro,320k(storage)ro,64k(caldata)ro,14656k@0x40000(firmware) ++f9k1115v2_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env),14464k(rootfs),1408k(kernel),64k(nvram)ro,64k(envram)ro,64k(art)ro,15872k@0x50000(firmware) ++dlrtdev_mtdlayout=mtdparts=spi0.0:256k(uboot)ro,64k(config)ro,6208k(firmware),64k(caldata)ro,640k(certs),960k(unknown)ro,64k@0x7f0000(caldata_copy) ++dlrtdev_mtdlayout_fat=mtdparts=spi0.0:256k(uboot)ro,64k(config)ro,7168k(firmware),640k(certs),64k(caldata)ro,64k@0x660000(caldata_orig),6208k@0x50000(firmware_orig) ++planex_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,7744k(firmware),128k(art)ro ++whrhpg300n_mtdlayout=mtdparts=spi0.0:248k(u-boot)ro,8k(u-boot-env)ro,3712k(firmware),64k(art)ro ++wndap360_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,7744k(firmware),64k(nvram)ro,64k(art)ro ++wnr2200_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,7808k(firmware),64k(art)ro ++wnr2000_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,3712k(firmware),64k(art)ro ++wnr2000v3_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,3712k(firmware),64k(art)ro ++wnr2000v4_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(u-boot-env)ro,3776k(firmware),64k(art)ro ++r6100_mtdlayout=mtdparts=ar934x-nfc:128k(u-boot)ro,256k(caldata)ro,256k(caldata-backup),512k(config),512k(pot),2048k(kernel),122240k(ubi),25600k@0x1a0000(firmware),2048k(language),3072k(traffic_meter) ++tew823dru_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(nvram)ro,15296k(firmware),192k(lang)ro,512k(my-dlink)ro,64k(mac)ro,64k(art)ro ++wndr4300_mtdlayout=mtdparts=ar934x-nfc:256k(u-boot)ro,256k(u-boot-env)ro,256k(caldata)ro,512k(pot),2048k(language),512k(config),3072k(traffic_meter),2048k(kernel),23552k(ubi),25600k@0x6c0000(firmware),256k(caldata_backup),-(reserved) ++zcn1523h_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6208k(rootfs),1472k(kernel),64k(configure)ro,64k(mfg)ro,64k(art)ro,7680k@0x50000(firmware) ++mynet_rext_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,7808k(firmware),64k(nvram)ro,64k(ART)ro ++zyx_nbg6716_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(env)ro,64k(RFdata)ro,-(nbu);ar934x-nfc:2048k@0x0(zyxel_rfsd),2048k@0x200000(romd),1024k@0x400000(header),2048k@0x500000(kernel),125952k@0x500000(firmware),-@0x700000(ubi) ++ ++define Image/BuildKernel ++ cp $(KDIR)/vmlinux.elf $(VMLINUX).elf ++ cp $(KDIR)/vmlinux $(VMLINUX).bin ++ dd if=$(KDIR)/vmlinux.bin.lzma of=$(VMLINUX).lzma bs=65536 conv=sync ++ $(call MkuImage,lzma,,$(KDIR)/vmlinux.bin.lzma,$(UIMAGE)-lzma.bin) ++ cp $(KDIR)/loader-generic.elf $(VMLINUX)-lzma.elf ++ -mkdir -p $(KDIR_TMP) ++endef ++ ++define Image/BuildKernel/Initramfs ++ cp $(KDIR)/vmlinux-initramfs.elf $(VMLINUX)-initramfs.elf ++ cp $(KDIR)/vmlinux-initramfs $(VMLINUX)-initramfs.bin ++ dd if=$(KDIR)/vmlinux-initramfs.bin.lzma of=$(VMLINUX)-initramfs.lzma bs=65536 conv=sync ++ $(call MkuImage,lzma,,$(KDIR)/vmlinux-initramfs.bin.lzma,$(UIMAGE)-initramfs-lzma.bin) ++ cp $(KDIR)/loader-generic-initramfs.elf $(VMLINUX)-initramfs-lzma.elf ++ $(call Image/Build/Initramfs) ++endef ++ ++Image/Build/WRT400N/buildkernel=$(call MkuImageLzma,$(2),$(3)) ++ ++define Image/Build/WRT400N ++ $(call Sysupgrade/KRuImage,$(1),$(2),1310720,6488064) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ wrt400n $(KDIR_TMP)/vmlinux-$(2).uImage $(KDIR)/root.$(1) $(call factoryname,$(1),$(2)); \ ++ fi ++endef ++ ++ ++define Image/Build/CameoAP94/buildkernel ++ $(call MkuImageLzma,$(2),$(3) $(4)) ++ $(call MkuImageLzma,$(2)-fat,$(3) $(5)) ++endef ++ ++define Image/Build/CameoAP94 ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(eval fwsize_fat=$(call mtdpartsize,firmware,$(5))) ++ $(call Sysupgrade/KRuImage,$(1),$(2),0,$$(($(fwsize)-4*64*1024)),64) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ ( \ ++ dd if=$(call sysupname,$(1),$(2)); \ ++ echo -n "$(6)"; \ ++ ) > $(call imgname,$(1),$(2))-backup-loader.bin; \ ++ if [ `stat -c%s $(call sysupname,$(1),$(2))` -gt 4194304 ]; then \ ++ echo "Warning: $(call sysupname,$(1),$(2)) is too big" >&2; \ ++ else \ ++ ( \ ++ dd if=$(call sysupname,$(1),$(2)) bs=4096k conv=sync; \ ++ echo -n "$(7)"; \ ++ ) > $(call factoryname,$(1),$(2)); \ ++ fi; \ ++ fi ++ $(call CatFiles,$(KDIR_TMP)/vmlinux-$(2)-fat.uImage,0,$(KDIR)/root.$(1),$$(($(fwsize_fat)-4*64*1024)),$(KDIR_TMP)/$(2)-fat.bin,64) ++ if [ -e "$(KDIR_TMP)/$(2)-fat.bin" ]; then \ ++ echo -n "" > $(KDIR_TMP)/$(2)-fat.dummy; \ ++ sh $(TOPDIR)/scripts/combined-image.sh \ ++ "$(KDIR_TMP)/$(2)-fat.bin" \ ++ "$(KDIR_TMP)/$(2)-fat.dummy" \ ++ $(call sysupname,$(1),$(2)-fat); \ ++ fi ++endef ++ ++define Image/Build/WZRHP ++ $(call Sysupgrade/KRuImage,$(1),$(2),0,$$(($(3)-4*$(4)*1024)),$(4)) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ ( \ ++ echo -n -e "# Airstation Public Fmt1\x00\x00\x00\x00\x00\x00\x00\x00"; \ ++ dd if=$(call sysupname,$(1),$(2)); \ ++ ) > $(call imgname,$(1),$(2))-tftp.bin; \ ++ buffalo-enc -p $(5) -v 1.99 \ ++ -i $(call sysupname,$(1),$(2)) \ ++ -o $(KDIR_TMP)/$(2).enc; \ ++ buffalo-tag -b $(5) -p $(5) -a ath -v 1.99 -m 1.01 -l mlang8 \ ++ -w 3 -c 0x80041000 -d 0x801e8000 -f 1 -r M_ \ ++ -i $(KDIR_TMP)/$(2).enc \ ++ -o $(call factoryname,$(1),$(2)); \ ++ fi ++endef ++ ++Image/Build/WZRHP64K/buildkernel=$(call MkuImageLzma,$(2),$(3)) ++Image/Build/WZRHP64K/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++Image/Build/WZRHP64K=$(call Image/Build/WZRHP,$(1),$(2),33095680,64,$(4)) ++ ++Image/Build/WZRHP128K/buildkernel=$(call MkuImageLzma,$(2),$(3)) ++Image/Build/WZRHP128K/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++Image/Build/WZRHP128K=$(call Image/Build/WZRHP,$(1),$(2),33030144,128,$(4)) ++ ++ ++Image/Build/WHRHPG300N/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/WHRHPG300N/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++define Image/Build/WHRHPG300N ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(call Sysupgrade/KRuImage,$(1),$(2),0,$$(($(fwsize)-4*64*1024)),64) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ ( \ ++ echo -n -e "# Airstation Public Fmt1\x00\x00\x00\x00\x00\x00\x00\x00"; \ ++ dd if=$(call sysupname,$(1),$(2)); \ ++ ) > $(call imgname,$(1),$(2))-tftp.bin; \ ++ buffalo-enc -p $(5) -v 1.99 \ ++ -i $(call sysupname,$(1),$(2)) \ ++ -o $(KDIR_TMP)/$(2).enc; \ ++ buffalo-tag -b $(5) -p $(5) -a ath -v 1.99 -m 1.01 -l mlang8 \ ++ -w 3 -c 0x80041000 -d 0x801e8000 -f 1 -r M_ \ ++ -i $(KDIR_TMP)/$(2).enc \ ++ -o $(call factoryname,$(1),$(2)); \ ++ fi ++endef ++ ++ ++define Image/Build/Cameo ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(call Sysupgrade/KRuImage,$(1),$(2),0,$$(($(fwsize)-4*64*1024)),64) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ factory_size=$$(($(fwsize) - $(6))); \ ++ ( \ ++ dd if=$(call sysupname,$(1),$(2)) bs=$${factory_size} conv=sync; \ ++ echo -n $(5); \ ++ ) > $(call factoryname,$(1),$(2)); \ ++ fi ++endef ++ ++Image/Build/CameoAP81/buildkernel=$(call MkuImageLzma,$(2),$(3) $(cameo_ap81_mtdlayout)) ++Image/Build/CameoAP81=$(call Image/Build/Cameo,$(1),$(2),$(3),$(cameo_ap81_mtdlayout),$(4),65536) ++Image/Build/CameoAP81/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(cameo_ap81_mtdlayout)) ++ ++Image/Build/CameoAP91/buildkernel=$(call MkuImageLzma,$(2),$(3) $(cameo_ap91_mtdlayout)) ++Image/Build/CameoAP91=$(call Image/Build/Cameo,$(1),$(2),$(3),$(cameo_ap91_mtdlayout),$(4),65536) ++Image/Build/CameoAP91/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(cameo_ap91_mtdlayout)) ++ ++Image/Build/CameoAP99/buildkernel=$(call MkuImageLzma,$(2),$(3) $(cameo_ap99_mtdlayout)) ++Image/Build/CameoAP99=$(call Image/Build/Cameo,$(1),$(2),$(3),$(cameo_ap99_mtdlayout),$(4),65536) ++Image/Build/CameoAP99/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(cameo_ap99_mtdlayout)) ++ ++Image/Build/CameoAP123_4M/buildkernel=$(call MkuImageLzma,$(2),$(3) $(cameo_ap123_mtdlayout_4M)) ++Image/Build/CameoAP123_4M=$(call Image/Build/Cameo,$(1),$(2),$(3),$(cameo_ap123_mtdlayout_4M),$(4),26) ++Image/Build/CameoAP123_4M/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(cameo_ap123_mtdlayout_4M)) ++ ++Image/Build/CameoAP135/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/CameoAP135=$(call Image/Build/Cameo,$(1),$(2),$(3),$(4),$(5),26) ++Image/Build/CameoAP135/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++Image/Build/CameoDB120/buildkernel=$(call MkuImageLzma,$(2),$(3) $(cameo_db120_mtdlayout)) ++Image/Build/CameoDB120=$(call Image/Build/Cameo,$(1),$(2),$(3),$(cameo_db120_mtdlayout),$(4),26) ++Image/Build/CameoDB120/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(cameo_db120_mtdlayout)) ++ ++Image/Build/CameoDB120_8M/buildkernel=$(call MkuImageLzma,$(2),$(3) $(cameo_db120_mtdlayout_8M)) ++Image/Build/CameoDB120_8M=$(call Image/Build/Cameo,$(1),$(2),$(3),$(cameo_db120_mtdlayout_8M),$(4),26) ++Image/Build/CameoDB120_8M/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(cameo_db120_mtdlayout_8M)) ++ ++define Image/Build/CameoHornet ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(call Sysupgrade/KRuImage,$(1),$(2),0,$$(($(fwsize)-4*64*1024)),64) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ for r in $(7); do \ ++ [ -n "$$r" ] && dashr="-$$r" || dashr=; \ ++ [ -z "$$r" ] && r="DEF"; \ ++ mkcameofw -M HORNET -R "$$r" -S $(5) -V $(6) -c \ ++ -K $(8) -I $(fwsize) \ ++ -k "$(call sysupname,$(1),$(2))" \ ++ -o $(call imgname,$(1),$(2))-factory$$dashr.bin; \ ++ true; \ ++ done; \ ++ fi ++endef ++ ++Image/Build/CameoAP121/buildkernel=$(call MkuImageLzma,$(2),$(3) $(cameo_ap121_mtdlayout)) ++Image/Build/CameoAP121=$(call Image/Build/CameoHornet,$(1),$(2),$(3),$(cameo_ap121_mtdlayout),$(4),$(5),$(6),0xe0000) ++Image/Build/CameoAP121/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(cameo_ap121_mtdlayout)) ++ ++Image/Build/CameoAP121_8M/buildkernel=$(call MkuImageLzma,$(2),$(3) $(cameo_ap121_mtdlayout_8M)) ++Image/Build/CameoAP121_8M=$(call Image/Build/CameoHornet,$(1),$(2),$(3),$(cameo_ap121_mtdlayout_8M),$(4),$(5),$(6),0x100000) ++Image/Build/CameoAP121_8M/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(cameo_ap121_mtdlayout_8M)) ++ ++define Image/Build/dLAN ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(eval rootsize=$(call mtdpartsize,rootfs,$(4))) ++ $(eval kernsize=$(call mtdpartsize,kernel,$(4))) ++ $(call Sysupgrade/$(5),$(1),$(2),$(if $(6),$(6),$(kernsize)),$(if $(rootsize),$(rootsize),$(fwsize))) ++endef ++ ++Image/Build/dLANLzma/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/dLANLzma=$(call Image/Build/dLAN,$(1),$(2),$(3),$(4),$(5),$(6),$(7)) ++Image/Build/dLANLzma/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++define Image/Build/Ath ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(eval rootsize=$(call mtdpartsize,rootfs,$(4))) ++ $(eval kernsize=$(call mtdpartsize,kernel,$(4))) ++ $(call Sysupgrade/$(5),$(1),$(2),$(if $(6),$(6),$(kernsize)),$(if $(rootsize),$(rootsize),$(fwsize))) ++endef ++ ++Image/Build/AthGzip/buildkernel=$(call MkuImageGzip,$(2),$(3) $(4)) ++Image/Build/AthGzip=$(call Image/Build/Ath,$(1),$(2),$(3),$(4),$(5),$(6),$(7)) ++Image/Build/AthGzip/initramfs=$(call MkuImageGzip/initramfs,$(2),$(3) $(4)) ++ ++Image/Build/AthLzma/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/AthLzma=$(call Image/Build/Ath,$(1),$(2),$(3),$(4),$(5),$(6),$(7)) ++Image/Build/AthLzma/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++ ++Image/Build/Belkin/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/Belkin/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++define Image/Build/Belkin ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(eval kernsize=$(call mtdpartsize,kernel,$(4))) ++ $(eval rootsize=$(call mtdpartsize,rootfs,$(4))) ++ $(call Sysupgrade/RKuImage,$(1),$(2),$(kernsize),$(rootsize)) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ edimax_fw_header -m $(5) -v "$(shell echo -n $(VERSION_DIST)$(REVISION) | cut -c -13)" \ ++ -n "uImage" \ ++ -i $(KDIR_TMP)/vmlinux-$(2).uImage \ ++ -o $(KDIR_TMP)/$(2)-uImage; \ ++ edimax_fw_header -m $(5) -v "$(shell echo -n $(VERSION_DIST)$(REVISION) | cut -c -13)" \ ++ -n "rootfs" \ ++ -i $(KDIR)/root.$(1) \ ++ -o $(KDIR_TMP)/$(2)-rootfs; \ ++ ( \ ++ dd if=$(KDIR_TMP)/$(2)-rootfs; \ ++ dd if=$(KDIR_TMP)/$(2)-uImage; \ ++ ) > "$(call factoryname,$(1),$(2))"; \ ++ fi ++endef ++ ++define Image/Build/EnGenius ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(eval rootsize=$(call mtdpartsize,rootfs,$(4))) ++ $(eval kernsize=$(call mtdpartsize,kernel,$(4))) ++ $(call Sysupgrade/$(5),$(1),$(2),$(if $(6),$(6),$(kernsize)),$(if $(rootsize),$(rootsize),$(fwsize))) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ mksenaofw -e $(call sysupname,$(1),$(2)) \ ++ -o $(call imgname,$(1),$(2))-factory.dlf \ ++ -r 0x101 -p $(7) -t 2; \ ++ fi ++endef ++ ++Image/Build/EnGenius/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/EnGenius/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++ ++Image/Build/PB4X/buildkernel=$(call PatchKernelLzma,$(2),$(3)) ++ ++define Image/Build/PB4X ++ dd if=$(KDIR_TMP)/vmlinux-$(2).bin.lzma \ ++ of=$(call imgname,kernel,$(2)).bin bs=64k conv=sync ++ dd if=$(KDIR)/root.$(1) \ ++ of=$(call imgname,$(1),$(2)-rootfs).bin bs=128k conv=sync ++ -sh $(TOPDIR)/scripts/combined-image.sh \ ++ "$(call imgname,kernel,$(2)).bin" \ ++ "$(call imgname,$(1),$(2)-rootfs).bin" \ ++ $(call sysupname,$(1),$(2)) ++endef ++ ++ ++Image/Build/MyLoader/buildkernel=$(call PatchKernelLzma,$(2),$(3)) ++Image/Build/MyLoader/initramfs=$(call PatchKernel/initramfs,$(2),$(3)) ++ ++define Image/Build/MyLoader ++ $(eval fwsize=$(shell echo $$(($(4)-0x30000-4*64*1024)))) ++ $(eval fwimage=$(KDIR_TMP)/$(2)-$(5)-firmware.bin) ++ $(call CatFiles,$(KDIR_TMP)/vmlinux-$(2).bin.lzma,65536,$(KDIR)/root.$(1),$(fwsize),$(fwimage)) ++ if [ -e "$(fwimage)" ]; then \ ++ $(STAGING_DIR_HOST)/bin/mkmylofw -B $(2) -s $(4) -v \ ++ -p0x00030000:0:al:0x80060000:firmware:$(fwimage) \ ++ $(call imgname,$(1),$(2))-$(5)-factory.img; \ ++ echo -n "" > $(KDIR_TMP)/empty.bin; \ ++ sh $(TOPDIR)/scripts/combined-image.sh \ ++ $(fwimage) $(KDIR_TMP)/empty.bin \ ++ $(call imgname,$(1),$(2))-$(5)-sysupgrade.bin; \ ++ fi ++endef ++ ++Image/Build/Planex/initramfs=$(call MkuImageGzip/initramfs,$(2),$(3) $(planex_mtdlayout)) ++Image/Build/Planex/loader=$(call Image/BuildLoaderAlone,$(1),gz,$(2) $(planex_mtdlayout),0x52000,0) ++ ++define Image/Build/Planex/buildkernel ++ [ -e "$(KDIR)/loader-$(2).gz" ] ++ $(call MkuImageOKLI,$(2)) ++ ( \ ++ dd if=$(KDIR)/loader-$(2).gz bs=8128 count=1 conv=sync; \ ++ dd if=$(KDIR_TMP)/vmlinux-$(2).okli; \ ++ ) > $(KDIR_TMP)/kernel-$(2).bin ++ $(call MkuImage,gzip,,$(KDIR_TMP)/kernel-$(2).bin,$(KDIR_TMP)/vmlinux-$(2).uImage) ++endef ++ ++define Image/Build/Planex ++ $(eval fwsize=$(call mtdpartsize,firmware,$(planex_mtdlayout))) ++ $(call Sysupgrade/KRuImage,$(1),$(2),0,$$(($(fwsize)-4*64*1024)),64) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ $(STAGING_DIR_HOST)/bin/mkplanexfw \ ++ -B $(2) \ ++ -v 2.00.00 \ ++ -i $(call sysupname,$(1),$(2)) \ ++ -o $(call factoryname,$(1),$(2)); \ ++ fi ++endef ++ ++ ++Image/Build/ALFA/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/ALFA/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++define Image/Build/ALFA ++ $(call Sysupgrade/RKuImage,$(1),$(2),$(5),$(6)) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ rm -rf $(KDIR)/$(1); \ ++ mkdir -p $(KDIR)/$(1); \ ++ cd $(KDIR)/$(1); \ ++ cp $(KDIR_TMP)/vmlinux-$(2).uImage $(KDIR)/$(1)/$(7); \ ++ cp $(KDIR)/root.$(1) $(KDIR)/$(1)/$(8); \ ++ $(TAR) c \ ++ $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \ ++ -C $(KDIR)/$(1) $(7) $(8) \ ++ | gzip -9nc > $(call factoryname,$(1),$(2)); \ ++ ( \ ++ echo WRM7222C | dd bs=32 count=1 conv=sync; \ ++ echo -ne '\xfe'; \ ++ ) >> $(call factoryname,$(1),$(2)); \ ++ fi ++endef ++ ++ ++Image/Build/Senao/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/Senao/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++define Image/Build/Senao ++ mkdir -p $(KDIR_TMP)/$(2)/ ++ touch $(KDIR_TMP)/$(2)/FWINFO-OpenWrt-$(REVISION)-$(2) ++ -$(CP) ./$(2)/* $(KDIR_TMP)/$(2)/ ++ dd if=$(KDIR_TMP)/vmlinux-$(2).uImage \ ++ of=$(KDIR_TMP)/$(2)/openwrt-senao-$(2)-uImage-lzma.bin bs=64k conv=sync ++ dd if=$(KDIR)/root.$(1) \ ++ of=$(KDIR_TMP)/$(2)/openwrt-senao-$(2)-root.$(1) bs=64k conv=sync ++ ( \ ++ cd $(KDIR_TMP)/$(2)/; \ ++ $(TAR) -c \ ++ $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \ ++ * | gzip -9nc > $(call factoryname,$(1),$(2)) \ ++ ) ++ -rm -rf $(KDIR_TMP)/$(2)/ ++ -sh $(TOPDIR)/scripts/combined-image.sh \ ++ $(KDIR_TMP)/vmlinux-$(2).uImage \ ++ $(KDIR)/root.$(1) \ ++ $(call sysupname,$(1),$(2)) ++endef ++ ++define Image/Build/CyberTAN ++ echo -n '' > $(KDIR_TMP)/empty.bin ++ -$(STAGING_DIR_HOST)/bin/trx -o $(KDIR)/image.tmp \ ++ -f $(KDIR_TMP)/vmlinux-$(2).uImage -F $(KDIR_TMP)/empty.bin \ ++ -x 32 -a 0x10000 -x -32 -f $(KDIR)/root.$(1) && \ ++ $(STAGING_DIR_HOST)/bin/addpattern -B $(2) -v v$(5) \ ++ -i $(KDIR)/image.tmp \ ++ -o $(call sysupname,$(1),$(2)) ++ -$(STAGING_DIR_HOST)/bin/trx -o $(KDIR)/image.tmp -f $(KDIR_TMP)/vmlinux-$(2).uImage \ ++ -x 32 -a 0x10000 -x -32 -f $(KDIR)/root.$(1) && \ ++ $(STAGING_DIR_HOST)/bin/addpattern -B $(2) -v v$(5) -g \ ++ -i $(KDIR)/image.tmp \ ++ -o $(call factoryname,$(1),$(2)) ++ -rm $(KDIR)/image.tmp ++endef ++ ++Image/Build/CyberTANGZIP/loader=$(call Image/BuildLoader,$(1),gz,$(2),0x80060000) ++Image/Build/CyberTANGZIP/buildkernel=$(call MkuImage,gzip,,$(KDIR)/loader-$(2).gz,$(KDIR_TMP)/vmlinux-$(2).uImage) ++Image/Build/CyberTANGZIP=$(call Image/Build/CyberTAN,$(1),$(2),$(3),$(4),$(5)) ++ ++Image/Build/CyberTANLZMA/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/CyberTANLZMA=$(call Image/Build/CyberTAN,$(1),$(2),$(3),$(4),$(5)) ++ ++ ++Image/Build/Netgear/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4),,-M $(5)) ++ ++define Image/Build/Netgear/buildkernel ++ $(call MkuImageLzma,$(2),$(3) $(4),-d20,,-M $(5)) ++ -rm -rf $(KDIR_TMP)/$(2) ++ mkdir -p $(KDIR_TMP)/$(2)/image ++ cat $(KDIR_TMP)/vmlinux-$(2).uImage > $(KDIR_TMP)/$(2)/image/uImage ++ $(STAGING_DIR_HOST)/bin/mksquashfs-lzma \ ++ $(KDIR_TMP)/$(2) $(KDIR_TMP)/vmlinux-$(2).uImage.squashfs.tmp1 \ ++ -noappend -root-owned -be -b 65536 \ ++ $(if $(SOURCE_DATE_EPOCH),-fixed-time $(SOURCE_DATE_EPOCH)) ++ ( \ ++ cat $(KDIR_TMP)/vmlinux-$(2).uImage.squashfs.tmp1; \ ++ dd if=/dev/zero bs=1k count=1 \ ++ ) > $(KDIR_TMP)/vmlinux-$(2).uImage.squashfs.tmp2 ++ mkimage -A mips -O linux -T filesystem -C none -M $(5) \ ++ -a 0xbf070000 -e 0xbf070000 \ ++ -n 'MIPS $(VERSION_DIST) Linux-$(LINUX_VERSION)' \ ++ -d $(KDIR_TMP)/vmlinux-$(2).uImage.squashfs.tmp2 \ ++ $(KDIR_TMP)/vmlinux-$(2).uImage.squashfs ++endef ++ ++define Image/Build/Netgear ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(call CatFiles,$(KDIR_TMP)/vmlinux-$(2).uImage.squashfs,0,$(KDIR)/root.$(1),$(fwsize),$(call sysupname,$(1),$(2)),64) ++ if [ -e $(call sysupname,$(1),$(2)) ]; then \ ++ for r in $(7) ; do \ ++ [ -n "$$r" ] && dashr="-$$r" || dashr= ; \ ++ $(STAGING_DIR_HOST)/bin/mkdniimg \ ++ -B $(6) -v $(VERSION_DIST).$(REVISION) -r "$$r" $(8) \ ++ -i $(call sysupname,$(1),$(2)) \ ++ -o $(call imgname,$(1),$(2))-factory$$dashr.img; \ ++ done; \ ++ fi ++ if [ "$2" = "wnr2000" ]; then \ ++ dd if=$(KDIR)/root.$(1) \ ++ of=$(call imgname,$(1),$(2)-rootfs).bin bs=128k conv=sync; \ ++ fi ++endef ++ ++ ++Image/Build/NetgearLzma/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4),,-M $(5)) ++Image/Build/NetgearLzma/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4),-d20,,-M $(5)) ++ ++define Image/Build/NetgearLzma ++ $(eval fwsize=$(call mtdpartsize,firmware,$(4))) ++ $(call CatFiles,$(KDIR_TMP)/vmlinux-$(2).uImage,0,$(KDIR)/root.$(1),$(fwsize),$(call sysupname,$(1),$(2)),64) ++endef ++ ++ ++Image/Build/NetgearNAND/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4),,-M $(5)) ++ ++# $(1): (empty) ++# $(2): Board name (small caps) ++# $(3): Kernel board specific cmdline ++# $(4): Kernel mtdparts definition ++# $(5): U-Boot magic ++define Image/Build/NetgearNAND/buildkernel ++ $(eval kernelsize=$(call mtdpartsize,kernel,$(4))) ++ $(call PatchKernelLzma,$(2),$(3) $(4),-d20) ++ dd if=$(KDIR_TMP)/vmlinux-$(2).bin.lzma \ ++ of=$(KDIR_TMP)/vmlinux-$(2).bin.tmp \ ++ bs=$$(($(kernelsize)-131072-2*64-1)) \ ++ count=1 conv=sync ++ $(call MkuImage,lzma,-M $(5),$(KDIR_TMP)/vmlinux-$(2).bin.tmp,$(KDIR_TMP)/vmlinux-$(2).uImage) ++ echo -ne '\xff' >> $(KDIR_TMP)/vmlinux-$(2).uImage ++ # create a fake rootfs image ++ dd if=/dev/zero of=$(KDIR_TMP)/fakeroot-$(2) bs=131072 count=1 ++ mkimage -A mips -O linux -T filesystem -C none \ ++ -a 0xbf070000 -e 0xbf070000 \ ++ -n 'MIPS $(VERSION_DIST) fakeroot' \ ++ -d $(KDIR_TMP)/fakeroot-$(2) \ ++ -M $(5) \ ++ $(KDIR_TMP)/fakeroot-$(2).uImage ++ # append the fake rootfs image to the kernel, it will reside in the last ++ # erase block of the kernel partition ++ cat $(KDIR_TMP)/fakeroot-$(2).uImage >> $(KDIR_TMP)/vmlinux-$(2).uImage ++endef ++ ++ ++# $(1): rootfs image suffix ++# $(2): Board name (small caps) ++# $(3): Kernel board specific cmdline ++# $(4): Kernel mtdparts definition ++# $(5): U-Boot magic ++# $(6): Board name (upper caps) ++# $(7): firmware region code (not used yet) ++# $(8): DNI Hardware version ++# $(9): suffix of the configuration file for ubinize ++define Image/Build/NetgearNAND ++ $(eval firmwaresize=$(call mtdpartsize,firmware,$(4))) ++ $(eval kernelsize=$(call mtdpartsize,kernel,$(4))) ++ $(eval imageraw=$(KDIR_TMP)/$(2)-raw.img) ++ $(CP) $(KDIR)/root.squashfs-raw $(KDIR_TMP)/root.squashfs ++ echo -ne '\xde\xad\xc0\xde' > $(KDIR_TMP)/jffs2.eof ++ $(call ubinize,ubinize-$(9).ini,$(KDIR_TMP),$(KDIR_TMP)/$(2)-root.ubi,128KiB,2048,-E 5) ++ ( \ ++ dd if=$(KDIR_TMP)/vmlinux-$(2).uImage; \ ++ dd if=$(KDIR_TMP)/$(2)-root.ubi \ ++ ) > $(imageraw) ++ $(STAGING_DIR_HOST)/bin/mkdniimg \ ++ -B $(6) -v $(VERSION_DIST).$(REVISION) -r "$$r" $(8) \ ++ -i $(imageraw) \ ++ -o $(call imgname,ubi,$(2))-factory.img ++ ++ $(call Image/Build/SysupgradeNAND,$(2),squashfs,$(KDIR_TMP)/vmlinux-$(2).uImage) ++endef ++ ++ZYXEL_UBOOT = $(KDIR)/u-boot-nbg460n_550n_550nh.bin ++ZYXEL_UBOOT_BIN = $(wildcard $(BIN_DIR)/u-boot-nbg460n_550n_550nh/u-boot.bin) ++ ++Image/Build/ZyXEL/buildkernel=$(call MkuImageLzma,$(2),$(3)) ++ ++define Image/Build/ZyXEL ++ $(call Sysupgrade/KRuImage,$(1),$(2),917504,2752512) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ if [ ! -f $(ZYXEL_UBOOT) ]; then \ ++ echo "Warning: $(ZYXEL_UBOOT) not found" >&2; \ ++ else \ ++ $(STAGING_DIR_HOST)/bin/mkzynfw \ ++ -B $(4) \ ++ -b $(ZYXEL_UBOOT) \ ++ -r $(call sysupname,$(1),$(2)):0x10000 \ ++ -o $(call factoryname,$(1),$(2)); \ ++ fi; fi ++endef ++ ++# attention: only zlib compression is allowed for the boot fs ++define Image/Build/ZyXELNAND/buildkernel ++ $(eval kernelsize=$(call mtdpartsize,kernel,$(5))) ++ $(call MkuImageLzma,$(2),$(3) $(5) $(6)) ++ mkdir -p $(KDIR_TMP)/$(2)/image/boot ++ cp $(KDIR_TMP)/vmlinux-$(2).uImage $(KDIR_TMP)/$(2)/image/boot/vmlinux.lzma.uImage ++ $(STAGING_DIR_HOST)/bin/mkfs.jffs2 \ ++ --pad=$(kernelsize) --big-endian --squash-uids -v -e 128KiB -q -f -n -x lzma -x rtime \ ++ -o $(KDIR_TMP)/$(2)-kernel.jffs2 \ ++ -d $(KDIR_TMP)/$(2)/image \ ++ 2>&1 1>/dev/null | awk '/^.+$$/' ++ -rm -rf $(KDIR_TMP)/$(2) ++endef ++ ++define Image/Build/ZyXELNAND ++ if [ "$(1)" != "squashfs" ]; then \ ++ echo Only squashfs is supported; \ ++ return 0; \ ++ fi ++ $(eval firmwaresize=$(call mtdpartsize,firmware,$(4))) ++ $(eval kernelsize=$(call mtdpartsize,kernel,$(4))) ++ $(eval imageraw=$(KDIR_TMP)/$(2)-raw.img) ++ $(CP) $(KDIR)/root.$(1) $(KDIR_TMP)/ubi_root.img ++ $(call ubinize,ubinize-$(2).ini,$(KDIR_TMP),$(KDIR_TMP)/$(2)-root.ubi,128KiB,2048,-E 5) ++ ( \ ++ dd if=$(KDIR_TMP)/$(2)-kernel.jffs2; \ ++ dd if=$(KDIR_TMP)/$(2)-root.ubi \ ++ ) > $(imageraw) ++ dd if=$(imageraw) of=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory.bin \ ++ bs=128k conv=sync ++ $(call Image/Build/SysupgradeNAND,$(2),squashfs,$(KDIR_TMP)/$(2)-kernel.jffs2) ++endef ++ ++ ++Image/Build/OpenMesh/buildkernel=$(call MkuImageLzma,$(2)) ++Image/Build/OpenMesh/initramfs=$(call MkuImageLzma/initramfs,$(2),) ++ ++define Image/Build/OpenMesh ++ -sh $(TOPDIR)/scripts/om-fwupgradecfg-gen.sh \ ++ "$(4)" \ ++ "$(BUILD_DIR)/fwupgrade.cfg-$(4)" \ ++ "$(KDIR_TMP)/vmlinux-$(2).uImage" \ ++ "$(KDIR)/root.$(1)" ++ -sh $(TOPDIR)/scripts/combined-ext-image.sh \ ++ "$(4)" "$(call factoryname,$(1),$(2))" \ ++ "$(BUILD_DIR)/fwupgrade.cfg-$(4)" "fwupgrade.cfg" \ ++ "$(KDIR_TMP)/vmlinux-$(2).uImage" "kernel" \ ++ "$(KDIR)/root.$(1)" "rootfs" ++ if [ -e "$(call factoryname,$(1),$(2))" ]; then \ ++ cp "$(call factoryname,$(1),$(2))" "$(call sysupname,$(1),$(2))"; \ ++ fi ++endef ++ ++ ++Image/Build/Zcomax/buildkernel=$(call MkuImageLzma,$(2),$(3) $(4)) ++Image/Build/Zcomax/initramfs=$(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++ ++define Image/Build/Zcomax ++ $(call Sysupgrade/RKuImage,$(1),$(2),1507328,6356992) ++ if [ -e "$(call sysupname,$(1),$(2))" ]; then \ ++ $(STAGING_DIR_HOST)/bin/mkzcfw \ ++ -B $(2) \ ++ -k $(KDIR_TMP)/vmlinux-$(2).uImage \ ++ -r $(KDIR)/root.$(1) \ ++ -o $(call imgname,$(1),$(2))-factory.img; \ ++ fi ++endef ++ ++ ++# $(1): template name to be defined. ++# $(2): squashfs suffix to be used. ++define BuildTemplate ++ # $(1) : name of build method. ++ # $(2) : board name. ++ # $(3) : kernel command line. ++ # $(4)~$(8): extra arguments. ++ define Image/Build/Template/$(1)/initramfs ++ $$(call Image/Build/$$(1)/initramfs,initramfs,$$(2),$$(3),$$(4),$$(5),$$(6),$$(7),$$(8),$$(9),$$(10)) ++ endef ++ define Image/Build/Template/$(1)/loader ++ $$(call Image/Build/$$(1)/loader,$$(2),$$(3),$$(4),$$(5),$$(6),$$(7),$$(8),$$(9),$$(10)) ++ endef ++ define Image/Build/Template/$(1)/buildkernel ++ $$(call Image/Build/$$(1)/buildkernel,,$$(2),$$(3),$$(4),$$(5),$$(6),$$(7),$$(8),$$(9),$$(10)) ++ endef ++ define Image/Build/Template/$(1)/squashfs ++ $$(call Image/Build/$$(1),squashfs$(2),$$(2),$$(3),$$(4),$$(5),$$(6),$$(7),$$(8),$$(9),$$(10)) ++ endef ++endef ++ ++$(eval $(call BuildTemplate,squashfs-only)) ++$(eval $(call BuildTemplate,64k,-64k)) ++$(eval $(call BuildTemplate,64kraw,-raw)) ++$(eval $(call BuildTemplate,64kraw-nojffs,-raw)) ++$(eval $(call BuildTemplate,128k)) ++$(eval $(call BuildTemplate,128kraw,-raw)) ++$(eval $(call BuildTemplate,256k)) ++$(eval $(call BuildTemplate,all)) ++ ++ifeq ($(SUBTARGET),generic) ++$(eval $(call SingleProfile,ALFA,64k,ALFANX,alfa-nx,ALFA-NX,ttyS0,115200,$$(alfa_mtdlayout_8M),1638400,6291456,vmlinux.gz.uImage,pb9x-2.6.31-jffs2)) ++$(eval $(call SingleProfile,ALFA,64k,HORNETUB,hornet-ub,HORNET-UB,ttyATH0,115200,$$(alfa_mtdlayout_8M),1638400,6291456,kernel_image,rootfs_image)) ++$(eval $(call SingleProfile,ALFA,64k,TUBE2H8M,tube2h-8M,TUBE2H,ttyATH0,115200,$$(alfa_mtdlayout_8M),1638400,6291456,kernel.image,rootfs.image)) ++ ++$(eval $(call SingleProfile,AthGzip,64k,AP96,ap96,AP96,ttyS0,115200,$$(ap96_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthGzip,64k,WNDAP360,wndap360,WNDAP360,ttyS0,9600,$$(wndap360_mtdlayout),KRuImage,65536)) ++ ++$(eval $(call SingleProfile,AthLzma,64k,ALFAAP120C,alfa-ap120c,ALFA-AP120C,ttyS0,115200,$$(alfa_ap120c_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,ALFAAP96,alfa-ap96,ALFA-AP96,ttyS0,115200,$$(alfa_ap96_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,ALL0258N,all0258n,ALL0258N,ttyS0,115200,$$(all0258n_mtdlayout),KRuImage,65536)) ++$(eval $(call SingleProfile,AthLzma,256k,ALL0315N,all0315n,ALL0315N,ttyS0,115200,$$(all0315n_mtdlayout),KRuImage,262144)) ++$(eval $(call SingleProfile,AthLzma,64k,AP121_8M,ap121-8M,AP121,ttyATH0,115200,$$(ap121_mtdlayout_8M),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP121_16M,ap121-16M,AP121,ttyATH0,115200,$$(ap121_mtdlayout_16M),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP132,ap132,AP132,ttyS0,115200,$$(ap132_mtdlayout),KRuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP135,ap135-020,AP135-020,ttyS0,115200,$$(ap135_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP136_010,ap136-010,AP136-010,ttyS0,115200,$$(ap136_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP136_020,ap136-020,AP136-020,ttyS0,115200,$$(ap136_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP143_8M,ap143-8M,AP143,ttyS0,115200,$$(ap143_mtdlayout_8M),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP143_16M,ap143-16M,AP143,ttyS0,115200,$$(ap143_mtdlayout_16M),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP147_010,ap147-010,AP147-010,ttyS0,115200,$$(ap147_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,AP152_16M,ap152-16M,AP152,ttyS0,115200,$$(ap152_mtdlayout_16M),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,BXU2000N2,bxu2000n-2-a1,BXU2000n-2-A1,ttyS0,115200,$$(bxu2000n2_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,CAP4200AG,cap4200ag,CAP4200AG,ttyS0,115200,$$(cap4200ag_mtdlayout),KRuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,DB120,db120,DB120,ttyS0,115200,$$(db120_mtdlayout),RKuImage)) ++$(eval $(call SingleProfile,AthLzma,64k,HORNETUBx2,hornet-ub-x2,HORNET-UB,ttyATH0,115200,$$(alfa_mtdlayout_16M),KRuImage,65536)) ++$(eval $(call SingleProfile,AthLzma,64k,TUBE2H16M,tube2h-16M,TUBE2H,ttyATH0,115200,$$(alfa_mtdlayout_16M),KRuImage,65536)) ++ ++$(eval $(call SingleProfile,CameoAP121_8M,64kraw-nojffs,DIR505A1,dir-505-a1,DIR-505-A1,ttyATH0,115200,"HORNET-PACKET-DIR505A1-3",1.99.99,"")) ++ ++$(eval $(call SingleProfile,CameoAP135,64kraw,DGL5500A1,dgl-5500-a1,DGL-5500-A1,ttyS0,115200,$$(dgl_5500_mtdlayout),"00AP135AR9558-RT-130508-00")) ++$(eval $(call SingleProfile,CameoAP135,64kraw,TEW823DRU,tew-823dru,TEW-823DRU,ttyS0,115200,$$(tew823dru_mtdlayout) mem=256M,"00AP135AR9558-RT-131129-00")) ++ ++$(eval $(call SingleProfile,CameoDB120,64kraw,DHP1565A1,dhp-1565-a1,DHP-1565-A1,ttyS0,115200,"00DB120AR9344-RT-101214-00")) ++$(eval $(call SingleProfile,CameoDB120,64kraw,DIR825C1,dir-825-c1,DIR-825-C1,ttyS0,115200,"00DB120AR9344-RT-101214-00")) ++$(eval $(call SingleProfile,CameoDB120,64kraw,DIR835A1,dir-835-a1,DIR-835-A1,ttyS0,115200,"00DB120AR9344-RT-101214-00")) ++ ++$(eval $(call SingleProfile,CameoDB120_8M,64kraw,TEW732BR,tew-732br,TEW-732BR,ttyS0,115200,"00DB120AR9341-RT-120906-NA")) ++ ++$(eval $(call SingleProfile,CyberTANGZIP,64k,E2100L,e2100l,E2100L,ttyS0,115200,,1.00.01)) ++$(eval $(call SingleProfile,CyberTANGZIP,64k,WRT160NL,wrt160nl,WRT160NL,ttyS0,115200,,1.00.01)) ++ ++$(eval $(call SingleProfile,CyberTANLZMA,64k,MYNETREXT,mynet-rext,MYNET-REXT,ttyS0,115200,$$(mynet_rext_mtdlayout) root=31:2,1.00.01)) ++ ++$(eval $(call SingleProfile,CameoAP94,64kraw,DIR825B1,dir-825-b1,DIR-825-B1,ttyS0,115200,$$(cameo_ap94_mtdlayout),$$(cameo_ap94_mtdlayout_fat),01AP94-AR7161-RT-080619-00,00AP94-AR7161-RT-080619-00)) ++$(eval $(call SingleProfile,CameoAP94,64kraw,TEW673GRU,tew-673gru,TEW-673GRU,ttyS0,115200,$$(cameo_ap94_mtdlayout),$$(cameo_ap94_mtdlayout_fat),01AP94-AR7161-RT-080619-01,00AP94-AR7161-RT-080619-01)) ++$(eval $(call SingleProfile,CameoAP94,64kraw,DLRTDEV01,dlrtdev01,DIR-825-B1,ttyS0,115200,$$(dlrtdev_mtdlayout),$$(dlrtdev_mtdlayout_fat),01AP94-AR7161-RT-080619-00,00AP94-AR7161-RT-080619-00)) ++ ++$(eval $(call SingleProfile,dLANLzma,64k,dLAN_Hotspot,dlan-hotspot,dLAN-Hotspot,ttyATH0,115200,$$(dlan_hotspot_mtdlayout) mem=64M,KRuImage,65536)) ++$(eval $(call SingleProfile,dLANLzma,64k,dLAN_pro_500_wp,dlan-pro-500-wp,dLAN-pro-500-wp,ttyS0,115200,$$(dlan_pro_500_wp_mtdlayout) mem=128M,KRuImage,65536)) ++$(eval $(call SingleProfile,dLANLzma,64k,dLAN_pro_1200_ac,dlan-pro-1200-ac,dLAN-pro-1200-ac,ttyS0,115200,$$(dlan_pro_1200_ac_mtdlayout) mem=128M,KRuImage,65536)) ++ ++$(eval $(call SingleProfile,EnGenius,64k,ESR900,esr900,ESR900,ttyS0,115200,$$(esr900_mtdlayout),KRuImage,,0x4e)) ++$(eval $(call SingleProfile,EnGenius,64k,ESR1750,esr1750,ESR1750,ttyS0,115200,$$(esr1750_mtdlayout),KRuImage,,0x61)) ++$(eval $(call SingleProfile,EnGenius,64k,EPG5000,epg5000,EPG5000,ttyS0,115200,$$(epg5000_mtdlayout),KRuImage,,0x71)) ++ ++$(eval $(call SingleProfile,MyLoader,64k,WP543_8M,wp543,,ttyS0,115200,0x800000,8M)) ++$(eval $(call SingleProfile,MyLoader,64k,WP543_16M,wp543,,ttyS0,115200,0x1000000,16M)) ++$(eval $(call SingleProfile,MyLoader,64k,WPE72_8M,wpe72,,ttyS0,115200,0x800000,8M)) ++$(eval $(call SingleProfile,MyLoader,64k,WPE72_16M,wpe72,,ttyS0,115200,0x1000000,16M)) ++ ++$(eval $(call SingleProfile,Netgear,64kraw,WNR2200,wnr2200,WNR2200,ttyS0,115200,$$(wnr2200_mtdlayout),0x32323030,wnr2200,"" NA,)) ++ ++$(eval $(call SingleProfile,OpenMesh,squashfs-only,A60,a60,,,,A60)) ++$(eval $(call SingleProfile,OpenMesh,squashfs-only,OM2P,om2p,,,,OM2P)) ++$(eval $(call SingleProfile,OpenMesh,squashfs-only,OM5P,om5p,,,,OM5P)) ++$(eval $(call SingleProfile,OpenMesh,squashfs-only,OM5PAC,om5pac,,,,OM5PAC)) ++$(eval $(call SingleProfile,OpenMesh,squashfs-only,MR600,mr600,,,,MR600)) ++$(eval $(call SingleProfile,OpenMesh,squashfs-only,MR900,mr900,,,,MR900)) ++$(eval $(call SingleProfile,OpenMesh,squashfs-only,MR1750,mr1750,,,,MR1750)) ++ ++$(eval $(call SingleProfile,PB4X,128k,ALL0305,all0305,ALL0305,ttyS0,115200)) ++$(eval $(call SingleProfile,PB4X,128k,EAP7660D,eap7660d,EAP7660D,ttyS0,115200)) ++$(eval $(call SingleProfile,PB4X,64k,JA76PF,ja76pf,JA76PF,ttyS0,115200)) ++$(eval $(call SingleProfile,PB4X,64k,JA76PF2,ja76pf2,JA76PF2,ttyS0,115200)) ++$(eval $(call SingleProfile,PB4X,64k,JWAP003,jwap003,JWAP003,ttyS0,115200)) ++$(eval $(call SingleProfile,PB4X,64k,PB42,pb42,PB42,ttyS0,115200)) ++$(eval $(call SingleProfile,PB4X,64k,PB44,pb44,PB44,ttyS0,115200)) ++ ++$(eval $(call SingleProfile,Planex,64kraw,MZKW04NU,mzk-w04nu,MZK-W04NU,ttyS0,115200)) ++$(eval $(call SingleProfile,Planex,64kraw,MZKW300NH,mzk-w300nh,MZK-W300NH,ttyS0,115200)) ++ ++$(eval $(call SingleProfile,Senao,squashfs-only,EAP300V2,eap300v2,EAP300V2,ttyS0,115200,$$(eap300v2_mtdlayout))) ++ ++$(eval $(call SingleProfile,WRT400N,64k,WRT400N,wrt400n,WRT400N,ttyS0,115200)) ++ ++$(eval $(call SingleProfile,WZRHP128K,128kraw,WZRHPG300NH,wzr-hp-g300nh,WZR-HP-G300NH,ttyS0,115200,WZR-HP-G300NH)) ++$(eval $(call SingleProfile,WZRHP64K,64kraw,WZRHPG300NH2,wzr-hp-g300nh2,WZR-HP-G300NH2,ttyS0,115200,WZR-HP-G300NH2)) ++$(eval $(call SingleProfile,WZRHP64K,64kraw,WZRHPAG300H,wzr-hp-ag300h,WZR-HP-AG300H,ttyS0,115200,WZR-HP-AG300H)) ++$(eval $(call SingleProfile,WZRHP64K,64kraw,WZRHPG450H,wzr-hp-g450h,WZR-HP-G450H,ttyS0,115200,WZR-HP-AG450H)) ++$(eval $(call SingleProfile,WZRHP64K,64kraw,WZR600DHP,wzr-600dhp,WZR-HP-AG300H,ttyS0,115200,WZR-600DHP)) ++$(eval $(call SingleProfile,WZRHP64K,64kraw,WZR450HP2,wzr-450hp2,WZR-450HP2,ttyS0,115200,WZR-450HP2)) ++ ++$(eval $(call SingleProfile,Zcomax,64k,ZCN1523H28,zcn-1523h-2-8,ZCN-1523H-2,ttyS0,115200,$$(zcn1523h_mtdlayout))) ++$(eval $(call SingleProfile,Zcomax,64k,ZCN1523H516,zcn-1523h-5-16,ZCN-1523H-5,ttyS0,115200,$$(zcn1523h_mtdlayout))) ++ ++endif # ifeq ($(SUBTARGET),generic) ++ ++ ++ifeq ($(SUBTARGET),tiny) ++ ++$(eval $(call SingleProfile,Belkin,64k,F9K1115V2,f9k1115v2,F9K1115V2,ttyS0,115200,$$(f9k1115v2_mtdlayout),BR-6679BAC)) ++ ++$(eval $(call SingleProfile,CameoAP91,64kraw,DIR600A1,dir-600-a1,DIR-600-A1,ttyS0,115200,"AP91-AR7240-RT-090223-00")) ++$(eval $(call SingleProfile,CameoAP91,64kraw,DIR601A1,dir-601-a1,DIR-600-A1,ttyS0,115200,"AP91-AR7240-RT-090223-02")) ++$(eval $(call SingleProfile,CameoAP91,64kraw,FR54RTR,fr-54rtr,DIR-600-A1,ttyS0,115200,"AP91-AR7240-RT-090223-01")) ++ ++$(eval $(call SingleProfile,CameoAP99,64kraw,EBR2310C1,ebr-2310-c1,EBR-2310-C1,ttyS0,115200,"AP91-AR7240-RT-090223-03")) ++$(eval $(call SingleProfile,CameoAP99,64kraw,DIR615E1,dir-615-e1,DIR-615-E1,ttyS0,115200,"AP93-AR7240-RT-081028-00")) ++$(eval $(call SingleProfile,CameoAP99,64kraw,DIR615E4,dir-615-e4,DIR-615-E4,ttyS0,115200,"AP99-AR7240-RT-091105-05")) ++ ++$(eval $(call SingleProfile,CameoAP123_4M,64kraw,DIR615I1,dir-615-i1,DIR-615-I1,ttyS0,115200,"00DB120AR9341-RT-1012I1-00")) ++$(eval $(call SingleProfile,CameoAP123_4M,64kraw,DIR615I3,dir-615-i3,DIR-615-I1,ttyS0,115200,"00DB120AR9341-RT-101214-00")) ++ ++$(eval $(call SingleProfile,CameoAP81,64kraw-nojffs,A02RBW300N,a02-rb-w300n,TEW-632BRP,ttyS0,115200,"AP81-AR9130-RT-070614-03")) ++$(eval $(call SingleProfile,CameoAP81,64kraw-nojffs,DIR615C1,dir-615-c1,DIR-615-C1,ttyS0,115200,"AP81-AR9130-RT-070614-02")) ++$(eval $(call SingleProfile,CameoAP81,64kraw-nojffs,TEW632BRP,tew-632brp,TEW-632BRP,ttyS0,115200,"AP81-AR9130-RT-070614-00")) ++$(eval $(call SingleProfile,CameoAP81,64kraw-nojffs,TEW652BRP_FW,tew-652brp,TEW-632BRP,ttyS0,115200,"AP81-AR9130-RT-080609-05")) ++$(eval $(call SingleProfile,CameoAP81,64kraw-nojffs,TEW652BRP_RECOVERY,tew-652brp-recovery,TEW-632BRP,ttyS0,115200,"AP81-AR9130-RT-070614-02")) ++ ++$(eval $(call SingleProfile,CameoAP121,64kraw-nojffs,TEW712BR,tew-712br,TEW-712BR,ttyATH0,115200,"HORNET-RT-TEW712BR-3",1.99,"")) ++$(eval $(call SingleProfile,CameoAP121,64kraw-nojffs,DIR601B1,dir-601-b1,TEW-712BR,ttyATH0,115200,"HORNET-RT-DIR601B1-3",2.99.99,"" "NA")) ++ ++$(eval $(call SingleProfile,MyLoader,64k,WP543_4M,wp543,,ttyS0,115200,0x400000,4M)) ++$(eval $(call SingleProfile,MyLoader,64k,WPE72_4M,wpe72,,ttyS0,115200,0x400000,4M)) ++ ++$(eval $(call SingleProfile,Netgear,64kraw,WNR2000V3,wnr2000v3,WNR2000V3,ttyS0,115200,$$(wnr2000v3_mtdlayout),0x32303033,WNR2000V3,"" NA,-H 29763551+04+32)) ++$(eval $(call SingleProfile,NetgearLzma,64kraw,WNR2000V4,wnr2000v4,WNR2000V4,ttyS0,115200,$$(wnr2000v4_mtdlayout),0x32303034,WNR2000V4,"" NA,)) ++$(eval $(call SingleProfile,Netgear,64kraw,WNR2000,wnr2000,WNR2000,ttyS0,115200,$$(wnr2000_mtdlayout),0x32303031,WNR2000,"" NA,)) ++$(eval $(call SingleProfile,Netgear,64kraw,REALWNR612V2,wnr612v2,WNR612V2,ttyS0,115200,$$(wnr2000v3_mtdlayout),0x32303631,WNR612V2,"",)) ++$(eval $(call SingleProfile,Netgear,64kraw,N150R,n150r,WNR612V2,ttyS0,115200,$$(wnr2000v3_mtdlayout),0x32303631,N150R,"",)) ++$(eval $(call SingleProfile,Netgear,64kraw,REALWNR1000V2,wnr1000v2,WNR1000V2,ttyS0,115200,$$(wnr2000v3_mtdlayout),0x31303031,WNR1000V2,"",)) ++$(eval $(call SingleProfile,Netgear,64kraw,WNR1000V2_VC,wnr1000v2-vc,WNR1000V2,ttyS0,115200,$$(wnr2000v3_mtdlayout),0x31303030,WNR1000V2-VC,"",)) ++$(eval $(call SingleProfile,Netgear,64kraw,WPN824N,wpn824n,WPN824N,ttyS0,115200,$$(wnr2000v3_mtdlayout),0x31313030,WPN824N,"" NA,)) ++ ++$(eval $(call SingleProfile,WHRHPG300N,64kraw,WHRG301N,whr-g301n,WHR-G301N,ttyS0,115200,$$(whrhpg300n_mtdlayout),WHR-G301N)) ++$(eval $(call SingleProfile,WHRHPG300N,64kraw,WHRHPG300N,whr-hp-g300n,WHR-HP-G300N,ttyS0,115200,$$(whrhpg300n_mtdlayout),WHR-HP-G300N)) ++$(eval $(call SingleProfile,WHRHPG300N,64kraw,WHRHPGN,whr-hp-gn,WHR-HP-GN,ttyS0,115200,$$(whrhpg300n_mtdlayout),WHR-HP-GN)) ++$(eval $(call SingleProfile,WHRHPG300N,64kraw,WLAEAG300N,wlae-ag300n,WLAE-AG300N,ttyS0,115200,$$(whrhpg300n_mtdlayout),WLAE-AG300N)) ++ ++$(eval $(call SingleProfile,ZyXEL,64k,NBG_460N_550N_550NH,nbg460n_550n_550nh,NBG460N,ttyS0,115200,NBG-460N)) ++ ++endif # ifeq ($(SUBTARGET),tiny) ++ ++ ++ifeq ($(SUBTARGET),nand) ++ ++$(eval $(call SingleProfile,NetgearNAND,64k,WNDR3700V4,wndr3700v4,WNDR3700_V4,ttyS0,115200,$$(wndr4300_mtdlayout),0x33373033,WNDR3700v4,"",-H 29763948+128+128,wndr4300)) ++$(eval $(call SingleProfile,NetgearNAND,64k,WNDR4300V1,wndr4300,WNDR4300,ttyS0,115200,$$(wndr4300_mtdlayout),0x33373033,WNDR4300,"",-H 29763948+0+128+128+2x2+3x3,wndr4300)) ++$(eval $(call SingleProfile,NetgearNAND,64k,R6100,r6100,R6100,ttyS0,115200,$$(r6100_mtdlayout),0x36303030,R6100,"",-H 29764434+0+128+128+2x2+2x2,wndr4300)) ++ ++$(eval $(call SingleProfile,ZyXELNAND,128k,NBG6716,nbg6716,NBG6716,ttyS0,115200,NBG6716,$$(zyx_nbg6716_mtdlayout),mem=256M)) ++ ++endif # ifeq ($(SUBTARGET),nand) ++ ++define Image/Build/squashfs ++ cp $(KDIR)/root.squashfs $(KDIR)/root.squashfs-raw ++ cp $(KDIR)/root.squashfs $(KDIR)/root.squashfs-64k ++ $(STAGING_DIR_HOST)/bin/padjffs2 $(KDIR)/root.squashfs-64k 64 ++ $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) ++ dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) bs=128k conv=sync ++endef ++ ++define Image/Prepare ++ $(if $(wildcard $(ZYXEL_UBOOT_BIN)),cp $(ZYXEL_UBOOT_BIN) $(ZYXEL_UBOOT)) ++ $(call CompressLzma,$(KDIR)/vmlinux,$(KDIR)/vmlinux.bin.lzma) ++ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) ++ $(call CompressLzma,$(KDIR)/vmlinux-initramfs,$(KDIR)/vmlinux-initramfs.bin.lzma) ++ $(call Image/BuildLoader,generic,elf,,,-initramfs) ++endif ++ $(call Image/BuildLoader,generic,elf) ++endef ++ ++define Image/Prepare/Profile ++ $(call Image/Build/Profile/$(1),loader) ++endef ++ ++define Image/Build/Profile ++ $(call Image/Build/Profile/$(1),buildkernel) ++ $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(call Image/Build/Profile/$(1),initramfs)) ++ $(call Image/Build/Profile/$(1),$(2)) ++endef ++ ++# $(1): filesystem type. ++define Image/Build ++ $(call Image/Build/$(call rootfs_type,$(1)),$(1)) ++endef +diff --git a/target/linux/ar71xx/image/lzma-loader/Makefile b/target/linux/ar71xx/image/lzma-loader/Makefile +new file mode 100644 +index 0000000000..738093a958 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/Makefile +@@ -0,0 +1,70 @@ ++# ++# Copyright (C) 2011 OpenWrt.org ++# Copyright (C) 2011 Gabor Juhos ++# ++# This is free software, licensed under the GNU General Public License v2. ++# See /LICENSE for more information. ++# ++ ++include $(TOPDIR)/rules.mk ++ ++LZMA_TEXT_START := 0x80a00000 ++LOADADDR := 0x80060000 ++LOADER := loader.bin ++LOADER_NAME := $(basename $(notdir $(LOADER))) ++LOADER_DATA := ++TARGET_DIR := ++FLASH_OFFS := ++FLASH_MAX := ++BOARD := ++ ++ifeq ($(TARGET_DIR),) ++TARGET_DIR := $(KDIR) ++endif ++ ++LOADER_BIN := $(TARGET_DIR)/$(LOADER_NAME).bin ++LOADER_GZ := $(TARGET_DIR)/$(LOADER_NAME).gz ++LOADER_ELF := $(TARGET_DIR)/$(LOADER_NAME).elf ++ ++PKG_NAME := lzma-loader ++PKG_BUILD_DIR := $(KDIR)/$(PKG_NAME) ++ ++.PHONY : loader-compile loader.bin loader.elf loader.gz ++ ++$(PKG_BUILD_DIR)/.prepared: ++ mkdir $(PKG_BUILD_DIR) ++ $(CP) ./src/* $(PKG_BUILD_DIR)/ ++ touch $@ ++ ++loader-compile: $(PKG_BUILD_DIR)/.prepared ++ $(MAKE) -C $(PKG_BUILD_DIR) CROSS_COMPILE="$(TARGET_CROSS)" \ ++ LZMA_TEXT_START=$(LZMA_TEXT_START) \ ++ LOADADDR=$(LOADADDR) \ ++ LOADER_DATA=$(LOADER_DATA) \ ++ FLASH_OFFS=$(FLASH_OFFS) \ ++ FLASH_MAX=$(FLASH_MAX) \ ++ BOARD="$(BOARD)" \ ++ clean all ++ ++loader.gz: $(PKG_BUILD_DIR)/loader.bin ++ # Workaround for buggy bootloaders: Some devices ++ # (TP-Link TL-WR1043ND v1) don't work correctly when ++ # the uncompressed loader is too small (probably a cache ++ # invalidation issue) ++ dd if=$< bs=512K conv=sync | gzip -nc9 > $(LOADER_GZ) ++ ++loader.elf: $(PKG_BUILD_DIR)/loader.elf ++ $(CP) $< $(LOADER_ELF) ++ ++loader.bin: $(PKG_BUILD_DIR)/loader.bin ++ $(CP) $< $(LOADER_BIN) ++ ++download: ++prepare: $(PKG_BUILD_DIR)/.prepared ++compile: loader-compile ++ ++install: ++ ++clean: ++ rm -rf $(PKG_BUILD_DIR) ++ +diff --git a/target/linux/ar71xx/image/lzma-loader/src/LzmaDecode.c b/target/linux/ar71xx/image/lzma-loader/src/LzmaDecode.c +new file mode 100644 +index 0000000000..cb8345377e +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/LzmaDecode.c +@@ -0,0 +1,584 @@ ++/* ++ LzmaDecode.c ++ LZMA Decoder (optimized for Speed version) ++ ++ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) ++ http://www.7-zip.org/ ++ ++ LZMA SDK is licensed under two licenses: ++ 1) GNU Lesser General Public License (GNU LGPL) ++ 2) Common Public License (CPL) ++ It means that you can select one of these two licenses and ++ follow rules of that license. ++ ++ SPECIAL EXCEPTION: ++ Igor Pavlov, as the author of this Code, expressly permits you to ++ statically or dynamically link your Code (or bind by name) to the ++ interfaces of this file without subjecting your linked Code to the ++ terms of the CPL or GNU LGPL. Any modifications or additions ++ to this file, however, are subject to the LGPL or CPL terms. ++*/ ++ ++#include "LzmaDecode.h" ++ ++#define kNumTopBits 24 ++#define kTopValue ((UInt32)1 << kNumTopBits) ++ ++#define kNumBitModelTotalBits 11 ++#define kBitModelTotal (1 << kNumBitModelTotalBits) ++#define kNumMoveBits 5 ++ ++#define RC_READ_BYTE (*Buffer++) ++ ++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ ++ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} ++ ++#ifdef _LZMA_IN_CB ++ ++#define RC_TEST { if (Buffer == BufferLim) \ ++ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ ++ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} ++ ++#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 ++ ++#else ++ ++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } ++ ++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 ++ ++#endif ++ ++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } ++ ++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) ++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; ++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; ++ ++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ ++ { UpdateBit0(p); mi <<= 1; A0; } else \ ++ { UpdateBit1(p); mi = (mi + mi) + 1; A1; } ++ ++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) ++ ++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ ++ { int i = numLevels; res = 1; \ ++ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ ++ res -= (1 << numLevels); } ++ ++ ++#define kNumPosBitsMax 4 ++#define kNumPosStatesMax (1 << kNumPosBitsMax) ++ ++#define kLenNumLowBits 3 ++#define kLenNumLowSymbols (1 << kLenNumLowBits) ++#define kLenNumMidBits 3 ++#define kLenNumMidSymbols (1 << kLenNumMidBits) ++#define kLenNumHighBits 8 ++#define kLenNumHighSymbols (1 << kLenNumHighBits) ++ ++#define LenChoice 0 ++#define LenChoice2 (LenChoice + 1) ++#define LenLow (LenChoice2 + 1) ++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) ++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) ++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) ++ ++ ++#define kNumStates 12 ++#define kNumLitStates 7 ++ ++#define kStartPosModelIndex 4 ++#define kEndPosModelIndex 14 ++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) ++ ++#define kNumPosSlotBits 6 ++#define kNumLenToPosStates 4 ++ ++#define kNumAlignBits 4 ++#define kAlignTableSize (1 << kNumAlignBits) ++ ++#define kMatchMinLen 2 ++ ++#define IsMatch 0 ++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) ++#define IsRepG0 (IsRep + kNumStates) ++#define IsRepG1 (IsRepG0 + kNumStates) ++#define IsRepG2 (IsRepG1 + kNumStates) ++#define IsRep0Long (IsRepG2 + kNumStates) ++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) ++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) ++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) ++#define LenCoder (Align + kAlignTableSize) ++#define RepLenCoder (LenCoder + kNumLenProbs) ++#define Literal (RepLenCoder + kNumLenProbs) ++ ++#if Literal != LZMA_BASE_SIZE ++StopCompilingDueBUG ++#endif ++ ++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) ++{ ++ unsigned char prop0; ++ if (size < LZMA_PROPERTIES_SIZE) ++ return LZMA_RESULT_DATA_ERROR; ++ prop0 = propsData[0]; ++ if (prop0 >= (9 * 5 * 5)) ++ return LZMA_RESULT_DATA_ERROR; ++ { ++ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); ++ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); ++ propsRes->lc = prop0; ++ /* ++ unsigned char remainder = (unsigned char)(prop0 / 9); ++ propsRes->lc = prop0 % 9; ++ propsRes->pb = remainder / 5; ++ propsRes->lp = remainder % 5; ++ */ ++ } ++ ++ #ifdef _LZMA_OUT_READ ++ { ++ int i; ++ propsRes->DictionarySize = 0; ++ for (i = 0; i < 4; i++) ++ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); ++ if (propsRes->DictionarySize == 0) ++ propsRes->DictionarySize = 1; ++ } ++ #endif ++ return LZMA_RESULT_OK; ++} ++ ++#define kLzmaStreamWasFinishedId (-1) ++ ++int LzmaDecode(CLzmaDecoderState *vs, ++ #ifdef _LZMA_IN_CB ++ ILzmaInCallback *InCallback, ++ #else ++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, ++ #endif ++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) ++{ ++ CProb *p = vs->Probs; ++ SizeT nowPos = 0; ++ Byte previousByte = 0; ++ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; ++ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; ++ int lc = vs->Properties.lc; ++ ++ #ifdef _LZMA_OUT_READ ++ ++ UInt32 Range = vs->Range; ++ UInt32 Code = vs->Code; ++ #ifdef _LZMA_IN_CB ++ const Byte *Buffer = vs->Buffer; ++ const Byte *BufferLim = vs->BufferLim; ++ #else ++ const Byte *Buffer = inStream; ++ const Byte *BufferLim = inStream + inSize; ++ #endif ++ int state = vs->State; ++ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; ++ int len = vs->RemainLen; ++ UInt32 globalPos = vs->GlobalPos; ++ UInt32 distanceLimit = vs->DistanceLimit; ++ ++ Byte *dictionary = vs->Dictionary; ++ UInt32 dictionarySize = vs->Properties.DictionarySize; ++ UInt32 dictionaryPos = vs->DictionaryPos; ++ ++ Byte tempDictionary[4]; ++ ++ #ifndef _LZMA_IN_CB ++ *inSizeProcessed = 0; ++ #endif ++ *outSizeProcessed = 0; ++ if (len == kLzmaStreamWasFinishedId) ++ return LZMA_RESULT_OK; ++ ++ if (dictionarySize == 0) ++ { ++ dictionary = tempDictionary; ++ dictionarySize = 1; ++ tempDictionary[0] = vs->TempDictionary[0]; ++ } ++ ++ if (len == kLzmaNeedInitId) ++ { ++ { ++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); ++ UInt32 i; ++ for (i = 0; i < numProbs; i++) ++ p[i] = kBitModelTotal >> 1; ++ rep0 = rep1 = rep2 = rep3 = 1; ++ state = 0; ++ globalPos = 0; ++ distanceLimit = 0; ++ dictionaryPos = 0; ++ dictionary[dictionarySize - 1] = 0; ++ #ifdef _LZMA_IN_CB ++ RC_INIT; ++ #else ++ RC_INIT(inStream, inSize); ++ #endif ++ } ++ len = 0; ++ } ++ while(len != 0 && nowPos < outSize) ++ { ++ UInt32 pos = dictionaryPos - rep0; ++ if (pos >= dictionarySize) ++ pos += dictionarySize; ++ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; ++ if (++dictionaryPos == dictionarySize) ++ dictionaryPos = 0; ++ len--; ++ } ++ if (dictionaryPos == 0) ++ previousByte = dictionary[dictionarySize - 1]; ++ else ++ previousByte = dictionary[dictionaryPos - 1]; ++ ++ #else /* if !_LZMA_OUT_READ */ ++ ++ int state = 0; ++ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; ++ int len = 0; ++ const Byte *Buffer; ++ const Byte *BufferLim; ++ UInt32 Range; ++ UInt32 Code; ++ ++ #ifndef _LZMA_IN_CB ++ *inSizeProcessed = 0; ++ #endif ++ *outSizeProcessed = 0; ++ ++ { ++ UInt32 i; ++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); ++ for (i = 0; i < numProbs; i++) ++ p[i] = kBitModelTotal >> 1; ++ } ++ ++ #ifdef _LZMA_IN_CB ++ RC_INIT; ++ #else ++ RC_INIT(inStream, inSize); ++ #endif ++ ++ #endif /* _LZMA_OUT_READ */ ++ ++ while(nowPos < outSize) ++ { ++ CProb *prob; ++ UInt32 bound; ++ int posState = (int)( ++ (nowPos ++ #ifdef _LZMA_OUT_READ ++ + globalPos ++ #endif ++ ) ++ & posStateMask); ++ ++ prob = p + IsMatch + (state << kNumPosBitsMax) + posState; ++ IfBit0(prob) ++ { ++ int symbol = 1; ++ UpdateBit0(prob) ++ prob = p + Literal + (LZMA_LIT_SIZE * ++ ((( ++ (nowPos ++ #ifdef _LZMA_OUT_READ ++ + globalPos ++ #endif ++ ) ++ & literalPosMask) << lc) + (previousByte >> (8 - lc)))); ++ ++ if (state >= kNumLitStates) ++ { ++ int matchByte; ++ #ifdef _LZMA_OUT_READ ++ UInt32 pos = dictionaryPos - rep0; ++ if (pos >= dictionarySize) ++ pos += dictionarySize; ++ matchByte = dictionary[pos]; ++ #else ++ matchByte = outStream[nowPos - rep0]; ++ #endif ++ do ++ { ++ int bit; ++ CProb *probLit; ++ matchByte <<= 1; ++ bit = (matchByte & 0x100); ++ probLit = prob + 0x100 + bit + symbol; ++ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) ++ } ++ while (symbol < 0x100); ++ } ++ while (symbol < 0x100) ++ { ++ CProb *probLit = prob + symbol; ++ RC_GET_BIT(probLit, symbol) ++ } ++ previousByte = (Byte)symbol; ++ ++ outStream[nowPos++] = previousByte; ++ #ifdef _LZMA_OUT_READ ++ if (distanceLimit < dictionarySize) ++ distanceLimit++; ++ ++ dictionary[dictionaryPos] = previousByte; ++ if (++dictionaryPos == dictionarySize) ++ dictionaryPos = 0; ++ #endif ++ if (state < 4) state = 0; ++ else if (state < 10) state -= 3; ++ else state -= 6; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ prob = p + IsRep + state; ++ IfBit0(prob) ++ { ++ UpdateBit0(prob); ++ rep3 = rep2; ++ rep2 = rep1; ++ rep1 = rep0; ++ state = state < kNumLitStates ? 0 : 3; ++ prob = p + LenCoder; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ prob = p + IsRepG0 + state; ++ IfBit0(prob) ++ { ++ UpdateBit0(prob); ++ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; ++ IfBit0(prob) ++ { ++ #ifdef _LZMA_OUT_READ ++ UInt32 pos; ++ #endif ++ UpdateBit0(prob); ++ ++ #ifdef _LZMA_OUT_READ ++ if (distanceLimit == 0) ++ #else ++ if (nowPos == 0) ++ #endif ++ return LZMA_RESULT_DATA_ERROR; ++ ++ state = state < kNumLitStates ? 9 : 11; ++ #ifdef _LZMA_OUT_READ ++ pos = dictionaryPos - rep0; ++ if (pos >= dictionarySize) ++ pos += dictionarySize; ++ previousByte = dictionary[pos]; ++ dictionary[dictionaryPos] = previousByte; ++ if (++dictionaryPos == dictionarySize) ++ dictionaryPos = 0; ++ #else ++ previousByte = outStream[nowPos - rep0]; ++ #endif ++ outStream[nowPos++] = previousByte; ++ #ifdef _LZMA_OUT_READ ++ if (distanceLimit < dictionarySize) ++ distanceLimit++; ++ #endif ++ ++ continue; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ } ++ } ++ else ++ { ++ UInt32 distance; ++ UpdateBit1(prob); ++ prob = p + IsRepG1 + state; ++ IfBit0(prob) ++ { ++ UpdateBit0(prob); ++ distance = rep1; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ prob = p + IsRepG2 + state; ++ IfBit0(prob) ++ { ++ UpdateBit0(prob); ++ distance = rep2; ++ } ++ else ++ { ++ UpdateBit1(prob); ++ distance = rep3; ++ rep3 = rep2; ++ } ++ rep2 = rep1; ++ } ++ rep1 = rep0; ++ rep0 = distance; ++ } ++ state = state < kNumLitStates ? 8 : 11; ++ prob = p + RepLenCoder; ++ } ++ { ++ int numBits, offset; ++ CProb *probLen = prob + LenChoice; ++ IfBit0(probLen) ++ { ++ UpdateBit0(probLen); ++ probLen = prob + LenLow + (posState << kLenNumLowBits); ++ offset = 0; ++ numBits = kLenNumLowBits; ++ } ++ else ++ { ++ UpdateBit1(probLen); ++ probLen = prob + LenChoice2; ++ IfBit0(probLen) ++ { ++ UpdateBit0(probLen); ++ probLen = prob + LenMid + (posState << kLenNumMidBits); ++ offset = kLenNumLowSymbols; ++ numBits = kLenNumMidBits; ++ } ++ else ++ { ++ UpdateBit1(probLen); ++ probLen = prob + LenHigh; ++ offset = kLenNumLowSymbols + kLenNumMidSymbols; ++ numBits = kLenNumHighBits; ++ } ++ } ++ RangeDecoderBitTreeDecode(probLen, numBits, len); ++ len += offset; ++ } ++ ++ if (state < 4) ++ { ++ int posSlot; ++ state += kNumLitStates; ++ prob = p + PosSlot + ++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << ++ kNumPosSlotBits); ++ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); ++ if (posSlot >= kStartPosModelIndex) ++ { ++ int numDirectBits = ((posSlot >> 1) - 1); ++ rep0 = (2 | ((UInt32)posSlot & 1)); ++ if (posSlot < kEndPosModelIndex) ++ { ++ rep0 <<= numDirectBits; ++ prob = p + SpecPos + rep0 - posSlot - 1; ++ } ++ else ++ { ++ numDirectBits -= kNumAlignBits; ++ do ++ { ++ RC_NORMALIZE ++ Range >>= 1; ++ rep0 <<= 1; ++ if (Code >= Range) ++ { ++ Code -= Range; ++ rep0 |= 1; ++ } ++ } ++ while (--numDirectBits != 0); ++ prob = p + Align; ++ rep0 <<= kNumAlignBits; ++ numDirectBits = kNumAlignBits; ++ } ++ { ++ int i = 1; ++ int mi = 1; ++ do ++ { ++ CProb *prob3 = prob + mi; ++ RC_GET_BIT2(prob3, mi, ; , rep0 |= i); ++ i <<= 1; ++ } ++ while(--numDirectBits != 0); ++ } ++ } ++ else ++ rep0 = posSlot; ++ if (++rep0 == (UInt32)(0)) ++ { ++ /* it's for stream version */ ++ len = kLzmaStreamWasFinishedId; ++ break; ++ } ++ } ++ ++ len += kMatchMinLen; ++ #ifdef _LZMA_OUT_READ ++ if (rep0 > distanceLimit) ++ #else ++ if (rep0 > nowPos) ++ #endif ++ return LZMA_RESULT_DATA_ERROR; ++ ++ #ifdef _LZMA_OUT_READ ++ if (dictionarySize - distanceLimit > (UInt32)len) ++ distanceLimit += len; ++ else ++ distanceLimit = dictionarySize; ++ #endif ++ ++ do ++ { ++ #ifdef _LZMA_OUT_READ ++ UInt32 pos = dictionaryPos - rep0; ++ if (pos >= dictionarySize) ++ pos += dictionarySize; ++ previousByte = dictionary[pos]; ++ dictionary[dictionaryPos] = previousByte; ++ if (++dictionaryPos == dictionarySize) ++ dictionaryPos = 0; ++ #else ++ previousByte = outStream[nowPos - rep0]; ++ #endif ++ len--; ++ outStream[nowPos++] = previousByte; ++ } ++ while(len != 0 && nowPos < outSize); ++ } ++ } ++ RC_NORMALIZE; ++ ++ #ifdef _LZMA_OUT_READ ++ vs->Range = Range; ++ vs->Code = Code; ++ vs->DictionaryPos = dictionaryPos; ++ vs->GlobalPos = globalPos + (UInt32)nowPos; ++ vs->DistanceLimit = distanceLimit; ++ vs->Reps[0] = rep0; ++ vs->Reps[1] = rep1; ++ vs->Reps[2] = rep2; ++ vs->Reps[3] = rep3; ++ vs->State = state; ++ vs->RemainLen = len; ++ vs->TempDictionary[0] = tempDictionary[0]; ++ #endif ++ ++ #ifdef _LZMA_IN_CB ++ vs->Buffer = Buffer; ++ vs->BufferLim = BufferLim; ++ #else ++ *inSizeProcessed = (SizeT)(Buffer - inStream); ++ #endif ++ *outSizeProcessed = nowPos; ++ return LZMA_RESULT_OK; ++} +diff --git a/target/linux/ar71xx/image/lzma-loader/src/LzmaDecode.h b/target/linux/ar71xx/image/lzma-loader/src/LzmaDecode.h +new file mode 100644 +index 0000000000..2870eeb9c9 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/LzmaDecode.h +@@ -0,0 +1,113 @@ ++/* ++ LzmaDecode.h ++ LZMA Decoder interface ++ ++ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) ++ http://www.7-zip.org/ ++ ++ LZMA SDK is licensed under two licenses: ++ 1) GNU Lesser General Public License (GNU LGPL) ++ 2) Common Public License (CPL) ++ It means that you can select one of these two licenses and ++ follow rules of that license. ++ ++ SPECIAL EXCEPTION: ++ Igor Pavlov, as the author of this code, expressly permits you to ++ statically or dynamically link your code (or bind by name) to the ++ interfaces of this file without subjecting your linked code to the ++ terms of the CPL or GNU LGPL. Any modifications or additions ++ to this file, however, are subject to the LGPL or CPL terms. ++*/ ++ ++#ifndef __LZMADECODE_H ++#define __LZMADECODE_H ++ ++#include "LzmaTypes.h" ++ ++/* #define _LZMA_IN_CB */ ++/* Use callback for input data */ ++ ++/* #define _LZMA_OUT_READ */ ++/* Use read function for output data */ ++ ++/* #define _LZMA_PROB32 */ ++/* It can increase speed on some 32-bit CPUs, ++ but memory usage will be doubled in that case */ ++ ++/* #define _LZMA_LOC_OPT */ ++/* Enable local speed optimizations inside code */ ++ ++#ifdef _LZMA_PROB32 ++#define CProb UInt32 ++#else ++#define CProb UInt16 ++#endif ++ ++#define LZMA_RESULT_OK 0 ++#define LZMA_RESULT_DATA_ERROR 1 ++ ++#ifdef _LZMA_IN_CB ++typedef struct _ILzmaInCallback ++{ ++ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); ++} ILzmaInCallback; ++#endif ++ ++#define LZMA_BASE_SIZE 1846 ++#define LZMA_LIT_SIZE 768 ++ ++#define LZMA_PROPERTIES_SIZE 5 ++ ++typedef struct _CLzmaProperties ++{ ++ int lc; ++ int lp; ++ int pb; ++ #ifdef _LZMA_OUT_READ ++ UInt32 DictionarySize; ++ #endif ++}CLzmaProperties; ++ ++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); ++ ++#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) ++ ++#define kLzmaNeedInitId (-2) ++ ++typedef struct _CLzmaDecoderState ++{ ++ CLzmaProperties Properties; ++ CProb *Probs; ++ ++ #ifdef _LZMA_IN_CB ++ const unsigned char *Buffer; ++ const unsigned char *BufferLim; ++ #endif ++ ++ #ifdef _LZMA_OUT_READ ++ unsigned char *Dictionary; ++ UInt32 Range; ++ UInt32 Code; ++ UInt32 DictionaryPos; ++ UInt32 GlobalPos; ++ UInt32 DistanceLimit; ++ UInt32 Reps[4]; ++ int State; ++ int RemainLen; ++ unsigned char TempDictionary[4]; ++ #endif ++} CLzmaDecoderState; ++ ++#ifdef _LZMA_OUT_READ ++#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } ++#endif ++ ++int LzmaDecode(CLzmaDecoderState *vs, ++ #ifdef _LZMA_IN_CB ++ ILzmaInCallback *inCallback, ++ #else ++ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, ++ #endif ++ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); ++ ++#endif +diff --git a/target/linux/ar71xx/image/lzma-loader/src/LzmaTypes.h b/target/linux/ar71xx/image/lzma-loader/src/LzmaTypes.h +new file mode 100644 +index 0000000000..9c27290757 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/LzmaTypes.h +@@ -0,0 +1,45 @@ ++/* ++LzmaTypes.h ++ ++Types for LZMA Decoder ++ ++This file written and distributed to public domain by Igor Pavlov. ++This file is part of LZMA SDK 4.40 (2006-05-01) ++*/ ++ ++#ifndef __LZMATYPES_H ++#define __LZMATYPES_H ++ ++#ifndef _7ZIP_BYTE_DEFINED ++#define _7ZIP_BYTE_DEFINED ++typedef unsigned char Byte; ++#endif ++ ++#ifndef _7ZIP_UINT16_DEFINED ++#define _7ZIP_UINT16_DEFINED ++typedef unsigned short UInt16; ++#endif ++ ++#ifndef _7ZIP_UINT32_DEFINED ++#define _7ZIP_UINT32_DEFINED ++#ifdef _LZMA_UINT32_IS_ULONG ++typedef unsigned long UInt32; ++#else ++typedef unsigned int UInt32; ++#endif ++#endif ++ ++/* #define _LZMA_NO_SYSTEM_SIZE_T */ ++/* You can use it, if you don't want */ ++ ++#ifndef _7ZIP_SIZET_DEFINED ++#define _7ZIP_SIZET_DEFINED ++#ifdef _LZMA_NO_SYSTEM_SIZE_T ++typedef UInt32 SizeT; ++#else ++#include ++typedef size_t SizeT; ++#endif ++#endif ++ ++#endif +diff --git a/target/linux/ar71xx/image/lzma-loader/src/Makefile b/target/linux/ar71xx/image/lzma-loader/src/Makefile +new file mode 100644 +index 0000000000..7773f027a2 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/Makefile +@@ -0,0 +1,108 @@ ++# ++# Makefile for the LZMA compressed kernel loader for ++# Atheros AR7XXX/AR9XXX based boards ++# ++# Copyright (C) 2011 Gabor Juhos ++# ++# Some parts of this file was based on the OpenWrt specific lzma-loader ++# for the BCM47xx and ADM5120 based boards: ++# Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org) ++# Copyright (C) 2005 Mineharu Takahara ++# Copyright (C) 2005 by Oleg I. Vdovikin ++# ++# 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. ++# ++ ++LOADADDR := ++LZMA_TEXT_START := 0x80a00000 ++LOADER_DATA := ++BOARD := ++FLASH_OFFS := ++FLASH_MAX := ++ ++CC := $(CROSS_COMPILE)gcc ++LD := $(CROSS_COMPILE)ld ++OBJCOPY := $(CROSS_COMPILE)objcopy ++OBJDUMP := $(CROSS_COMPILE)objdump ++ ++BIN_FLAGS := -O binary -R .reginfo -R .note -R .comment -R .mdebug \ ++ -R .MIPS.abiflags -S ++ ++CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \ ++ -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 \ ++ -mno-abicalls -fno-pic -ffunction-sections -pipe -mlong-calls \ ++ -fno-common -ffreestanding -fhonour-copts -nostartfiles \ ++ -mabi=32 -march=mips32r2 \ ++ -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap ++CFLAGS += -D_LZMA_PROB32 ++CFLAGS += -flto ++ ++ASFLAGS = $(CFLAGS) -D__ASSEMBLY__ ++ ++LDFLAGS = -static -Wl,--gc-sections -Wl,-no-warn-mismatch ++LDFLAGS += -Wl,-e,startup -T loader.lds -Wl,-Ttext,$(LZMA_TEXT_START) ++LDFLAGS += -flto -fwhole-program ++ ++O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32) ++ ++OBJECTS := head.o loader.o cache.o board.o printf.o LzmaDecode.o ++ ++ifneq ($(strip $(LOADER_DATA)),) ++OBJECTS += data.o ++CFLAGS += -DLZMA_WRAPPER=1 -DLOADADDR=$(LOADADDR) ++endif ++ ++ifneq ($(strip $(KERNEL_CMDLINE)),) ++CFLAGS += -DCONFIG_KERNEL_CMDLINE='"$(KERNEL_CMDLINE)"' ++endif ++ ++ifneq ($(strip $(FLASH_OFFS)),) ++CFLAGS += -DCONFIG_FLASH_OFFS=$(FLASH_OFFS) ++endif ++ ++ifneq ($(strip $(FLASH_MAX)),) ++CFLAGS += -DCONFIG_FLASH_MAX=$(FLASH_MAX) ++endif ++ ++BOARD_DEF := $(shell echo $(strip $(BOARD)) | tr a-z A-Z | tr - _) ++ifneq ($(BOARD_DEF),) ++CFLAGS += -DCONFIG_BOARD_$(BOARD_DEF) ++endif ++ ++all: loader.elf ++ ++# Don't build dependencies, this may die if $(CC) isn't gcc ++dep: ++ ++install: ++ ++%.o : %.c ++ $(CC) $(CFLAGS) -c -o $@ $< ++ ++%.o : %.S ++ $(CC) $(ASFLAGS) -c -o $@ $< ++ ++data.o: $(LOADER_DATA) ++ $(LD) -r -b binary --oformat $(O_FORMAT) -T lzma-data.lds -o $@ $< ++ ++loader: $(OBJECTS) ++ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) ++ ++loader.bin: loader ++ $(OBJCOPY) $(BIN_FLAGS) $< $@ ++ ++loader2.o: loader.bin ++ $(LD) -r -b binary --oformat $(O_FORMAT) -o $@ $< ++ ++loader.elf: loader2.o ++ $(LD) -z max-page-size=0x1000 -e startup -T loader2.lds -Ttext $(LOADADDR) -o $@ $< ++ ++mrproper: clean ++ ++clean: ++ rm -f loader *.elf *.bin *.o ++ ++ ++ +diff --git a/target/linux/ar71xx/image/lzma-loader/src/ar71xx_regs.h b/target/linux/ar71xx/image/lzma-loader/src/ar71xx_regs.h +new file mode 100644 +index 0000000000..19a4785bb4 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/ar71xx_regs.h +@@ -0,0 +1,725 @@ ++/* ++ * Atheros AR71XX/AR724X/AR913X SoC register definitions ++ * ++ * Copyright (C) 2010-2011 Jaiganesh Narayanan ++ * Copyright (C) 2008-2010 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP ++ * ++ * 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 __ASM_MACH_AR71XX_REGS_H ++#define __ASM_MACH_AR71XX_REGS_H ++ ++#define BIT(_x) (1UL << (_x)) ++ ++#define AR71XX_APB_BASE 0x18000000 ++#define AR71XX_GE0_BASE 0x19000000 ++#define AR71XX_GE0_SIZE 0x10000 ++#define AR71XX_GE1_BASE 0x1a000000 ++#define AR71XX_GE1_SIZE 0x10000 ++#define AR71XX_EHCI_BASE 0x1b000000 ++#define AR71XX_EHCI_SIZE 0x1000 ++#define AR71XX_OHCI_BASE 0x1c000000 ++#define AR71XX_OHCI_SIZE 0x1000 ++#define AR71XX_SPI_BASE 0x1f000000 ++#define AR71XX_SPI_SIZE 0x01000000 ++ ++#define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000) ++#define AR71XX_DDR_CTRL_SIZE 0x100 ++#define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000) ++#define AR71XX_UART_SIZE 0x100 ++#define AR71XX_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) ++#define AR71XX_USB_CTRL_SIZE 0x100 ++#define AR71XX_GPIO_BASE (AR71XX_APB_BASE + 0x00040000) ++#define AR71XX_GPIO_SIZE 0x100 ++#define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000) ++#define AR71XX_PLL_SIZE 0x100 ++#define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000) ++#define AR71XX_RESET_SIZE 0x100 ++#define AR71XX_MII_BASE (AR71XX_APB_BASE + 0x00070000) ++#define AR71XX_MII_SIZE 0x100 ++ ++#define AR71XX_PCI_MEM_BASE 0x10000000 ++#define AR71XX_PCI_MEM_SIZE 0x07000000 ++ ++#define AR71XX_PCI_WIN0_OFFS 0x10000000 ++#define AR71XX_PCI_WIN1_OFFS 0x11000000 ++#define AR71XX_PCI_WIN2_OFFS 0x12000000 ++#define AR71XX_PCI_WIN3_OFFS 0x13000000 ++#define AR71XX_PCI_WIN4_OFFS 0x14000000 ++#define AR71XX_PCI_WIN5_OFFS 0x15000000 ++#define AR71XX_PCI_WIN6_OFFS 0x16000000 ++#define AR71XX_PCI_WIN7_OFFS 0x07000000 ++ ++#define AR71XX_PCI_CFG_BASE \ ++ (AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000) ++#define AR71XX_PCI_CFG_SIZE 0x100 ++ ++#define AR7240_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) ++#define AR7240_USB_CTRL_SIZE 0x100 ++#define AR7240_OHCI_BASE 0x1b000000 ++#define AR7240_OHCI_SIZE 0x1000 ++ ++#define AR724X_PCI_MEM_BASE 0x10000000 ++#define AR724X_PCI_MEM_SIZE 0x04000000 ++ ++#define AR724X_PCI_CFG_BASE 0x14000000 ++#define AR724X_PCI_CFG_SIZE 0x1000 ++#define AR724X_PCI_CRP_BASE (AR71XX_APB_BASE + 0x000c0000) ++#define AR724X_PCI_CRP_SIZE 0x1000 ++#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000) ++#define AR724X_PCI_CTRL_SIZE 0x100 ++ ++#define AR724X_EHCI_BASE 0x1b000000 ++#define AR724X_EHCI_SIZE 0x1000 ++ ++#define AR913X_EHCI_BASE 0x1b000000 ++#define AR913X_EHCI_SIZE 0x1000 ++#define AR913X_WMAC_BASE (AR71XX_APB_BASE + 0x000C0000) ++#define AR913X_WMAC_SIZE 0x30000 ++ ++#define AR933X_UART_BASE (AR71XX_APB_BASE + 0x00020000) ++#define AR933X_UART_SIZE 0x14 ++#define AR933X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) ++#define AR933X_GMAC_SIZE 0x04 ++#define AR933X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) ++#define AR933X_WMAC_SIZE 0x20000 ++#define AR933X_EHCI_BASE 0x1b000000 ++#define AR933X_EHCI_SIZE 0x1000 ++ ++#define AR934X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) ++#define AR934X_GMAC_SIZE 0x14 ++#define AR934X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) ++#define AR934X_WMAC_SIZE 0x20000 ++#define AR934X_EHCI_BASE 0x1b000000 ++#define AR934X_EHCI_SIZE 0x200 ++ ++#define QCA955X_PCI_MEM_BASE0 0x10000000 ++#define QCA955X_PCI_MEM_BASE1 0x12000000 ++#define QCA955X_PCI_MEM_SIZE 0x02000000 ++#define QCA955X_PCI_CFG_BASE0 0x14000000 ++#define QCA955X_PCI_CFG_BASE1 0x16000000 ++#define QCA955X_PCI_CFG_SIZE 0x1000 ++#define QCA955X_PCI_CRP_BASE0 (AR71XX_APB_BASE + 0x000c0000) ++#define QCA955X_PCI_CRP_BASE1 (AR71XX_APB_BASE + 0x00250000) ++#define QCA955X_PCI_CRP_SIZE 0x1000 ++#define QCA955X_PCI_CTRL_BASE0 (AR71XX_APB_BASE + 0x000f0000) ++#define QCA955X_PCI_CTRL_BASE1 (AR71XX_APB_BASE + 0x00280000) ++#define QCA955X_PCI_CTRL_SIZE 0x100 ++ ++#define QCA955X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) ++#define QCA955X_WMAC_SIZE 0x20000 ++#define QCA955X_EHCI0_BASE 0x1b000000 ++#define QCA955X_EHCI1_BASE 0x1b400000 ++#define QCA955X_EHCI_SIZE 0x1000 ++#define QCA955X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) ++#define QCA955X_GMAC_SIZE 0x40 ++ ++#define AR9300_OTP_BASE 0x14000 ++#define AR9300_OTP_STATUS 0x15f18 ++#define AR9300_OTP_STATUS_TYPE 0x7 ++#define AR9300_OTP_STATUS_VALID 0x4 ++#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 ++#define AR9300_OTP_STATUS_SM_BUSY 0x1 ++#define AR9300_OTP_READ_DATA 0x15f1c ++ ++/* ++ * DDR_CTRL block ++ */ ++#define AR71XX_DDR_REG_PCI_WIN0 0x7c ++#define AR71XX_DDR_REG_PCI_WIN1 0x80 ++#define AR71XX_DDR_REG_PCI_WIN2 0x84 ++#define AR71XX_DDR_REG_PCI_WIN3 0x88 ++#define AR71XX_DDR_REG_PCI_WIN4 0x8c ++#define AR71XX_DDR_REG_PCI_WIN5 0x90 ++#define AR71XX_DDR_REG_PCI_WIN6 0x94 ++#define AR71XX_DDR_REG_PCI_WIN7 0x98 ++#define AR71XX_DDR_REG_FLUSH_GE0 0x9c ++#define AR71XX_DDR_REG_FLUSH_GE1 0xa0 ++#define AR71XX_DDR_REG_FLUSH_USB 0xa4 ++#define AR71XX_DDR_REG_FLUSH_PCI 0xa8 ++ ++#define AR724X_DDR_REG_FLUSH_GE0 0x7c ++#define AR724X_DDR_REG_FLUSH_GE1 0x80 ++#define AR724X_DDR_REG_FLUSH_USB 0x84 ++#define AR724X_DDR_REG_FLUSH_PCIE 0x88 ++ ++#define AR913X_DDR_REG_FLUSH_GE0 0x7c ++#define AR913X_DDR_REG_FLUSH_GE1 0x80 ++#define AR913X_DDR_REG_FLUSH_USB 0x84 ++#define AR913X_DDR_REG_FLUSH_WMAC 0x88 ++ ++#define AR933X_DDR_REG_FLUSH_GE0 0x7c ++#define AR933X_DDR_REG_FLUSH_GE1 0x80 ++#define AR933X_DDR_REG_FLUSH_USB 0x84 ++#define AR933X_DDR_REG_FLUSH_WMAC 0x88 ++ ++#define AR934X_DDR_REG_FLUSH_GE0 0x9c ++#define AR934X_DDR_REG_FLUSH_GE1 0xa0 ++#define AR934X_DDR_REG_FLUSH_USB 0xa4 ++#define AR934X_DDR_REG_FLUSH_PCIE 0xa8 ++#define AR934X_DDR_REG_FLUSH_WMAC 0xac ++ ++/* ++ * PLL block ++ */ ++#define AR71XX_PLL_REG_CPU_CONFIG 0x00 ++#define AR71XX_PLL_REG_SEC_CONFIG 0x04 ++#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10 ++#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14 ++ ++#define AR71XX_PLL_DIV_SHIFT 3 ++#define AR71XX_PLL_DIV_MASK 0x1f ++#define AR71XX_CPU_DIV_SHIFT 16 ++#define AR71XX_CPU_DIV_MASK 0x3 ++#define AR71XX_DDR_DIV_SHIFT 18 ++#define AR71XX_DDR_DIV_MASK 0x3 ++#define AR71XX_AHB_DIV_SHIFT 20 ++#define AR71XX_AHB_DIV_MASK 0x7 ++ ++#define AR71XX_ETH0_PLL_SHIFT 17 ++#define AR71XX_ETH1_PLL_SHIFT 19 ++ ++#define AR724X_PLL_REG_CPU_CONFIG 0x00 ++#define AR724X_PLL_REG_PCIE_CONFIG 0x18 ++ ++#define AR724X_PLL_DIV_SHIFT 0 ++#define AR724X_PLL_DIV_MASK 0x3ff ++#define AR724X_PLL_REF_DIV_SHIFT 10 ++#define AR724X_PLL_REF_DIV_MASK 0xf ++#define AR724X_AHB_DIV_SHIFT 19 ++#define AR724X_AHB_DIV_MASK 0x1 ++#define AR724X_DDR_DIV_SHIFT 22 ++#define AR724X_DDR_DIV_MASK 0x3 ++ ++#define AR7242_PLL_REG_ETH0_INT_CLOCK 0x2c ++ ++#define AR913X_PLL_REG_CPU_CONFIG 0x00 ++#define AR913X_PLL_REG_ETH_CONFIG 0x04 ++#define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14 ++#define AR913X_PLL_REG_ETH1_INT_CLOCK 0x18 ++ ++#define AR913X_PLL_DIV_SHIFT 0 ++#define AR913X_PLL_DIV_MASK 0x3ff ++#define AR913X_DDR_DIV_SHIFT 22 ++#define AR913X_DDR_DIV_MASK 0x3 ++#define AR913X_AHB_DIV_SHIFT 19 ++#define AR913X_AHB_DIV_MASK 0x1 ++ ++#define AR913X_ETH0_PLL_SHIFT 20 ++#define AR913X_ETH1_PLL_SHIFT 22 ++ ++#define AR933X_PLL_CPU_CONFIG_REG 0x00 ++#define AR933X_PLL_CLOCK_CTRL_REG 0x08 ++ ++#define AR933X_PLL_CPU_CONFIG_NINT_SHIFT 10 ++#define AR933X_PLL_CPU_CONFIG_NINT_MASK 0x3f ++#define AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT 16 ++#define AR933X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f ++#define AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT 23 ++#define AR933X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 ++ ++#define AR933X_PLL_CLOCK_CTRL_BYPASS BIT(2) ++#define AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT 5 ++#define AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK 0x3 ++#define AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT 10 ++#define AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK 0x3 ++#define AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT 15 ++#define AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK 0x7 ++ ++#define AR934X_PLL_CPU_CONFIG_REG 0x00 ++#define AR934X_PLL_DDR_CONFIG_REG 0x04 ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_REG 0x08 ++#define AR934X_PLL_ETH_XMII_CONTROL_REG 0x2c ++ ++#define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 ++#define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f ++#define AR934X_PLL_CPU_CONFIG_NINT_SHIFT 6 ++#define AR934X_PLL_CPU_CONFIG_NINT_MASK 0x3f ++#define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 ++#define AR934X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f ++#define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 ++#define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 ++ ++#define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 ++#define AR934X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff ++#define AR934X_PLL_DDR_CONFIG_NINT_SHIFT 10 ++#define AR934X_PLL_DDR_CONFIG_NINT_MASK 0x3f ++#define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 ++#define AR934X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f ++#define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 ++#define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 ++ ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS BIT(2) ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS BIT(3) ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS BIT(4) ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT 5 ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK 0x1f ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT 10 ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK 0x1f ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT 15 ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK 0x1f ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) ++#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) ++ ++#define QCA955X_PLL_CPU_CONFIG_REG 0x00 ++#define QCA955X_PLL_DDR_CONFIG_REG 0x04 ++#define QCA955X_PLL_CLK_CTRL_REG 0x08 ++ ++#define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 ++#define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f ++#define QCA955X_PLL_CPU_CONFIG_NINT_SHIFT 6 ++#define QCA955X_PLL_CPU_CONFIG_NINT_MASK 0x3f ++#define QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 ++#define QCA955X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f ++#define QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 ++#define QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 ++ ++#define QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 ++#define QCA955X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff ++#define QCA955X_PLL_DDR_CONFIG_NINT_SHIFT 10 ++#define QCA955X_PLL_DDR_CONFIG_NINT_MASK 0x3f ++#define QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 ++#define QCA955X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f ++#define QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 ++#define QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 ++ ++#define QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) ++#define QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) ++#define QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) ++#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 ++#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f ++#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 ++#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f ++#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 ++#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f ++#define QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) ++#define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) ++#define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) ++ ++/* ++ * USB_CONFIG block ++ */ ++#define AR71XX_USB_CTRL_REG_FLADJ 0x00 ++#define AR71XX_USB_CTRL_REG_CONFIG 0x04 ++ ++/* ++ * RESET block ++ */ ++#define AR71XX_RESET_REG_TIMER 0x00 ++#define AR71XX_RESET_REG_TIMER_RELOAD 0x04 ++#define AR71XX_RESET_REG_WDOG_CTRL 0x08 ++#define AR71XX_RESET_REG_WDOG 0x0c ++#define AR71XX_RESET_REG_MISC_INT_STATUS 0x10 ++#define AR71XX_RESET_REG_MISC_INT_ENABLE 0x14 ++#define AR71XX_RESET_REG_PCI_INT_STATUS 0x18 ++#define AR71XX_RESET_REG_PCI_INT_ENABLE 0x1c ++#define AR71XX_RESET_REG_GLOBAL_INT_STATUS 0x20 ++#define AR71XX_RESET_REG_RESET_MODULE 0x24 ++#define AR71XX_RESET_REG_PERFC_CTRL 0x2c ++#define AR71XX_RESET_REG_PERFC0 0x30 ++#define AR71XX_RESET_REG_PERFC1 0x34 ++#define AR71XX_RESET_REG_REV_ID 0x90 ++ ++#define AR913X_RESET_REG_GLOBAL_INT_STATUS 0x18 ++#define AR913X_RESET_REG_RESET_MODULE 0x1c ++#define AR913X_RESET_REG_PERF_CTRL 0x20 ++#define AR913X_RESET_REG_PERFC0 0x24 ++#define AR913X_RESET_REG_PERFC1 0x28 ++ ++#define AR724X_RESET_REG_RESET_MODULE 0x1c ++ ++#define AR933X_RESET_REG_RESET_MODULE 0x1c ++#define AR933X_RESET_REG_BOOTSTRAP 0xac ++ ++#define AR934X_RESET_REG_RESET_MODULE 0x1c ++#define AR934X_RESET_REG_BOOTSTRAP 0xb0 ++#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac ++ ++#define QCA955X_RESET_REG_BOOTSTRAP 0xb0 ++#define QCA955X_RESET_REG_EXT_INT_STATUS 0xac ++ ++#define MISC_INT_ETHSW BIT(12) ++#define MISC_INT_TIMER4 BIT(10) ++#define MISC_INT_TIMER3 BIT(9) ++#define MISC_INT_TIMER2 BIT(8) ++#define MISC_INT_DMA BIT(7) ++#define MISC_INT_OHCI BIT(6) ++#define MISC_INT_PERFC BIT(5) ++#define MISC_INT_WDOG BIT(4) ++#define MISC_INT_UART BIT(3) ++#define MISC_INT_GPIO BIT(2) ++#define MISC_INT_ERROR BIT(1) ++#define MISC_INT_TIMER BIT(0) ++ ++#define AR71XX_RESET_EXTERNAL BIT(28) ++#define AR71XX_RESET_FULL_CHIP BIT(24) ++#define AR71XX_RESET_CPU_NMI BIT(21) ++#define AR71XX_RESET_CPU_COLD BIT(20) ++#define AR71XX_RESET_DMA BIT(19) ++#define AR71XX_RESET_SLIC BIT(18) ++#define AR71XX_RESET_STEREO BIT(17) ++#define AR71XX_RESET_DDR BIT(16) ++#define AR71XX_RESET_GE1_MAC BIT(13) ++#define AR71XX_RESET_GE1_PHY BIT(12) ++#define AR71XX_RESET_USBSUS_OVERRIDE BIT(10) ++#define AR71XX_RESET_GE0_MAC BIT(9) ++#define AR71XX_RESET_GE0_PHY BIT(8) ++#define AR71XX_RESET_USB_OHCI_DLL BIT(6) ++#define AR71XX_RESET_USB_HOST BIT(5) ++#define AR71XX_RESET_USB_PHY BIT(4) ++#define AR71XX_RESET_PCI_BUS BIT(1) ++#define AR71XX_RESET_PCI_CORE BIT(0) ++ ++#define AR7240_RESET_USB_HOST BIT(5) ++#define AR7240_RESET_OHCI_DLL BIT(3) ++ ++#define AR724X_RESET_GE1_MDIO BIT(23) ++#define AR724X_RESET_GE0_MDIO BIT(22) ++#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) ++#define AR724X_RESET_PCIE_PHY BIT(7) ++#define AR724X_RESET_PCIE BIT(6) ++#define AR724X_RESET_USB_HOST BIT(5) ++#define AR724X_RESET_USB_PHY BIT(4) ++#define AR724X_RESET_USBSUS_OVERRIDE BIT(3) ++ ++#define AR913X_RESET_AMBA2WMAC BIT(22) ++#define AR913X_RESET_USBSUS_OVERRIDE BIT(10) ++#define AR913X_RESET_USB_HOST BIT(5) ++#define AR913X_RESET_USB_PHY BIT(4) ++ ++#define AR933X_RESET_GE1_MDIO BIT(23) ++#define AR933X_RESET_GE0_MDIO BIT(22) ++#define AR933X_RESET_GE1_MAC BIT(13) ++#define AR933X_RESET_WMAC BIT(11) ++#define AR933X_RESET_GE0_MAC BIT(9) ++#define AR933X_RESET_USB_HOST BIT(5) ++#define AR933X_RESET_USB_PHY BIT(4) ++#define AR933X_RESET_USBSUS_OVERRIDE BIT(3) ++ ++#define AR934X_RESET_HOST BIT(31) ++#define AR934X_RESET_SLIC BIT(30) ++#define AR934X_RESET_HDMA BIT(29) ++#define AR934X_RESET_EXTERNAL BIT(28) ++#define AR934X_RESET_RTC BIT(27) ++#define AR934X_RESET_PCIE_EP_INT BIT(26) ++#define AR934X_RESET_CHKSUM_ACC BIT(25) ++#define AR934X_RESET_FULL_CHIP BIT(24) ++#define AR934X_RESET_GE1_MDIO BIT(23) ++#define AR934X_RESET_GE0_MDIO BIT(22) ++#define AR934X_RESET_CPU_NMI BIT(21) ++#define AR934X_RESET_CPU_COLD BIT(20) ++#define AR934X_RESET_HOST_RESET_INT BIT(19) ++#define AR934X_RESET_PCIE_EP BIT(18) ++#define AR934X_RESET_UART1 BIT(17) ++#define AR934X_RESET_DDR BIT(16) ++#define AR934X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) ++#define AR934X_RESET_NANDF BIT(14) ++#define AR934X_RESET_GE1_MAC BIT(13) ++#define AR934X_RESET_ETH_SWITCH_ANALOG BIT(12) ++#define AR934X_RESET_USB_PHY_ANALOG BIT(11) ++#define AR934X_RESET_HOST_DMA_INT BIT(10) ++#define AR934X_RESET_GE0_MAC BIT(9) ++#define AR934X_RESET_ETH_SWITCH BIT(8) ++#define AR934X_RESET_PCIE_PHY BIT(7) ++#define AR934X_RESET_PCIE BIT(6) ++#define AR934X_RESET_USB_HOST BIT(5) ++#define AR934X_RESET_USB_PHY BIT(4) ++#define AR934X_RESET_USBSUS_OVERRIDE BIT(3) ++#define AR934X_RESET_LUT BIT(2) ++#define AR934X_RESET_MBOX BIT(1) ++#define AR934X_RESET_I2S BIT(0) ++ ++#define AR933X_BOOTSTRAP_MDIO_GPIO_EN BIT(18) ++#define AR933X_BOOTSTRAP_EEPBUSY BIT(4) ++#define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0) ++ ++#define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23) ++#define AR934X_BOOTSTRAP_SW_OPTION7 BIT(22) ++#define AR934X_BOOTSTRAP_SW_OPTION6 BIT(21) ++#define AR934X_BOOTSTRAP_SW_OPTION5 BIT(20) ++#define AR934X_BOOTSTRAP_SW_OPTION4 BIT(19) ++#define AR934X_BOOTSTRAP_SW_OPTION3 BIT(18) ++#define AR934X_BOOTSTRAP_SW_OPTION2 BIT(17) ++#define AR934X_BOOTSTRAP_SW_OPTION1 BIT(16) ++#define AR934X_BOOTSTRAP_USB_MODE_DEVICE BIT(7) ++#define AR934X_BOOTSTRAP_PCIE_RC BIT(6) ++#define AR934X_BOOTSTRAP_EJTAG_MODE BIT(5) ++#define AR934X_BOOTSTRAP_REF_CLK_40 BIT(4) ++#define AR934X_BOOTSTRAP_BOOT_FROM_SPI BIT(2) ++#define AR934X_BOOTSTRAP_SDRAM_DISABLED BIT(1) ++#define AR934X_BOOTSTRAP_DDR1 BIT(0) ++ ++#define QCA955X_BOOTSTRAP_REF_CLK_40 BIT(4) ++ ++#define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) ++#define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1) ++#define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) ++#define AR934X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) ++#define AR934X_PCIE_WMAC_INT_PCIE_RC BIT(4) ++#define AR934X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) ++#define AR934X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) ++#define AR934X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) ++#define AR934X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) ++#define AR934X_PCIE_WMAC_INT_WMAC_ALL \ ++ (AR934X_PCIE_WMAC_INT_WMAC_MISC | AR934X_PCIE_WMAC_INT_WMAC_TX | \ ++ AR934X_PCIE_WMAC_INT_WMAC_RXLP | AR934X_PCIE_WMAC_INT_WMAC_RXHP) ++ ++#define AR934X_PCIE_WMAC_INT_PCIE_ALL \ ++ (AR934X_PCIE_WMAC_INT_PCIE_RC | AR934X_PCIE_WMAC_INT_PCIE_RC0 | \ ++ AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \ ++ AR934X_PCIE_WMAC_INT_PCIE_RC3) ++ ++#define QCA955X_EXT_INT_WMAC_MISC BIT(0) ++#define QCA955X_EXT_INT_WMAC_TX BIT(1) ++#define QCA955X_EXT_INT_WMAC_RXLP BIT(2) ++#define QCA955X_EXT_INT_WMAC_RXHP BIT(3) ++#define QCA955X_EXT_INT_PCIE_RC1 BIT(4) ++#define QCA955X_EXT_INT_PCIE_RC1_INT0 BIT(5) ++#define QCA955X_EXT_INT_PCIE_RC1_INT1 BIT(6) ++#define QCA955X_EXT_INT_PCIE_RC1_INT2 BIT(7) ++#define QCA955X_EXT_INT_PCIE_RC1_INT3 BIT(8) ++#define QCA955X_EXT_INT_PCIE_RC2 BIT(12) ++#define QCA955X_EXT_INT_PCIE_RC2_INT0 BIT(13) ++#define QCA955X_EXT_INT_PCIE_RC2_INT1 BIT(14) ++#define QCA955X_EXT_INT_PCIE_RC2_INT2 BIT(15) ++#define QCA955X_EXT_INT_PCIE_RC2_INT3 BIT(16) ++#define QCA955X_EXT_INT_USB1 BIT(24) ++#define QCA955X_EXT_INT_USB2 BIT(28) ++ ++#define QCA955X_EXT_INT_WMAC_ALL \ ++ (QCA955X_EXT_INT_WMAC_MISC | QCA955X_EXT_INT_WMAC_TX | \ ++ QCA955X_EXT_INT_WMAC_RXLP | QCA955X_EXT_INT_WMAC_RXHP) ++ ++#define QCA955X_EXT_INT_PCIE_RC1_ALL \ ++ (QCA955X_EXT_INT_PCIE_RC1 | QCA955X_EXT_INT_PCIE_RC1_INT0 | \ ++ QCA955X_EXT_INT_PCIE_RC1_INT1 | QCA955X_EXT_INT_PCIE_RC1_INT2 | \ ++ QCA955X_EXT_INT_PCIE_RC1_INT3) ++ ++#define QCA955X_EXT_INT_PCIE_RC2_ALL \ ++ (QCA955X_EXT_INT_PCIE_RC2 | QCA955X_EXT_INT_PCIE_RC2_INT0 | \ ++ QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \ ++ QCA955X_EXT_INT_PCIE_RC2_INT3) ++ ++#define REV_ID_MAJOR_MASK 0xfff0 ++#define REV_ID_MAJOR_AR71XX 0x00a0 ++#define REV_ID_MAJOR_AR913X 0x00b0 ++#define REV_ID_MAJOR_AR7240 0x00c0 ++#define REV_ID_MAJOR_AR7241 0x0100 ++#define REV_ID_MAJOR_AR7242 0x1100 ++#define REV_ID_MAJOR_AR9330 0x0110 ++#define REV_ID_MAJOR_AR9331 0x1110 ++#define REV_ID_MAJOR_AR9341 0x0120 ++#define REV_ID_MAJOR_AR9342 0x1120 ++#define REV_ID_MAJOR_AR9344 0x2120 ++#define REV_ID_MAJOR_QCA9558 0x1130 ++ ++#define AR71XX_REV_ID_MINOR_MASK 0x3 ++#define AR71XX_REV_ID_MINOR_AR7130 0x0 ++#define AR71XX_REV_ID_MINOR_AR7141 0x1 ++#define AR71XX_REV_ID_MINOR_AR7161 0x2 ++#define AR71XX_REV_ID_REVISION_MASK 0x3 ++#define AR71XX_REV_ID_REVISION_SHIFT 2 ++ ++#define AR913X_REV_ID_MINOR_MASK 0x3 ++#define AR913X_REV_ID_MINOR_AR9130 0x0 ++#define AR913X_REV_ID_MINOR_AR9132 0x1 ++#define AR913X_REV_ID_REVISION_MASK 0x3 ++#define AR913X_REV_ID_REVISION_SHIFT 2 ++ ++#define AR933X_REV_ID_REVISION_MASK 0x3 ++ ++#define AR724X_REV_ID_REVISION_MASK 0x3 ++ ++#define AR934X_REV_ID_REVISION_MASK 0xf ++ ++#define AR944X_REV_ID_REVISION_MASK 0xf ++ ++/* ++ * SPI block ++ */ ++#define AR71XX_SPI_REG_FS 0x00 /* Function Select */ ++#define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */ ++#define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */ ++#define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */ ++ ++#define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */ ++ ++#define AR71XX_SPI_CTRL_RD BIT(6) /* Remap Disable */ ++#define AR71XX_SPI_CTRL_DIV_MASK 0x3f ++ ++#define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */ ++#define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */ ++#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n)) ++#define AR71XX_SPI_IOC_CS0 AR71XX_SPI_IOC_CS(0) ++#define AR71XX_SPI_IOC_CS1 AR71XX_SPI_IOC_CS(1) ++#define AR71XX_SPI_IOC_CS2 AR71XX_SPI_IOC_CS(2) ++#define AR71XX_SPI_IOC_CS_ALL (AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | \ ++ AR71XX_SPI_IOC_CS2) ++ ++/* ++ * GPIO block ++ */ ++#define AR71XX_GPIO_REG_OE 0x00 ++#define AR71XX_GPIO_REG_IN 0x04 ++#define AR71XX_GPIO_REG_OUT 0x08 ++#define AR71XX_GPIO_REG_SET 0x0c ++#define AR71XX_GPIO_REG_CLEAR 0x10 ++#define AR71XX_GPIO_REG_INT_MODE 0x14 ++#define AR71XX_GPIO_REG_INT_TYPE 0x18 ++#define AR71XX_GPIO_REG_INT_POLARITY 0x1c ++#define AR71XX_GPIO_REG_INT_PENDING 0x20 ++#define AR71XX_GPIO_REG_INT_ENABLE 0x24 ++#define AR71XX_GPIO_REG_FUNC 0x28 ++ ++#define AR934X_GPIO_REG_OUT_FUNC0 0x2c ++#define AR934X_GPIO_REG_OUT_FUNC1 0x30 ++#define AR934X_GPIO_REG_OUT_FUNC2 0x34 ++#define AR934X_GPIO_REG_OUT_FUNC3 0x38 ++#define AR934X_GPIO_REG_OUT_FUNC4 0x3c ++#define AR934X_GPIO_REG_OUT_FUNC5 0x40 ++#define AR934X_GPIO_REG_FUNC 0x6c ++ ++#define AR71XX_GPIO_COUNT 16 ++#define AR724X_GPIO_COUNT 18 ++#define AR913X_GPIO_COUNT 22 ++#define AR933X_GPIO_COUNT 30 ++#define AR934X_GPIO_COUNT 23 ++#define QCA955X_GPIO_COUNT 24 ++ ++#define AR71XX_GPIO_FUNC_STEREO_EN BIT(17) ++#define AR71XX_GPIO_FUNC_SLIC_EN BIT(16) ++#define AR71XX_GPIO_FUNC_SPI_CS2_EN BIT(13) ++#define AR71XX_GPIO_FUNC_SPI_CS1_EN BIT(12) ++#define AR71XX_GPIO_FUNC_UART_EN BIT(8) ++#define AR71XX_GPIO_FUNC_USB_OC_EN BIT(4) ++#define AR71XX_GPIO_FUNC_USB_CLK_EN BIT(0) ++ ++#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN BIT(19) ++#define AR724X_GPIO_FUNC_SPI_EN BIT(18) ++#define AR724X_GPIO_FUNC_SPI_CS_EN2 BIT(14) ++#define AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13) ++#define AR724X_GPIO_FUNC_CLK_OBS5_EN BIT(12) ++#define AR724X_GPIO_FUNC_CLK_OBS4_EN BIT(11) ++#define AR724X_GPIO_FUNC_CLK_OBS3_EN BIT(10) ++#define AR724X_GPIO_FUNC_CLK_OBS2_EN BIT(9) ++#define AR724X_GPIO_FUNC_CLK_OBS1_EN BIT(8) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) ++#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) ++#define AR724X_GPIO_FUNC_UART_EN BIT(1) ++#define AR724X_GPIO_FUNC_JTAG_DISABLE BIT(0) ++ ++#define AR913X_GPIO_FUNC_WMAC_LED_EN BIT(22) ++#define AR913X_GPIO_FUNC_EXP_PORT_CS_EN BIT(21) ++#define AR913X_GPIO_FUNC_I2S_REFCLKEN BIT(20) ++#define AR913X_GPIO_FUNC_I2S_MCKEN BIT(19) ++#define AR913X_GPIO_FUNC_I2S1_EN BIT(18) ++#define AR913X_GPIO_FUNC_I2S0_EN BIT(17) ++#define AR913X_GPIO_FUNC_SLIC_EN BIT(16) ++#define AR913X_GPIO_FUNC_UART_RTSCTS_EN BIT(9) ++#define AR913X_GPIO_FUNC_UART_EN BIT(8) ++#define AR913X_GPIO_FUNC_USB_CLK_EN BIT(4) ++ ++#define AR933X_GPIO_FUNC_SPDIF2TCK BIT(31) ++#define AR933X_GPIO_FUNC_SPDIF_EN BIT(30) ++#define AR933X_GPIO_FUNC_I2SO_22_18_EN BIT(29) ++#define AR933X_GPIO_FUNC_I2S_MCK_EN BIT(27) ++#define AR933X_GPIO_FUNC_I2SO_EN BIT(26) ++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_DUPL BIT(25) ++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_COLL BIT(24) ++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_ACT BIT(23) ++#define AR933X_GPIO_FUNC_SPI_EN BIT(18) ++#define AR933X_GPIO_FUNC_SPI_CS_EN2 BIT(14) ++#define AR933X_GPIO_FUNC_SPI_CS_EN1 BIT(13) ++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) ++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) ++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) ++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) ++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) ++#define AR933X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) ++#define AR933X_GPIO_FUNC_UART_EN BIT(1) ++#define AR933X_GPIO_FUNC_JTAG_DISABLE BIT(0) ++ ++#define AR934X_GPIO_FUNC_DDR_DQOE_EN BIT(17) ++#define AR934X_GPIO_FUNC_SPI_CS_1_EN BIT(14) ++#define AR934X_GPIO_FUNC_SPI_CS_0_EN BIT(13) ++ ++#define AR934X_GPIO_OUT_GPIO 0x00 ++ ++/* ++ * MII_CTRL block ++ */ ++#define AR71XX_MII_REG_MII0_CTRL 0x00 ++#define AR71XX_MII_REG_MII1_CTRL 0x04 ++ ++#define AR71XX_MII_CTRL_IF_MASK 3 ++#define AR71XX_MII_CTRL_SPEED_SHIFT 4 ++#define AR71XX_MII_CTRL_SPEED_MASK 3 ++#define AR71XX_MII_CTRL_SPEED_10 0 ++#define AR71XX_MII_CTRL_SPEED_100 1 ++#define AR71XX_MII_CTRL_SPEED_1000 2 ++ ++#define AR71XX_MII0_CTRL_IF_GMII 0 ++#define AR71XX_MII0_CTRL_IF_MII 1 ++#define AR71XX_MII0_CTRL_IF_RGMII 2 ++#define AR71XX_MII0_CTRL_IF_RMII 3 ++ ++#define AR71XX_MII1_CTRL_IF_RGMII 0 ++#define AR71XX_MII1_CTRL_IF_RMII 1 ++ ++/* ++ * AR933X GMAC interface ++ */ ++#define AR933X_GMAC_REG_ETH_CFG 0x00 ++ ++#define AR933X_ETH_CFG_RGMII_GE0 BIT(0) ++#define AR933X_ETH_CFG_MII_GE0 BIT(1) ++#define AR933X_ETH_CFG_GMII_GE0 BIT(2) ++#define AR933X_ETH_CFG_MII_GE0_MASTER BIT(3) ++#define AR933X_ETH_CFG_MII_GE0_SLAVE BIT(4) ++#define AR933X_ETH_CFG_MII_GE0_ERR_EN BIT(5) ++#define AR933X_ETH_CFG_SW_PHY_SWAP BIT(7) ++#define AR933X_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8) ++#define AR933X_ETH_CFG_RMII_GE0 BIT(9) ++#define AR933X_ETH_CFG_RMII_GE0_SPD_10 0 ++#define AR933X_ETH_CFG_RMII_GE0_SPD_100 BIT(10) ++ ++/* ++ * AR934X GMAC Interface ++ */ ++#define AR934X_GMAC_REG_ETH_CFG 0x00 ++ ++#define AR934X_ETH_CFG_RGMII_GMAC0 BIT(0) ++#define AR934X_ETH_CFG_MII_GMAC0 BIT(1) ++#define AR934X_ETH_CFG_GMII_GMAC0 BIT(2) ++#define AR934X_ETH_CFG_MII_GMAC0_MASTER BIT(3) ++#define AR934X_ETH_CFG_MII_GMAC0_SLAVE BIT(4) ++#define AR934X_ETH_CFG_MII_GMAC0_ERR_EN BIT(5) ++#define AR934X_ETH_CFG_SW_ONLY_MODE BIT(6) ++#define AR934X_ETH_CFG_SW_PHY_SWAP BIT(7) ++#define AR934X_ETH_CFG_SW_APB_ACCESS BIT(9) ++#define AR934X_ETH_CFG_RMII_GMAC0 BIT(10) ++#define AR933X_ETH_CFG_MII_CNTL_SPEED BIT(11) ++#define AR934X_ETH_CFG_RMII_GMAC0_MASTER BIT(12) ++#define AR933X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) ++ ++/* ++ * QCA955X GMAC Interface ++ */ ++ ++#define QCA955X_GMAC_REG_ETH_CFG 0x00 ++ ++#define QCA955X_ETH_CFG_RGMII_GMAC0 BIT(0) ++#define QCA955X_ETH_CFG_SGMII_GMAC0 BIT(6) ++ ++#endif /* __ASM_MACH_AR71XX_REGS_H */ +diff --git a/target/linux/ar71xx/image/lzma-loader/src/board.c b/target/linux/ar71xx/image/lzma-loader/src/board.c +new file mode 100644 +index 0000000000..2f4dd6b1f6 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/board.c +@@ -0,0 +1,56 @@ ++/* ++ * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards ++ * ++ * 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. ++ */ ++ ++#include ++#include "config.h" ++#include "ar71xx_regs.h" ++ ++#define READREG(r) *(volatile unsigned int *)(r) ++#define WRITEREG(r,v) *(volatile unsigned int *)(r) = v ++ ++#define KSEG1ADDR(_x) (((_x) & 0x1fffffff) | 0xa0000000) ++ ++#define UART_BASE 0xb8020000 ++ ++#define UART_TX 0 ++#define UART_LSR 5 ++ ++#define UART_LSR_THRE 0x20 ++ ++#define UART_READ(r) READREG(UART_BASE + 4 * (r)) ++#define UART_WRITE(r,v) WRITEREG(UART_BASE + 4 * (r), (v)) ++ ++void board_putc(int ch) ++{ ++ while (((UART_READ(UART_LSR)) & UART_LSR_THRE) == 0); ++ UART_WRITE(UART_TX, ch); ++ while (((UART_READ(UART_LSR)) & UART_LSR_THRE) == 0); ++} ++ ++#ifdef CONFIG_BOARD_TL_WR1043ND_V1 ++static void tlwr1043nd_init(void) ++{ ++ unsigned int reg = KSEG1ADDR(AR71XX_RESET_BASE); ++ unsigned int t; ++ ++ t = READREG(reg + AR913X_RESET_REG_RESET_MODULE); ++ t |= AR71XX_RESET_GE0_PHY; ++ WRITEREG(reg + AR913X_RESET_REG_RESET_MODULE, t); ++ /* flush write */ ++ t = READREG(reg + AR913X_RESET_REG_RESET_MODULE); ++} ++#else ++static inline void tlwr1043nd_init(void) {} ++#endif ++ ++void board_init(void) ++{ ++ tlwr1043nd_init(); ++} +diff --git a/target/linux/ar71xx/image/lzma-loader/src/cache.c b/target/linux/ar71xx/image/lzma-loader/src/cache.c +new file mode 100644 +index 0000000000..28cc848333 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/cache.c +@@ -0,0 +1,43 @@ ++/* ++ * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards ++ * ++ * Copyright (C) 2011 Gabor Juhos ++ * ++ * The cache manipulation routine has been taken from the U-Boot project. ++ * (C) Copyright 2003 ++ * Wolfgang Denk, DENX Software Engineering, ++ * ++ * 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 "cache.h" ++#include "cacheops.h" ++#include "config.h" ++ ++#define cache_op(op,addr) \ ++ __asm__ __volatile__( \ ++ " .set push \n" \ ++ " .set noreorder \n" \ ++ " .set mips3\n\t \n" \ ++ " cache %0, %1 \n" \ ++ " .set pop \n" \ ++ : \ ++ : "i" (op), "R" (*(unsigned char *)(addr))) ++ ++void flush_cache(unsigned long start_addr, unsigned long size) ++{ ++ unsigned long lsize = CONFIG_CACHELINE_SIZE; ++ unsigned long addr = start_addr & ~(lsize - 1); ++ unsigned long aend = (start_addr + size - 1) & ~(lsize - 1); ++ ++ while (1) { ++ cache_op(Hit_Writeback_Inv_D, addr); ++ cache_op(Hit_Invalidate_I, addr); ++ if (addr == aend) ++ break; ++ addr += lsize; ++ } ++} +diff --git a/target/linux/ar71xx/image/lzma-loader/src/cache.h b/target/linux/ar71xx/image/lzma-loader/src/cache.h +new file mode 100644 +index 0000000000..506a235884 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/cache.h +@@ -0,0 +1,17 @@ ++/* ++ * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards ++ * ++ * 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 __CACHE_H ++#define __CACHE_H ++ ++void flush_cache(unsigned long start_addr, unsigned long size); ++ ++#endif /* __CACHE_H */ +diff --git a/target/linux/ar71xx/image/lzma-loader/src/cacheops.h b/target/linux/ar71xx/image/lzma-loader/src/cacheops.h +new file mode 100644 +index 0000000000..70bcad7694 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/cacheops.h +@@ -0,0 +1,85 @@ ++/* ++ * Cache operations for the cache instruction. ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * (C) Copyright 1996, 97, 99, 2002, 03 Ralf Baechle ++ * (C) Copyright 1999 Silicon Graphics, Inc. ++ */ ++#ifndef __ASM_CACHEOPS_H ++#define __ASM_CACHEOPS_H ++ ++/* ++ * Cache Operations available on all MIPS processors with R4000-style caches ++ */ ++#define Index_Invalidate_I 0x00 ++#define Index_Writeback_Inv_D 0x01 ++#define Index_Load_Tag_I 0x04 ++#define Index_Load_Tag_D 0x05 ++#define Index_Store_Tag_I 0x08 ++#define Index_Store_Tag_D 0x09 ++#if defined(CONFIG_CPU_LOONGSON2) ++#define Hit_Invalidate_I 0x00 ++#else ++#define Hit_Invalidate_I 0x10 ++#endif ++#define Hit_Invalidate_D 0x11 ++#define Hit_Writeback_Inv_D 0x15 ++ ++/* ++ * R4000-specific cacheops ++ */ ++#define Create_Dirty_Excl_D 0x0d ++#define Fill 0x14 ++#define Hit_Writeback_I 0x18 ++#define Hit_Writeback_D 0x19 ++ ++/* ++ * R4000SC and R4400SC-specific cacheops ++ */ ++#define Index_Invalidate_SI 0x02 ++#define Index_Writeback_Inv_SD 0x03 ++#define Index_Load_Tag_SI 0x06 ++#define Index_Load_Tag_SD 0x07 ++#define Index_Store_Tag_SI 0x0A ++#define Index_Store_Tag_SD 0x0B ++#define Create_Dirty_Excl_SD 0x0f ++#define Hit_Invalidate_SI 0x12 ++#define Hit_Invalidate_SD 0x13 ++#define Hit_Writeback_Inv_SD 0x17 ++#define Hit_Writeback_SD 0x1b ++#define Hit_Set_Virtual_SI 0x1e ++#define Hit_Set_Virtual_SD 0x1f ++ ++/* ++ * R5000-specific cacheops ++ */ ++#define R5K_Page_Invalidate_S 0x17 ++ ++/* ++ * RM7000-specific cacheops ++ */ ++#define Page_Invalidate_T 0x16 ++ ++/* ++ * R10000-specific cacheops ++ * ++ * Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused. ++ * Most of the _S cacheops are identical to the R4000SC _SD cacheops. ++ */ ++#define Index_Writeback_Inv_S 0x03 ++#define Index_Load_Tag_S 0x07 ++#define Index_Store_Tag_S 0x0B ++#define Hit_Invalidate_S 0x13 ++#define Cache_Barrier 0x14 ++#define Hit_Writeback_Inv_S 0x17 ++#define Index_Load_Data_I 0x18 ++#define Index_Load_Data_D 0x19 ++#define Index_Load_Data_S 0x1b ++#define Index_Store_Data_I 0x1c ++#define Index_Store_Data_D 0x1d ++#define Index_Store_Data_S 0x1f ++ ++#endif /* __ASM_CACHEOPS_H */ +diff --git a/target/linux/ar71xx/image/lzma-loader/src/config.h b/target/linux/ar71xx/image/lzma-loader/src/config.h +new file mode 100644 +index 0000000000..287392b340 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/config.h +@@ -0,0 +1,31 @@ ++/* ++ * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards ++ * ++ * 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 _CONFIG_H_ ++#define _CONFIG_H_ ++ ++#define CONFIG_ICACHE_SIZE (32 * 1024) ++#define CONFIG_DCACHE_SIZE (64 * 1024) ++#define CONFIG_CACHELINE_SIZE 32 ++ ++#ifndef CONFIG_FLASH_OFFS ++#define CONFIG_FLASH_OFFS 0 ++#endif ++ ++#ifndef CONFIG_FLASH_MAX ++#define CONFIG_FLASH_MAX 0 ++#endif ++ ++#ifndef CONFIG_FLASH_STEP ++#define CONFIG_FLASH_STEP 0x1000 ++#endif ++ ++#endif /* _CONFIG_H_ */ +diff --git a/target/linux/ar71xx/image/lzma-loader/src/cp0regdef.h b/target/linux/ar71xx/image/lzma-loader/src/cp0regdef.h +new file mode 100644 +index 0000000000..c1188ad8c8 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/cp0regdef.h +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle ++ * ++ * Copyright (C) 2001, Monta Vista Software ++ * Author: jsun@mvista.com or jsun@junsun.net ++ */ ++#ifndef _cp0regdef_h_ ++#define _cp0regdef_h_ ++ ++#define CP0_INDEX $0 ++#define CP0_RANDOM $1 ++#define CP0_ENTRYLO0 $2 ++#define CP0_ENTRYLO1 $3 ++#define CP0_CONTEXT $4 ++#define CP0_PAGEMASK $5 ++#define CP0_WIRED $6 ++#define CP0_BADVADDR $8 ++#define CP0_COUNT $9 ++#define CP0_ENTRYHI $10 ++#define CP0_COMPARE $11 ++#define CP0_STATUS $12 ++#define CP0_CAUSE $13 ++#define CP0_EPC $14 ++#define CP0_PRID $15 ++#define CP0_CONFIG $16 ++#define CP0_LLADDR $17 ++#define CP0_WATCHLO $18 ++#define CP0_WATCHHI $19 ++#define CP0_XCONTEXT $20 ++#define CP0_FRAMEMASK $21 ++#define CP0_DIAGNOSTIC $22 ++#define CP0_PERFORMANCE $25 ++#define CP0_ECC $26 ++#define CP0_CACHEERR $27 ++#define CP0_TAGLO $28 ++#define CP0_TAGHI $29 ++#define CP0_ERROREPC $30 ++ ++#endif +diff --git a/target/linux/ar71xx/image/lzma-loader/src/head.S b/target/linux/ar71xx/image/lzma-loader/src/head.S +new file mode 100644 +index 0000000000..d414b14d11 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/head.S +@@ -0,0 +1,134 @@ ++/* ++ * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards ++ * ++ * Copyright (C) 2011 Gabor Juhos ++ * ++ * Some parts of this code was based on the OpenWrt specific lzma-loader ++ * for the BCM47xx and ADM5120 based boards: ++ * Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org) ++ * Copyright (C) 2005 by Oleg I. Vdovikin ++ * ++ * 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 "cp0regdef.h" ++#include "cacheops.h" ++#include "config.h" ++ ++#define KSEG0 0x80000000 ++ ++ .macro ehb ++ sll zero, 3 ++ .endm ++ ++ .text ++ ++LEAF(startup) ++ .set noreorder ++ .set mips32 ++ ++ mtc0 zero, CP0_WATCHLO # clear watch registers ++ mtc0 zero, CP0_WATCHHI ++ mtc0 zero, CP0_CAUSE # clear before writing status register ++ ++ mfc0 t0, CP0_STATUS ++ li t1, 0x1000001f ++ or t0, t1 ++ xori t0, 0x1f ++ mtc0 t0, CP0_STATUS ++ ehb ++ ++ /* ++ * Some bootloaders set the 'Kseg0 coherency algorithm' to ++ * 'Cacheable, noncoherent, write-through, no write allocate' ++ * and this cause performance issues. Let's go and change it to ++ * 'Cacheable, noncoherent, write-back, write allocate' ++ */ ++ mfc0 t0, CP0_CONFIG ++ li t1, ~7 #~CONF_CM_CMASK ++ and t0, t1 ++ ori t0, 3 #CONF_CM_CACHABLE_NONCOHERENT ++ mtc0 t0, CP0_CONFIG ++ nop ++ ++ mtc0 zero, CP0_COUNT ++ mtc0 zero, CP0_COMPARE ++ ehb ++ ++ la t0, __reloc_label # get linked address of label ++ bal __reloc_label # branch and link to label to ++ nop # get actual address ++__reloc_label: ++ subu t0, ra, t0 # get reloc_delta ++ ++ beqz t0, __reloc_done # if delta is 0 we are in the right place ++ nop ++ ++ /* Copy our code to the right place */ ++ la t1, _code_start # get linked address of _code_start ++ la t2, _code_end # get linked address of _code_end ++ addu t0, t0, t1 # calculate actual address of _code_start ++ ++__reloc_copy: ++ lw t3, 0(t0) ++ sw t3, 0(t1) ++ add t1, 4 ++ blt t1, t2, __reloc_copy ++ add t0, 4 ++ ++ /* flush cache */ ++ la t0, _code_start ++ la t1, _code_end ++ ++ li t2, ~(CONFIG_CACHELINE_SIZE - 1) ++ and t0, t2 ++ and t1, t2 ++ li t2, CONFIG_CACHELINE_SIZE ++ ++ b __flush_check ++ nop ++ ++__flush_line: ++ cache Hit_Writeback_Inv_D, 0(t0) ++ cache Hit_Invalidate_I, 0(t0) ++ add t0, t2 ++ ++__flush_check: ++ bne t0, t1, __flush_line ++ nop ++ ++ sync ++ ++__reloc_done: ++ ++ /* clear bss */ ++ la t0, _bss_start ++ la t1, _bss_end ++ b __bss_check ++ nop ++ ++__bss_fill: ++ sw zero, 0(t0) ++ addi t0, 4 ++ ++__bss_check: ++ bne t0, t1, __bss_fill ++ nop ++ ++ /* Setup new "C" stack */ ++ la sp, _stack ++ ++ /* reserve stack space for a0-a3 registers */ ++ subu sp, 16 ++ ++ /* jump to the decompressor routine */ ++ la t0, loader_main ++ jr t0 ++ nop ++ ++ .set reorder ++END(startup) +diff --git a/target/linux/ar71xx/image/lzma-loader/src/loader.c b/target/linux/ar71xx/image/lzma-loader/src/loader.c +new file mode 100644 +index 0000000000..794c4b6285 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/loader.c +@@ -0,0 +1,264 @@ ++/* ++ * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards ++ * ++ * Copyright (C) 2011 Gabor Juhos ++ * ++ * Some parts of this code was based on the OpenWrt specific lzma-loader ++ * for the BCM47xx and ADM5120 based boards: ++ * Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org) ++ * Copyright (C) 2005 Mineharu Takahara ++ * Copyright (C) 2005 by Oleg I. Vdovikin ++ * ++ * The image_header structure has been taken from the U-Boot project. ++ * (C) Copyright 2008 Semihalf ++ * (C) Copyright 2000-2005 ++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++ * ++ * 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 "config.h" ++#include "cache.h" ++#include "printf.h" ++#include "LzmaDecode.h" ++ ++#define AR71XX_FLASH_START 0x1f000000 ++#define AR71XX_FLASH_END 0x1fe00000 ++ ++#define KSEG0 0x80000000 ++#define KSEG1 0xa0000000 ++ ++#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1) ++ ++#undef LZMA_DEBUG ++ ++#ifdef LZMA_DEBUG ++# define DBG(f, a...) printf(f, ## a) ++#else ++# define DBG(f, a...) do {} while (0) ++#endif ++ ++#define IH_MAGIC_OKLI 0x4f4b4c49 /* 'OKLI' */ ++ ++#define IH_NMLEN 32 /* Image Name Length */ ++ ++typedef struct image_header { ++ uint32_t ih_magic; /* Image Header Magic Number */ ++ uint32_t ih_hcrc; /* Image Header CRC Checksum */ ++ uint32_t ih_time; /* Image Creation Timestamp */ ++ uint32_t ih_size; /* Image Data Size */ ++ uint32_t ih_load; /* Data Load Address */ ++ uint32_t ih_ep; /* Entry Point Address */ ++ uint32_t ih_dcrc; /* Image Data CRC Checksum */ ++ uint8_t ih_os; /* Operating System */ ++ uint8_t ih_arch; /* CPU architecture */ ++ uint8_t ih_type; /* Image Type */ ++ uint8_t ih_comp; /* Compression Type */ ++ uint8_t ih_name[IH_NMLEN]; /* Image Name */ ++} image_header_t; ++ ++/* beyond the image end, size not known in advance */ ++extern unsigned char workspace[]; ++extern void board_init(void); ++ ++static CLzmaDecoderState lzma_state; ++static unsigned char *lzma_data; ++static unsigned long lzma_datasize; ++static unsigned long lzma_outsize; ++static unsigned long kernel_la; ++ ++#ifdef CONFIG_KERNEL_CMDLINE ++#define kernel_argc 2 ++static const char kernel_cmdline[] = CONFIG_KERNEL_CMDLINE; ++static const char *const kernel_argv[] = { ++ NULL, ++ kernel_cmdline, ++ NULL, ++}; ++#endif /* CONFIG_KERNEL_CMDLINE */ ++ ++static void halt(void) ++{ ++ printf("\nSystem halted!\n"); ++ for(;;); ++} ++ ++static __inline__ unsigned long get_be32(void *buf) ++{ ++ unsigned char *p = buf; ++ ++ return (((unsigned long) p[0] << 24) + ++ ((unsigned long) p[1] << 16) + ++ ((unsigned long) p[2] << 8) + ++ (unsigned long) p[3]); ++} ++ ++static __inline__ unsigned char lzma_get_byte(void) ++{ ++ unsigned char c; ++ ++ lzma_datasize--; ++ c = *lzma_data++; ++ ++ return c; ++} ++ ++static int lzma_init_props(void) ++{ ++ unsigned char props[LZMA_PROPERTIES_SIZE]; ++ int res; ++ int i; ++ ++ /* read lzma properties */ ++ for (i = 0; i < LZMA_PROPERTIES_SIZE; i++) ++ props[i] = lzma_get_byte(); ++ ++ /* read the lower half of uncompressed size in the header */ ++ lzma_outsize = ((SizeT) lzma_get_byte()) + ++ ((SizeT) lzma_get_byte() << 8) + ++ ((SizeT) lzma_get_byte() << 16) + ++ ((SizeT) lzma_get_byte() << 24); ++ ++ /* skip rest of the header (upper half of uncompressed size) */ ++ for (i = 0; i < 4; i++) ++ lzma_get_byte(); ++ ++ res = LzmaDecodeProperties(&lzma_state.Properties, props, ++ LZMA_PROPERTIES_SIZE); ++ return res; ++} ++ ++static int lzma_decompress(unsigned char *outStream) ++{ ++ SizeT ip, op; ++ int ret; ++ ++ lzma_state.Probs = (CProb *) workspace; ++ ++ ret = LzmaDecode(&lzma_state, lzma_data, lzma_datasize, &ip, outStream, ++ lzma_outsize, &op); ++ ++ if (ret != LZMA_RESULT_OK) { ++ int i; ++ ++ DBG("LzmaDecode error %d at %08x, osize:%d ip:%d op:%d\n", ++ ret, lzma_data + ip, lzma_outsize, ip, op); ++ ++ for (i = 0; i < 16; i++) ++ DBG("%02x ", lzma_data[ip + i]); ++ ++ DBG("\n"); ++ } ++ ++ return ret; ++} ++ ++#if (LZMA_WRAPPER) ++static void lzma_init_data(void) ++{ ++ extern unsigned char _lzma_data_start[]; ++ extern unsigned char _lzma_data_end[]; ++ ++ kernel_la = LOADADDR; ++ lzma_data = _lzma_data_start; ++ lzma_datasize = _lzma_data_end - _lzma_data_start; ++} ++#else ++static void lzma_init_data(void) ++{ ++ struct image_header *hdr = NULL; ++ unsigned char *flash_base; ++ unsigned long flash_ofs; ++ unsigned long kernel_ofs; ++ unsigned long kernel_size; ++ ++ flash_base = (unsigned char *) KSEG1ADDR(AR71XX_FLASH_START); ++ ++ printf("Looking for OpenWrt image... "); ++ ++ for (flash_ofs = CONFIG_FLASH_OFFS; ++ flash_ofs <= (CONFIG_FLASH_OFFS + CONFIG_FLASH_MAX); ++ flash_ofs += CONFIG_FLASH_STEP) { ++ unsigned long magic; ++ unsigned char *p; ++ ++ p = flash_base + flash_ofs; ++ magic = get_be32(p); ++ if (magic == IH_MAGIC_OKLI) { ++ hdr = (struct image_header *) p; ++ break; ++ } ++ } ++ ++ if (hdr == NULL) { ++ printf("not found!\n"); ++ halt(); ++ } ++ ++ printf("found at 0x%08x\n", flash_base + flash_ofs); ++ ++ kernel_ofs = sizeof(struct image_header); ++ kernel_size = get_be32(&hdr->ih_size); ++ kernel_la = get_be32(&hdr->ih_load); ++ ++ lzma_data = flash_base + flash_ofs + kernel_ofs; ++ lzma_datasize = kernel_size; ++} ++#endif /* (LZMA_WRAPPER) */ ++ ++void loader_main(unsigned long reg_a0, unsigned long reg_a1, ++ unsigned long reg_a2, unsigned long reg_a3) ++{ ++ void (*kernel_entry) (unsigned long, unsigned long, unsigned long, ++ unsigned long); ++ int res; ++ ++ board_init(); ++ ++ printf("\n\nOpenWrt kernel loader for AR7XXX/AR9XXX\n"); ++ printf("Copyright (C) 2011 Gabor Juhos \n"); ++ ++ lzma_init_data(); ++ ++ res = lzma_init_props(); ++ if (res != LZMA_RESULT_OK) { ++ printf("Incorrect LZMA stream properties!\n"); ++ halt(); ++ } ++ ++ printf("Decompressing kernel... "); ++ ++ res = lzma_decompress((unsigned char *) kernel_la); ++ if (res != LZMA_RESULT_OK) { ++ printf("failed, "); ++ switch (res) { ++ case LZMA_RESULT_DATA_ERROR: ++ printf("data error!\n"); ++ break; ++ default: ++ printf("unknown error %d!\n", res); ++ } ++ halt(); ++ } else { ++ printf("done!\n"); ++ } ++ ++ flush_cache(kernel_la, lzma_outsize); ++ ++ printf("Starting kernel at %08x...\n\n", kernel_la); ++ ++#ifdef CONFIG_KERNEL_CMDLINE ++ reg_a0 = kernel_argc; ++ reg_a1 = (unsigned long) kernel_argv; ++ reg_a2 = 0; ++ reg_a3 = 0; ++#endif ++ ++ kernel_entry = (void *) kernel_la; ++ kernel_entry(reg_a0, reg_a1, reg_a2, reg_a3); ++} +diff --git a/target/linux/ar71xx/image/lzma-loader/src/loader.lds b/target/linux/ar71xx/image/lzma-loader/src/loader.lds +new file mode 100644 +index 0000000000..01ff852361 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/loader.lds +@@ -0,0 +1,34 @@ ++OUTPUT_ARCH(mips) ++SECTIONS { ++ .text : { ++ _code_start = .; ++ *(.text) ++ *(.text.*) ++ *(.rodata) ++ *(.rodata.*) ++ *(.data.lzma) ++ } ++ ++ . = ALIGN(32); ++ .data : { ++ *(.data) ++ *(.data.*) ++ } ++ ++ . = ALIGN(32); ++ _code_end = .; ++ ++ _bss_start = .; ++ .bss : { ++ *(.bss) ++ *(.bss.*) ++ } ++ ++ . = ALIGN(32); ++ _bss_end = .; ++ ++ . = . + 8192; ++ _stack = .; ++ ++ workspace = .; ++} +diff --git a/target/linux/ar71xx/image/lzma-loader/src/loader2.lds b/target/linux/ar71xx/image/lzma-loader/src/loader2.lds +new file mode 100644 +index 0000000000..db0bb46424 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/loader2.lds +@@ -0,0 +1,10 @@ ++OUTPUT_ARCH(mips) ++SECTIONS { ++ .text : { ++ startup = .; ++ *(.text) ++ *(.text.*) ++ *(.data) ++ *(.data.*) ++ } ++} +diff --git a/target/linux/ar71xx/image/lzma-loader/src/lzma-data.lds b/target/linux/ar71xx/image/lzma-loader/src/lzma-data.lds +new file mode 100644 +index 0000000000..abf756ba13 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/lzma-data.lds +@@ -0,0 +1,8 @@ ++OUTPUT_ARCH(mips) ++SECTIONS { ++ .data.lzma : { ++ _lzma_data_start = .; ++ *(.data) ++ _lzma_data_end = .; ++ } ++} +diff --git a/target/linux/ar71xx/image/lzma-loader/src/printf.c b/target/linux/ar71xx/image/lzma-loader/src/printf.c +new file mode 100644 +index 0000000000..7bb5a86e18 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/printf.c +@@ -0,0 +1,350 @@ ++/* ++ * Copyright (C) 2001 MontaVista Software Inc. ++ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net ++ * ++ * 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. ++ * ++ */ ++ ++#include "printf.h" ++ ++extern void board_putc(int ch); ++ ++/* this is the maximum width for a variable */ ++#define LP_MAX_BUF 256 ++ ++/* macros */ ++#define IsDigit(x) ( ((x) >= '0') && ((x) <= '9') ) ++#define Ctod(x) ( (x) - '0') ++ ++/* forward declaration */ ++static int PrintChar(char *, char, int, int); ++static int PrintString(char *, char *, int, int); ++static int PrintNum(char *, unsigned long, int, int, int, int, char, int); ++ ++/* private variable */ ++static const char theFatalMsg[] = "fatal error in lp_Print!"; ++ ++/* -*- ++ * A low level printf() function. ++ */ ++static void ++lp_Print(void (*output)(void *, char *, int), ++ void * arg, ++ char *fmt, ++ va_list ap) ++{ ++ ++#define OUTPUT(arg, s, l) \ ++ { if (((l) < 0) || ((l) > LP_MAX_BUF)) { \ ++ (*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \ ++ } else { \ ++ (*output)(arg, s, l); \ ++ } \ ++ } ++ ++ char buf[LP_MAX_BUF]; ++ ++ char c; ++ char *s; ++ long int num; ++ ++ int longFlag; ++ int negFlag; ++ int width; ++ int prec; ++ int ladjust; ++ char padc; ++ ++ int length; ++ ++ for(;;) { ++ { ++ /* scan for the next '%' */ ++ char *fmtStart = fmt; ++ while ( (*fmt != '\0') && (*fmt != '%')) { ++ fmt ++; ++ } ++ ++ /* flush the string found so far */ ++ OUTPUT(arg, fmtStart, fmt-fmtStart); ++ ++ /* are we hitting the end? */ ++ if (*fmt == '\0') break; ++ } ++ ++ /* we found a '%' */ ++ fmt ++; ++ ++ /* check for long */ ++ if (*fmt == 'l') { ++ longFlag = 1; ++ fmt ++; ++ } else { ++ longFlag = 0; ++ } ++ ++ /* check for other prefixes */ ++ width = 0; ++ prec = -1; ++ ladjust = 0; ++ padc = ' '; ++ ++ if (*fmt == '-') { ++ ladjust = 1; ++ fmt ++; ++ } ++ ++ if (*fmt == '0') { ++ padc = '0'; ++ fmt++; ++ } ++ ++ if (IsDigit(*fmt)) { ++ while (IsDigit(*fmt)) { ++ width = 10 * width + Ctod(*fmt++); ++ } ++ } ++ ++ if (*fmt == '.') { ++ fmt ++; ++ if (IsDigit(*fmt)) { ++ prec = 0; ++ while (IsDigit(*fmt)) { ++ prec = prec*10 + Ctod(*fmt++); ++ } ++ } ++ } ++ ++ ++ /* check format flag */ ++ negFlag = 0; ++ switch (*fmt) { ++ case 'b': ++ if (longFlag) { ++ num = va_arg(ap, long int); ++ } else { ++ num = va_arg(ap, int); ++ } ++ length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0); ++ OUTPUT(arg, buf, length); ++ break; ++ ++ case 'd': ++ case 'D': ++ if (longFlag) { ++ num = va_arg(ap, long int); ++ } else { ++ num = va_arg(ap, int); ++ } ++ if (num < 0) { ++ num = - num; ++ negFlag = 1; ++ } ++ length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0); ++ OUTPUT(arg, buf, length); ++ break; ++ ++ case 'o': ++ case 'O': ++ if (longFlag) { ++ num = va_arg(ap, long int); ++ } else { ++ num = va_arg(ap, int); ++ } ++ length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0); ++ OUTPUT(arg, buf, length); ++ break; ++ ++ case 'u': ++ case 'U': ++ if (longFlag) { ++ num = va_arg(ap, long int); ++ } else { ++ num = va_arg(ap, int); ++ } ++ length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0); ++ OUTPUT(arg, buf, length); ++ break; ++ ++ case 'x': ++ if (longFlag) { ++ num = va_arg(ap, long int); ++ } else { ++ num = va_arg(ap, int); ++ } ++ length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0); ++ OUTPUT(arg, buf, length); ++ break; ++ ++ case 'X': ++ if (longFlag) { ++ num = va_arg(ap, long int); ++ } else { ++ num = va_arg(ap, int); ++ } ++ length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1); ++ OUTPUT(arg, buf, length); ++ break; ++ ++ case 'c': ++ c = (char)va_arg(ap, int); ++ length = PrintChar(buf, c, width, ladjust); ++ OUTPUT(arg, buf, length); ++ break; ++ ++ case 's': ++ s = (char*)va_arg(ap, char *); ++ length = PrintString(buf, s, width, ladjust); ++ OUTPUT(arg, buf, length); ++ break; ++ ++ case '\0': ++ fmt --; ++ break; ++ ++ default: ++ /* output this char as it is */ ++ OUTPUT(arg, fmt, 1); ++ } /* switch (*fmt) */ ++ ++ fmt ++; ++ } /* for(;;) */ ++ ++ /* special termination call */ ++ OUTPUT(arg, "\0", 1); ++} ++ ++ ++/* --------------- local help functions --------------------- */ ++static int ++PrintChar(char * buf, char c, int length, int ladjust) ++{ ++ int i; ++ ++ if (length < 1) length = 1; ++ if (ladjust) { ++ *buf = c; ++ for (i=1; i< length; i++) buf[i] = ' '; ++ } else { ++ for (i=0; i< length-1; i++) buf[i] = ' '; ++ buf[length - 1] = c; ++ } ++ return length; ++} ++ ++static int ++PrintString(char * buf, char* s, int length, int ladjust) ++{ ++ int i; ++ int len=0; ++ char* s1 = s; ++ while (*s1++) len++; ++ if (length < len) length = len; ++ ++ if (ladjust) { ++ for (i=0; i< len; i++) buf[i] = s[i]; ++ for (i=len; i< length; i++) buf[i] = ' '; ++ } else { ++ for (i=0; i< length-len; i++) buf[i] = ' '; ++ for (i=length-len; i < length; i++) buf[i] = s[i-length+len]; ++ } ++ return length; ++} ++ ++static int ++PrintNum(char * buf, unsigned long u, int base, int negFlag, ++ int length, int ladjust, char padc, int upcase) ++{ ++ /* algorithm : ++ * 1. prints the number from left to right in reverse form. ++ * 2. fill the remaining spaces with padc if length is longer than ++ * the actual length ++ * TRICKY : if left adjusted, no "0" padding. ++ * if negtive, insert "0" padding between "0" and number. ++ * 3. if (!ladjust) we reverse the whole string including paddings ++ * 4. otherwise we only reverse the actual string representing the num. ++ */ ++ ++ int actualLength =0; ++ char *p = buf; ++ int i; ++ ++ do { ++ int tmp = u %base; ++ if (tmp <= 9) { ++ *p++ = '0' + tmp; ++ } else if (upcase) { ++ *p++ = 'A' + tmp - 10; ++ } else { ++ *p++ = 'a' + tmp - 10; ++ } ++ u /= base; ++ } while (u != 0); ++ ++ if (negFlag) { ++ *p++ = '-'; ++ } ++ ++ /* figure out actual length and adjust the maximum length */ ++ actualLength = p - buf; ++ if (length < actualLength) length = actualLength; ++ ++ /* add padding */ ++ if (ladjust) { ++ padc = ' '; ++ } ++ if (negFlag && !ladjust && (padc == '0')) { ++ for (i = actualLength-1; i< length-1; i++) buf[i] = padc; ++ buf[length -1] = '-'; ++ } else { ++ for (i = actualLength; i< length; i++) buf[i] = padc; ++ } ++ ++ ++ /* prepare to reverse the string */ ++ { ++ int begin = 0; ++ int end; ++ if (ladjust) { ++ end = actualLength - 1; ++ } else { ++ end = length -1; ++ } ++ ++ while (end > begin) { ++ char tmp = buf[begin]; ++ buf[begin] = buf[end]; ++ buf[end] = tmp; ++ begin ++; ++ end --; ++ } ++ } ++ ++ /* adjust the string pointer */ ++ return length; ++} ++ ++static void printf_output(void *arg, char *s, int l) ++{ ++ int i; ++ ++ // special termination call ++ if ((l==1) && (s[0] == '\0')) return; ++ ++ for (i=0; i< l; i++) { ++ board_putc(s[i]); ++ if (s[i] == '\n') board_putc('\r'); ++ } ++} ++ ++void printf(char *fmt, ...) ++{ ++ va_list ap; ++ va_start(ap, fmt); ++ lp_Print(printf_output, 0, fmt, ap); ++ va_end(ap); ++} +diff --git a/target/linux/ar71xx/image/lzma-loader/src/printf.h b/target/linux/ar71xx/image/lzma-loader/src/printf.h +new file mode 100644 +index 0000000000..9b1c1df232 +--- /dev/null ++++ b/target/linux/ar71xx/image/lzma-loader/src/printf.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (C) 2001 MontaVista Software Inc. ++ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net ++ * ++ * 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. ++ * ++ */ ++ ++#ifndef _printf_h_ ++#define _printf_h_ ++ ++#include ++void printf(char *fmt, ...); ++ ++#endif /* _printf_h_ */ +diff --git a/target/linux/ar71xx/image/mikrotik.mk b/target/linux/ar71xx/image/mikrotik.mk +new file mode 100644 +index 0000000000..871f4c5352 +--- /dev/null ++++ b/target/linux/ar71xx/image/mikrotik.mk +@@ -0,0 +1,61 @@ ++define Device/mikrotik ++ PROFILES := Default ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARD_NAME := routerboard ++ LOADER_TYPE := elf ++ KERNEL_NAME := vmlinux.bin.lzma ++ KERNEL := kernel-bin | loader-kernel ++ KERNEL_INITRAMFS_NAME := vmlinux-initramfs.bin.lzma ++ MIKROTIK_CHUNKSIZE := ++ IMAGE/sysupgrade.bin/squashfs := ++endef ++DEVICE_VARS += MIKROTIK_CHUNKSIZE ++ ++define Device/mikrotik-nand ++ $(Device/mikrotik) ++ IMAGE/sysupgrade.bin/squashfs = append-kernel | \ ++ kernel2minor -s $$(MIKROTIK_CHUNKSIZE) -e -c | sysupgrade-tar kernel=$$$$@ ++endef ++ ++define Device/nand-64m ++ $(Device/mikrotik-nand) ++ MIKROTIK_CHUNKSIZE := 512 ++ DEVICE_TITLE := MikroTik RouterBoard (64 MB NAND) ++endef ++TARGET_DEVICES += nand-64m ++ ++define Device/nand-large ++ $(Device/mikrotik-nand) ++ MIKROTIK_CHUNKSIZE := 2048 ++ DEVICE_TITLE := MikroTik RouterBoard (>= 128 MB NAND) ++endef ++TARGET_DEVICES += nand-large ++ ++define Device/nand-large-ac ++ $(Device/mikrotik-nand) ++ MIKROTIK_CHUNKSIZE := 2048 ++ DEVICE_TITLE := MikroTik RouterBoard (>= 128 MB NAND, 802.11ac) ++ DEVICE_PACKAGES += kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ SUPPORTED_DEVICES := rb-921gs-5hpacd-r2 rb-922uags-5hpacd ++endef ++TARGET_DEVICES += nand-large-ac ++ ++define Device/rb-nor-flash-16M ++ $(Device/mikrotik) ++ DEVICE_TITLE := MikroTik RouterBoard (16 MB SPI NOR) ++ DEVICE_PACKAGES := rssileds -nand-utils kmod-ledtrig-gpio ++ IMAGE_SIZE := 16000k ++ KERNEL_INSTALL := 1 ++ SUPPORTED_DEVICES := rb-750-r2 rb-750up-r2 rb-750p-pbr2 rb-911-2hn rb-911-5hn rb-931-2nd rb-941-2nd rb-951ui-2nd rb-952ui-5ac2nd rb-962uigs-5hact2hnt rb-lhg-5nd rb-map-2nd rb-mapl-2nd rb-wap-2nd rb-wapr-2nd rb-sxt-2nd-r3 ++ IMAGE/sysupgrade.bin := append-kernel | kernel2minor -s 1024 -e | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += rb-nor-flash-16M ++ ++define Device/rb-nor-flash-16M-ac ++ $(Device/rb-nor-flash-16M) ++ DEVICE_TITLE := MikroTik RouterBoard (16 MB SPI NOR, 802.11ac) ++ DEVICE_PACKAGES += kmod-ath10k-ct-smallbuffers ath10k-firmware-qca988x-ct ath10k-firmware-qca9887-ct kmod-usb-ehci ++ SUPPORTED_DEVICES += rb-wapg-5hact2hnd ++endef ++TARGET_DEVICES += rb-nor-flash-16M-ac +diff --git a/target/linux/ar71xx/image/nand.mk b/target/linux/ar71xx/image/nand.mk +new file mode 100644 +index 0000000000..8cf2e98234 +--- /dev/null ++++ b/target/linux/ar71xx/image/nand.mk +@@ -0,0 +1,137 @@ ++define Build/MerakiNAND ++ -$(STAGING_DIR_HOST)/bin/mkmerakifw \ ++ -B $(BOARDNAME) -s \ ++ -i $@ \ ++ -o $@.new ++ @mv $@.new $@ ++endef ++ ++define Build/MerakiNAND-old ++ -$(STAGING_DIR_HOST)/bin/mkmerakifw-old \ ++ -B $(BOARDNAME) -s \ ++ -i $@ \ ++ -o $@.new ++ @mv $@.new $@ ++endef ++ ++ ++define Device/c-60 ++ DEVICE_TITLE := AirTight C-60 ++ DEVICE_PACKAGES := kmod-spi-gpio kmod-usb2 kmod-ath9k ++ BOARDNAME := C-60 ++ BLOCKSIZE := 64k ++ KERNEL_SIZE := 3648k ++ IMAGE_SIZE := 32m ++ IMAGES := sysupgrade.tar ++ MTDPARTS := spi0.0:256k(u-boot)ro,128k(u-boot-env)ro,3648k(kernel),64k(art)ro;ar934x-nfc:32m(ubi) ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImage lzma ++ IMAGE/sysupgrade.tar := sysupgrade-tar ++endef ++TARGET_DEVICES += c-60 ++ ++define Device/domywifi-dw33d ++ DEVICE_TITLE := DomyWifi DW33D ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage kmod-usb-ledtrig-usbport kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := DW33D ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14528k(rootfs),1472k(kernel),64k(art)ro,16000k@0x50000(firmware);ar934x-nfc:96m(rootfs_data),32m(backup)ro ++ IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs | pad-to 14528k | append-kernel | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += domywifi-dw33d ++ ++define Device/hiveap-121 ++ DEVICE_TITLE := Aerohive HiveAP-121 ++ DEVICE_PACKAGES := kmod-usb2 kmod-i2c-gpio-custom kmod-spi-gpio kmod-ath9k kmod-tpm-i2c-atmel ++ BOARDNAME := HiveAP-121 ++ BLOCKSIZE := 128k ++ PAGESIZE := 2048 ++ IMAGE_SIZE := 115m ++ KERNEL_SIZE := 5120k ++ UBINIZE_OPTS := -E 5 ++ CONSOLE := ttyS0,9600 ++ MTDPARTS := spi0.0:512k(u-boot)ro,64k(u-boot-env),64k(hw-info)ro,64k(boot-info)ro,64k(boot-sinfo)ro;ar934x-nfc:4096k(u-boot-1),4096k(u-boot-env-1),5m(kernel),111m(ubi),4096k(wifi-info)ro ++ IMAGES := sysupgrade.tar factory.bin ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImage lzma ++ IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | check-size $$$$(IMAGE_SIZE) ++ IMAGE/sysupgrade.tar := sysupgrade-tar ++endef ++TARGET_DEVICES += hiveap-121 ++ ++define Device/mr18 ++ DEVICE_TITLE := Meraki MR18 ++ DEVICE_PACKAGES := kmod-spi-gpio kmod-ath9k ++ BOARDNAME := MR18 ++ BLOCKSIZE := 64k ++ MTDPARTS := ar934x-nfc:512k(nandloader)ro,8M(kernel),8M(recovery),113664k(ubi),128k@130944k(odm-caldata)ro ++ IMAGES := sysupgrade.tar ++ KERNEL := kernel-bin | patch-cmdline | MerakiNAND ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | MerakiNAND ++ IMAGE/sysupgrade.tar := sysupgrade-tar ++endef ++TARGET_DEVICES += mr18 ++ ++define Device/rambutan ++ DEVICE_TITLE := 8devices Rambutan ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := RAMBUTAN ++ BLOCKSIZE := 128KiB ++ MTDPARTS := ar934x-nfc:3M(u-boot)ro,2M(u-boot-env),1M(art),122M(ubi) ++ PAGESIZE := 2048 ++ KERNEL_IN_UBI := 1 ++ IMAGES := factory.ubi sysupgrade.tar ++ IMAGE/sysupgrade.tar := sysupgrade-tar ++ IMAGE/factory.ubi := append-ubi ++endef ++TARGET_DEVICES += rambutan ++ ++define Device/wi2a-ac200i ++ SUPPORTED_DEVICES = $(1) ++ DEVICE_TITLE := Nokia WI2A-AC200i ++ DEVICE_PACKAGES := kmod-usb2 kmod-ath9k kmod-ath10k-ct ath10k-firmware-qca988x-ct ++ BOARDNAME := WI2A-AC200i ++ BLOCKSIZE := 64k ++ KERNEL_SIZE := 3648k ++ IMAGE_SIZE := 32m ++ IMAGES := sysupgrade.tar ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(envFacA)ro,64k(envFacB)ro,64k(ART)ro,128k(u-boot-env) ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImage lzma ++ IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata ++endef ++TARGET_DEVICES += wi2a-ac200i ++ ++define Device/z1 ++ DEVICE_TITLE := Meraki Z1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport kmod-spi-gpio kmod-ath9k kmod-owl-loader ++ BOARDNAME := Z1 ++ BLOCKSIZE := 64k ++ MTDPARTS := ar934x-nfc:128K(loader1)ro,8064K(kernel),128K(loader2)ro,8064K(recovery),114560K(ubi),128K(origcaldata)ro ++ IMAGES := sysupgrade.tar ++ KERNEL := kernel-bin | patch-cmdline | MerakiNAND-old ++ KERNEL_INITRAMFS := kernel-bin | patch-cmdline | MerakiNAND-old ++ IMAGE/sysupgrade.tar := sysupgrade-tar ++endef ++TARGET_DEVICES += z1 ++ ++define LegacyDevice/R6100 ++ DEVICE_TITLE := NETGEAR R6100 ++ DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += R6100 ++ ++define LegacyDevice/WNDR3700V4 ++ DEVICE_TITLE := NETGEAR WNDR3700v4 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WNDR3700V4 ++ ++define LegacyDevice/WNDR4300V1 ++ DEVICE_TITLE := NETGEAR WNDR4300v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WNDR4300V1 ++ ++define LegacyDevice/NBG6716 ++ DEVICE_TITLE := Zyxel NBG 6716 ++ DEVICE_PACKAGES := kmod-rtc-pcf8563 kmod-ath10k-ct ath10k-firmware-qca988x-ct ++endef ++LEGACY_DEVICES += NBG6716 +diff --git a/target/linux/ar71xx/image/tiny-legacy-devices.mk b/target/linux/ar71xx/image/tiny-legacy-devices.mk +new file mode 100644 +index 0000000000..7f63d19de0 +--- /dev/null ++++ b/target/linux/ar71xx/image/tiny-legacy-devices.mk +@@ -0,0 +1,161 @@ ++define LegacyDevice/F9K1115V2 ++ DEVICE_TITLE := Belkin AC1750DB (F9K1115V2) ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb3 kmod-usb-ledtrig-usbport \ ++ kmod-ath10k-ct ath10k-firmware-qca988x-ct ++endef ++LEGACY_DEVICES += F9K1115V2 ++ ++define LegacyDevice/DIR600A1 ++ DEVICE_TITLE := D-Link DIR-600 rev. A1 ++endef ++LEGACY_DEVICES += DIR600A1 ++ ++define LegacyDevice/DIR601A1 ++ DEVICE_TITLE := D-Link DIR-601 rev. A1 ++endef ++LEGACY_DEVICES += DIR601A1 ++ ++define LegacyDevice/FR54RTR ++ DEVICE_TITLE := Frys FR-54RTR ++endef ++LEGACY_DEVICES += FR54RTR ++ ++define LegacyDevice/EBR2310C1 ++ DEVICE_TITLE := D-Link EBR-2310 rev. C1 ++endef ++LEGACY_DEVICES += EBR2310C1 ++ ++define LegacyDevice/DIR615E1 ++ DEVICE_TITLE := D-Link DIR-615 rev. E1 ++endef ++LEGACY_DEVICES += DIR615E1 ++ ++define LegacyDevice/DIR615E4 ++ DEVICE_TITLE := D-Link DIR-615 rev. E4 ++endef ++LEGACY_DEVICES += DIR615E4 ++ ++define LegacyDevice/DIR615I1 ++ DEVICE_TITLE := D-Link DIR-615 rev. I1 ++endef ++LEGACY_DEVICES += DIR615I1 ++ ++define LegacyDevice/DIR615I3 ++ DEVICE_TITLE := D-Link DIR-615 rev. I3 ++endef ++LEGACY_DEVICES += DIR615I3 ++ ++define LegacyDevice/A02RBW300N ++ DEVICE_TITLE := Atlantis-Land A02-RB-W300N ++endef ++LEGACY_DEVICES += A02RBW300N ++ ++define LegacyDevice/DIR615C1 ++ DEVICE_TITLE := D-Link DIR-615 rev. C1 ++endef ++LEGACY_DEVICES += DIR615C1 ++ ++define LegacyDevice/TEW632BRP ++ DEVICE_TITLE := TRENDNet TEW-632BRP ++endef ++LEGACY_DEVICES += TEW632BRP ++ ++define LegacyDevice/TEW652BRP_FW ++ DEVICE_TITLE := TRENDNet TEW-652BRP ++endef ++LEGACY_DEVICES += TEW652BRP_FW ++ ++define LegacyDevice/TEW652BRP_RECOVERY ++ DEVICE_TITLE := TRENDNet TEW-652BRP (recovery) ++endef ++LEGACY_DEVICES += TEW652BRP_RECOVERY ++ ++define LegacyDevice/TEW712BR ++ DEVICE_TITLE := TRENDNet TEW-712BR ++endef ++LEGACY_DEVICES += TEW712BR ++ ++define LegacyDevice/DIR601B1 ++ DEVICE_TITLE := D-Link DIR-601 rev. B1 ++endef ++LEGACY_DEVICES += DIR601B1 ++ ++define LegacyDevice/WP543_4M ++ DEVICE_TITLE := Compex WP543/WPJ543 (4MB flash) ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += WP543_4M ++ ++define LegacyDevice/WPE72_4M ++ DEVICE_TITLE := Compex WPE72/WPE72NX (4MB flash) ++ DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 ++endef ++LEGACY_DEVICES += WPE72_4M ++ ++define LegacyDevice/WNR2000 ++ DEVICE_TITLE := NETGEAR WNR2000V1 ++endef ++LEGACY_DEVICES += WNR2000 ++ ++define LegacyDevice/WNR2000V3 ++ DEVICE_TITLE := NETGEAR WNR2000V3 ++endef ++LEGACY_DEVICES += WNR2000V3 ++ ++define LegacyDevice/WNR2000V4 ++ DEVICE_TITLE := NETGEAR WNR2000V4 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++endef ++LEGACY_DEVICES += WNR2000V4 ++ ++define LegacyDevice/REALWNR612V2 ++ DEVICE_TITLE := NETGEAR WNR612V2 ++endef ++LEGACY_DEVICES += REALWNR612V2 ++ ++define LegacyDevice/N150R ++ DEVICE_TITLE := On Networks N150 ++endef ++LEGACY_DEVICES += N150R ++ ++define LegacyDevice/REALWNR1000V2 ++ DEVICE_TITLE := NETGEAR WNR1000V2 ++endef ++LEGACY_DEVICES += REALWNR1000V2 ++ ++define LegacyDevice/WNR1000V2_VC ++ DEVICE_TITLE := NETGEAR WNR1000V2-VC ++endef ++LEGACY_DEVICES += WNR1000V2_VC ++ ++define LegacyDevice/WPN824N ++ DEVICE_TITLE := NETGEAR WPN824N ++endef ++LEGACY_DEVICES += WPN824N ++ ++define LegacyDevice/WHRG301N ++ DEVICE_TITLE := Buffalo WHR-G301N ++endef ++LEGACY_DEVICES += WHRG301N ++ ++define LegacyDevice/WHRHPG300N ++ DEVICE_TITLE := Buffalo WHR-HP-G300N ++endef ++LEGACY_DEVICES += WHRHPG300N ++ ++define LegacyDevice/WHRHPGN ++ DEVICE_TITLE := Buffalo WHR-HP-GN ++endef ++LEGACY_DEVICES += WHRHPGN ++ ++define LegacyDevice/WLAEAG300N ++ DEVICE_TITLE := Buffalo WLAE-AG300N ++ DEVICE_PACKAGES := kmod-ledtrig-netdev ++endef ++LEGACY_DEVICES += WLAEAG300N ++ ++define LegacyDevice/NBG_460N_550N_550NH ++ DEVICE_TITLE := ZyXEL NBG 460N/550N/550NH ++ DEVICE_PACKAGES := kmod-rtc-pcf8563 ++endef ++LEGACY_DEVICES += NBG_460N_550N_550NH +diff --git a/target/linux/ar71xx/image/tiny-senao.mk b/target/linux/ar71xx/image/tiny-senao.mk +new file mode 100644 +index 0000000000..3a7f6776b3 +--- /dev/null ++++ b/target/linux/ar71xx/image/tiny-senao.mk +@@ -0,0 +1,28 @@ ++define Build/senao-factory-image ++ mkdir -p $@.senao ++ ++ touch $@.senao/FWINFO-OpenWrt-$(REVISION)-$(1) ++ $(CP) $(IMAGE_KERNEL) $@.senao/openwrt-senao-$(1)-uImage-lzma.bin ++ $(CP) $@ $@.senao/openwrt-senao-$(1)-root.squashfs ++ ++ $(TAR) -c \ ++ --numeric-owner --owner=0 --group=0 --sort=name \ ++ $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \ ++ -C $@.senao . | gzip -9nc > $@ ++ ++ rm -rf $@.senao ++endef ++ ++ ++define Device/ens202ext ++ DEVICE_TITLE := EnGenius ENS202EXT ++ BOARDNAME := ENS202EXT ++ DEVICE_PACKAGES := rssileds ++ KERNEL_SIZE := 1536k ++ IMAGE_SIZE := 13632k ++ IMAGES += factory.bin ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),320k(custom)ro,1536k(kernel),12096k(rootfs),2048k(failsafe)ro,64k(art)ro,13632k@0xa0000(firmware) ++ IMAGE/factory.bin := append-rootfs | pad-rootfs | senao-factory-image ens202ext ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += ens202ext +diff --git a/target/linux/ar71xx/image/tiny-tp-link.mk b/target/linux/ar71xx/image/tiny-tp-link.mk +new file mode 100644 +index 0000000000..5874808d21 +--- /dev/null ++++ b/target/linux/ar71xx/image/tiny-tp-link.mk +@@ -0,0 +1,695 @@ ++include ./common-tp-link.mk ++ ++ ++define Device/tl-mr10u-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-MR10U v1 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := TL-MR10U ++ DEVICE_PROFILE := TLMR10U ++ TPLINK_HWID := 0x00100101 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-mr10u-v1 ++ ++define Device/tl-mr11u-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-MR11U v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-MR11U ++ DEVICE_PROFILE := TLMR11U ++ TPLINK_HWID := 0x00110101 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-mr11u-v1 ++ ++define Device/tl-mr11u-v2 ++ $(Device/tl-mr11u-v1) ++ DEVICE_TITLE := TP-LINK TL-MR11U v2 ++ TPLINK_HWID := 0x00110102 ++endef ++TARGET_DEVICES += tl-mr11u-v2 ++ ++define Device/tl-mr12u-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-MR12U v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-MR13U ++ DEVICE_PROFILE := TLMR12U ++ TPLINK_HWID := 0x00120101 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-mr12u-v1 ++ ++define Device/tl-mr13u-v1 ++ $(Device/tl-mr12u-v1) ++ DEVICE_TITLE := TP-LINK TL-MR13U v1 ++ DEVICE_PROFILE := TLMR13U ++ TPLINK_HWID := 0x00130101 ++endef ++TARGET_DEVICES += tl-mr13u-v1 ++ ++define Device/tl-mr3020-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-MR3020 v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-MR3020 ++ DEVICE_PROFILE := TLMR3020 ++ TPLINK_HWID := 0x30200001 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-mr3020-v1 ++ ++define Device/tl-mr3040-v1 ++ $(Device/tl-mr3020-v1) ++ DEVICE_TITLE := TP-LINK TL-MR3040 v1 ++ BOARDNAME := TL-MR3040 ++ DEVICE_PROFILE := TLMR3040 ++ TPLINK_HWID := 0x30400001 ++endef ++TARGET_DEVICES += tl-mr3040-v1 ++ ++define Device/tl-mr3040-v2 ++ $(Device/tl-mr3040-v1) ++ DEVICE_TITLE := TP-LINK TL-MR3040 v2 ++ BOARDNAME := TL-MR3040-v2 ++ TPLINK_HWID := 0x30400002 ++endef ++TARGET_DEVICES += tl-mr3040-v2 ++ ++define Device/tl-mr3220-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-MR3220 v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-MR3220 ++ DEVICE_PROFILE := TLMR3220 ++ TPLINK_HWID := 0x32200001 ++endef ++TARGET_DEVICES += tl-mr3220-v1 ++ ++define Device/tl-mr3220-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-MR3220 v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-MR3220-v2 ++ DEVICE_PROFILE := TLMR3220 ++ TPLINK_HWID := 0x32200002 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-mr3220-v2 ++ ++define Device/tl-mr3420-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-MR3420 v1 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-MR3420 ++ DEVICE_PROFILE := TLMR3420 ++ TPLINK_HWID := 0x34200001 ++endef ++TARGET_DEVICES += tl-mr3420-v1 ++ ++define Device/tl-mr3420-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-MR3420 v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-MR3420-v2 ++ DEVICE_PROFILE := TLMR3420 ++ TPLINK_HWID := 0x34200002 ++endef ++TARGET_DEVICES += tl-mr3420-v2 ++ ++define Device/tl-wa701nd-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WA701N/ND v1 ++ BOARDNAME := TL-WA901ND ++ DEVICE_PROFILE := TLWA701 ++ TPLINK_HWID := 0x07010001 ++endef ++TARGET_DEVICES += tl-wa701nd-v1 ++ ++define Device/tl-wa701nd-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA701N/ND v2 ++ BOARDNAME := TL-WA701ND-v2 ++ DEVICE_PROFILE := TLWA701 ++ TPLINK_HWID := 0x07010002 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-wa701nd-v2 ++ ++define Device/tl-wa7210n-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA7210N v2 ++ DEVICE_PACKAGES := rssileds kmod-ledtrig-netdev ++ BOARDNAME := TL-WA7210N-v2 ++ DEVICE_PROFILE := TLWA7210 ++ TPLINK_HWID := 0x72100002 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-wa7210n-v2 ++ ++define Device/tl-wa730re-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WA730RE v1 ++ BOARDNAME := TL-WA901ND ++ DEVICE_PROFILE := TLWA730RE ++ TPLINK_HWID := 0x07300001 ++endef ++TARGET_DEVICES += tl-wa730re-v1 ++ ++define Device/tl-wa750re-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA750RE v1 ++ DEVICE_PACKAGES := rssileds ++ BOARDNAME := TL-WA750RE ++ DEVICE_PROFILE := TLWA750 ++ TPLINK_HWID := 0x07500001 ++endef ++TARGET_DEVICES += tl-wa750re-v1 ++ ++define Device/tl-wa7510n-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WA7510N v1 ++ BOARDNAME := TL-WA7510N ++ DEVICE_PROFILE := TLWA7510 ++ TPLINK_HWID := 0x75100001 ++endef ++TARGET_DEVICES += tl-wa7510n-v1 ++ ++define Device/tl-wa801nd-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WA801N/ND v1 ++ BOARDNAME := TL-WA901ND ++ DEVICE_PROFILE := TLWA801 ++ TPLINK_HWID := 0x08010001 ++endef ++TARGET_DEVICES += tl-wa801nd-v1 ++ ++define Device/tl-wa801nd-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA801N/ND v2 ++ BOARDNAME := TL-WA801ND-v2 ++ DEVICE_PROFILE := TLWA801 ++ TPLINK_HWID := 0x08010002 ++endef ++TARGET_DEVICES += tl-wa801nd-v2 ++ ++define Device/tl-wa801nd-v3 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA801N/ND v3 ++ BOARDNAME := TL-WA801ND-v3 ++ DEVICE_PROFILE := TLWA801 ++ TPLINK_HWID := 0x08010003 ++endef ++TARGET_DEVICES += tl-wa801nd-v3 ++ ++define Device/tl-wa801nd-v4 ++ $(Device/tl-wa801nd-v3) ++ DEVICE_TITLE := TP-LINK TL-WA801N/ND v4 ++ TPLINK_HWID := 0x08010004 ++endef ++TARGET_DEVICES += tl-wa801nd-v4 ++ ++define Device/tl-wa830re-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WA830RE v1 ++ BOARDNAME := TL-WA901ND ++ DEVICE_PROFILE := TLWA830 ++ TPLINK_HWID := 0x08300010 ++endef ++TARGET_DEVICES += tl-wa830re-v1 ++ ++define Device/tl-wa830re-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA830RE v2 ++ BOARDNAME := TL-WA830RE-v2 ++ DEVICE_PROFILE := TLWA830 ++ TPLINK_HWID := 0x08300002 ++endef ++TARGET_DEVICES += tl-wa830re-v2 ++ ++define Device/tl-wa850re-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA850RE v1 ++ DEVICE_PACKAGES := rssileds ++ BOARDNAME := TL-WA850RE ++ DEVICE_PROFILE := TLWA850 ++ TPLINK_HWID := 0x08500001 ++endef ++TARGET_DEVICES += tl-wa850re-v1 ++ ++define Device/tl-wa850re-v2 ++ $(Device/tplink-safeloader) ++ DEVICE_TITLE := TP-LINK TL-WA850RE v2 ++ DEVICE_PACKAGES := rssileds ++ BOARDNAME := TL-WA850RE-V2 ++ DEVICE_PROFILE := TLWA850 ++ TPLINK_BOARD_ID := TLWA850REV2 ++ TPLINK_HWID := 0x08500002 ++ TPLINK_HWREV := 0 ++ IMAGE_SIZE := 3648k ++ MTDPARTS := spi0.0:128k(u-boot)ro,3648k(firmware),256k(config)ro,64k(art)ro ++endef ++TARGET_DEVICES += tl-wa850re-v2 ++ ++define Device/tl-wa855re-v1 ++ $(Device/tplink-safeloader) ++ DEVICE_TITLE := TP-LINK TL-WA855RE v1 ++ BOARDNAME := TL-WA855RE-v1 ++ DEVICE_PROFILE := TLWA855RE ++ TPLINK_HWID := 0x08550001 ++ TPLINK_BOARD_ID := TLWA855REV1 ++ TPLINK_HWREV := 0 ++ IMAGE_SIZE := 3648k ++ MTDPARTS := spi0.0:128k(u-boot)ro,1344k(kernel),2304k(rootfs),256k(config)ro,64k(art)ro,3648k@0x20000(firmware) ++endef ++TARGET_DEVICES += tl-wa855re-v1 ++ ++define Device/tl-wa860re-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA860RE v1 ++ BOARDNAME := TL-WA860RE ++ DEVICE_PROFILE := TLWA860 ++ TPLINK_HWID := 0x08600001 ++endef ++TARGET_DEVICES += tl-wa860re-v1 ++ ++define Device/tl-wa901nd-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WA901N/ND v1 ++ BOARDNAME := TL-WA901ND ++ DEVICE_PROFILE := TLWA901 ++ TPLINK_HWID := 0x09010001 ++endef ++TARGET_DEVICES += tl-wa901nd-v1 ++ ++define Device/tl-wa901nd-v2 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WA901N/ND v2 ++ BOARDNAME := TL-WA901ND-v2 ++ DEVICE_PROFILE := TLWA901 ++ TPLINK_HWID := 0x09010002 ++endef ++TARGET_DEVICES += tl-wa901nd-v2 ++ ++define Device/tl-wa901nd-v3 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA901N/ND v3 ++ BOARDNAME := TL-WA901ND-v3 ++ DEVICE_PROFILE := TLWA901 ++ TPLINK_HWID := 0x09010003 ++endef ++TARGET_DEVICES += tl-wa901nd-v3 ++ ++define Device/tl-wa901nd-v4 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WA901N/ND v4 ++ BOARDNAME := TL-WA901ND-v4 ++ DEVICE_PROFILE := TLWA901 ++ TPLINK_HWID := 0x09010004 ++ IMAGE/factory.bin := append-rootfs | mktplinkfw factory -C EU ++endef ++TARGET_DEVICES += tl-wa901nd-v4 ++ ++define Device/tl-wa901nd-v5 ++ $(Device/tl-wa901nd-v4) ++ DEVICE_TITLE := TP-LINK TL-WA901N/ND v5 ++ BOARDNAME := TL-WA901ND-v5 ++ TPLINK_HWID := 0x09010005 ++endef ++TARGET_DEVICES += tl-wa901nd-v5 ++ ++define Device/tl-wdr3320-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WDR3320 v2 ++ DEVICE_PACKAGES := kmod-usb2 kmod-usb-ledtrig-usbport ++ BOARDNAME := TL-WDR3320-v2 ++ DEVICE_PROFILE := TLWDR3320V2 ++ TPLINK_HWID := 0x33200002 ++ TPLINK_HEADER_VERSION := 2 ++endef ++TARGET_DEVICES += tl-wdr3320-v2 ++ ++define Device/tl-wr1041n-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR1041N v2 ++ BOARDNAME := TL-WR1041N-v2 ++ DEVICE_PROFILE := TLWR1041 ++ TPLINK_HWID := 0x10410002 ++endef ++TARGET_DEVICES += tl-wr1041n-v2 ++ ++define Device/tl-wr703n-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR703N v1 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := TL-WR703N ++ DEVICE_PROFILE := TLWR703 ++ TPLINK_HWID := 0x07030101 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-wr703n-v1 ++ ++define Device/tl-wr710n-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR710N v2 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := TL-WR710N ++ DEVICE_PROFILE := TLWR710 ++ TPLINK_HWID := 0x07100002 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-wr710n-v2 ++ ++define Device/tl-wr720n-v3 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR720N v3 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := TL-WR720N-v3 ++ DEVICE_PROFILE := TLWR720 ++ TPLINK_HWID := 0x07200103 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-wr720n-v3 ++ ++define Device/tl-wr720n-v4 ++ $(Device/tl-wr720n-v3) ++ DEVICE_TITLE := TP-LINK TL-WR720N v4 ++ TPLINK_HWID := 0x07200104 ++endef ++TARGET_DEVICES += tl-wr720n-v4 ++ ++define Device/tl-wr740n-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR740N/ND v1 ++ BOARDNAME := TL-WR741ND ++ DEVICE_PROFILE := TLWR740 ++ TPLINK_HWID := 0x07400001 ++endef ++TARGET_DEVICES += tl-wr740n-v1 ++ ++define Device/tl-wr740n-v3 ++ $(Device/tl-wr740n-v1) ++ DEVICE_TITLE := TP-LINK TL-WR740N/ND v3 ++ TPLINK_HWID := 0x07400003 ++endef ++TARGET_DEVICES += tl-wr740n-v3 ++ ++define Device/tl-wr740n-v4 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR740N/ND v4 ++ BOARDNAME := TL-WR741ND-v4 ++ DEVICE_PROFILE := TLWR740 ++ TPLINK_HWID := 0x07400004 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-wr740n-v4 ++ ++define Device/tl-wr740n-v5 ++ $(Device/tl-wr740n-v4) ++ DEVICE_TITLE := TP-LINK TL-WR740N/ND v5 ++ TPLINK_HWID := 0x07400005 ++endef ++TARGET_DEVICES += tl-wr740n-v5 ++ ++define Device/tl-wr740n-v6 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR740N/ND v6 ++ BOARDNAME := TL-WR740N-v6 ++ DEVICE_PROFILE := TLWR740 ++ TPLINK_HWID := 0x07400006 ++endef ++TARGET_DEVICES += tl-wr740n-v6 ++ ++define Device/tl-wr741nd-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR741N/ND v1 ++ BOARDNAME := TL-WR741ND ++ DEVICE_PROFILE := TLWR741 ++ TPLINK_HWID := 0x07410001 ++endef ++TARGET_DEVICES += tl-wr741nd-v1 ++ ++define Device/tl-wr741nd-v2 ++ $(Device/tl-wr741nd-v1) ++ DEVICE_TITLE := TP-LINK TL-WR741N/ND v2 ++endef ++TARGET_DEVICES += tl-wr741nd-v2 ++ ++define Device/tl-wr741nd-v4 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR741N/ND v4 ++ BOARDNAME := TL-WR741ND-v4 ++ DEVICE_PROFILE := TLWR741 ++ TPLINK_HWID := 0x07410004 ++ CONSOLE := ttyATH0,115200 ++endef ++TARGET_DEVICES += tl-wr741nd-v4 ++ ++define Device/tl-wr741nd-v5 ++ $(Device/tl-wr741nd-v4) ++ DEVICE_TITLE := TP-LINK TL-WR741N/ND v5 ++ TPLINK_HWID := 0x07400005 ++endef ++TARGET_DEVICES += tl-wr741nd-v5 ++ ++define Device/tl-wr743nd-v1 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR743N/ND v1 ++ BOARDNAME := TL-WR741ND ++ DEVICE_PROFILE := TLWR743 ++ TPLINK_HWID := 0x07430001 ++endef ++TARGET_DEVICES += tl-wr743nd-v1 ++ ++define Device/tl-wr743nd-v2 ++ $(Device/tl-wr741nd-v4) ++ DEVICE_TITLE := TP-LINK TL-WR743N/ND v2 ++ DEVICE_PROFILE := TLWR743 ++ TPLINK_HWID := 0x07430002 ++endef ++TARGET_DEVICES += tl-wr743nd-v2 ++ ++define Device/tl-wr802n-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR802N v1 ++ BOARDNAME := TL-WR802N-v1 ++ DEVICE_PROFILE := TLWR802 ++ TPLINK_HWID := 0x08020001 ++ TPLINK_HWREV := 1 ++endef ++TARGET_DEVICES += tl-wr802n-v1 ++ ++define Device/tl-wr802n-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR802N v2 ++ BOARDNAME := TL-WR802N-v2 ++ DEVICE_PROFILE := TLWR802 ++ TPLINK_HWID := 0x08020002 ++ TPLINK_HWREV := 2 ++ IMAGES += factory-us.bin factory-eu.bin ++ IMAGE/factory-us.bin := append-rootfs | mktplinkfw factory -C US ++ IMAGE/factory-eu.bin := append-rootfs | mktplinkfw factory -C EU ++endef ++TARGET_DEVICES += tl-wr802n-v2 ++ ++define Device/tl-wr840n-v2 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR840N v2 ++ BOARDNAME := TL-WR840N-v2 ++ DEVICE_PROFILE := TLWR840 ++ TPLINK_HWID := 0x08400002 ++ IMAGES += factory-eu.bin ++ IMAGE/factory-eu.bin := append-rootfs | mktplinkfw factory -C EU ++endef ++TARGET_DEVICES += tl-wr840n-v2 ++ ++define Device/tl-wr840n-v3 ++ $(Device/tl-wr840n-v2) ++ DEVICE_TITLE := TP-LINK TL-WR840N v3 ++ BOARDNAME := TL-WR840N-v3 ++ TPLINK_HWID := 0x08400003 ++endef ++TARGET_DEVICES += tl-wr840n-v3 ++ ++define Device/tl-wr841-v1.5 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v1.5 ++ BOARDNAME := TL-WR841N-v1.5 ++ DEVICE_PROFILE := TLWR841 ++ TPLINK_HWID := 0x08410002 ++ TPLINK_HWREV := 2 ++endef ++TARGET_DEVICES += tl-wr841-v1.5 ++ ++define Device/tl-wr841-v3 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v3 ++ BOARDNAME := TL-WR941ND ++ DEVICE_PROFILE := TLWR841 ++ TPLINK_HWID := 0x08410003 ++ TPLINK_HWREV := 3 ++endef ++TARGET_DEVICES += tl-wr841-v3 ++ ++define Device/tl-wr841-v5 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v5 ++ BOARDNAME := TL-WR741ND ++ DEVICE_PROFILE := TLWR841 ++ TPLINK_HWID := 0x08410005 ++endef ++TARGET_DEVICES += tl-wr841-v5 ++ ++define Device/tl-wr841-v7 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v7 ++ BOARDNAME := TL-WR841N-v7 ++ DEVICE_PROFILE := TLWR841 ++ TPLINK_HWID := 0x08410007 ++endef ++TARGET_DEVICES += tl-wr841-v7 ++ ++define Device/tl-wr841-v8 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v8 ++ BOARDNAME := TL-WR841N-v8 ++ DEVICE_PROFILE := TLWR841 ++ TPLINK_HWID := 0x08410008 ++endef ++TARGET_DEVICES += tl-wr841-v8 ++ ++define Device/tl-wr841-v9 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v9 ++ BOARDNAME := TL-WR841N-v9 ++ DEVICE_PROFILE := TLWR841 ++ TPLINK_HWID := 0x08410009 ++endef ++TARGET_DEVICES += tl-wr841-v9 ++ ++define Device/tl-wr841-v10 ++ $(Device/tl-wr841-v9) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v10 ++ TPLINK_HWID := 0x08410010 ++endef ++TARGET_DEVICES += tl-wr841-v10 ++ ++define Device/tl-wr841-v11 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v11 ++ BOARDNAME := TL-WR841N-v11 ++ DEVICE_PROFILE := TLWR841 ++ TPLINK_HWID := 0x08410011 ++ IMAGES += factory-us.bin factory-eu.bin ++ IMAGE/factory-us.bin := append-rootfs | mktplinkfw factory -C US ++ IMAGE/factory-eu.bin := append-rootfs | mktplinkfw factory -C EU ++endef ++TARGET_DEVICES += tl-wr841-v11 ++ ++define Device/tl-wr841-v12 ++ $(Device/tl-wr841-v11) ++ DEVICE_TITLE := TP-LINK TL-WR841N/ND v12 ++ TPLINK_HWID := 0x08410012 ++endef ++TARGET_DEVICES += tl-wr841-v12 ++ ++define Device/tl-wr843nd-v1 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR843N/ND v1 ++ BOARDNAME := TL-WR841N-v8 ++ DEVICE_PROFILE := TLWR843 ++ TPLINK_HWID := 0x08430001 ++endef ++TARGET_DEVICES += tl-wr843nd-v1 ++ ++define Device/tl-wr847n-v8 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR847N/ND v8 ++ BOARDNAME := TL-WR841N-v8 ++ DEVICE_PROFILE := TLWR841 ++ TPLINK_HWID := 0x08470008 ++endef ++TARGET_DEVICES += tl-wr847n-v8 ++ ++define Device/tl-wr940n-v4 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR940N v4 ++ BOARDNAME := TL-WR940N-v4 ++ DEVICE_PROFILE := TLWR941 ++ TPLINK_HWID := 0x09400004 ++ IMAGES += factory-us.bin factory-eu.bin factory-br.bin ++ IMAGE/factory-us.bin := append-rootfs | mktplinkfw factory -C US ++ IMAGE/factory-eu.bin := append-rootfs | mktplinkfw factory -C EU ++ IMAGE/factory-br.bin := append-rootfs | mktplinkfw factory -C BR ++endef ++TARGET_DEVICES += tl-wr940n-v4 ++ ++define Device/tl-wr940n-v6 ++ $(Device/tl-wr940n-v4) ++ DEVICE_TITLE := TP-LINK TL-WR940N v6 ++ BOARDNAME := TL-WR940N-v6 ++ TPLINK_HWID := 0x09400006 ++endef ++TARGET_DEVICES += tl-wr940n-v6 ++ ++define Device/tl-wr941nd-v2 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR941N/ND v2 ++ BOARDNAME := TL-WR941ND ++ DEVICE_PROFILE := TLWR941 ++ TPLINK_HWID := 0x09410002 ++ TPLINK_HWREV := 2 ++endef ++TARGET_DEVICES += tl-wr941nd-v2 ++ ++define Device/tl-wr941nd-v3 ++ $(Device/tl-wr941nd-v2) ++ DEVICE_TITLE := TP-LINK TL-WR941N/ND v3 ++endef ++TARGET_DEVICES += tl-wr941nd-v3 ++ ++define Device/rnx-n360rt ++ $(Device/tl-wr941nd-v2) ++ DEVICE_TITLE := Rosewill RNX-N360RT ++ DEVICE_PROFILE := RNXN360RT ++ TPLINK_HWREV := 0x00420001 ++endef ++TARGET_DEVICES += rnx-n360rt ++ ++define Device/tl-wr941nd-v4 ++ $(Device/tplink-4m) ++ DEVICE_TITLE := TP-LINK TL-WR941N/ND v4 ++ BOARDNAME := TL-WR741ND ++ DEVICE_PROFILE := TLWR941 ++ TPLINK_HWID := 0x09410004 ++endef ++TARGET_DEVICES += tl-wr941nd-v4 ++ ++define Device/tl-wr941nd-v5 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR941N/ND v5 ++ BOARDNAME := TL-WR941ND-v5 ++ DEVICE_PROFILE := TLWR941 ++ TPLINK_HWID := 0x09410005 ++endef ++TARGET_DEVICES += tl-wr941nd-v5 ++ ++define Device/tl-wr941nd-v6 ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR941N/ND v6 ++ BOARDNAME := TL-WR941ND-v6 ++ DEVICE_PROFILE := TLWR941 ++ TPLINK_HWID := 0x09410006 ++endef ++TARGET_DEVICES += tl-wr941nd-v6 ++ ++# Chinese version (unlike European) is similar to the TL-WDR3500 ++define Device/tl-wr941nd-v6-cn ++ $(Device/tplink-4mlzma) ++ DEVICE_TITLE := TP-LINK TL-WR941N/ND v6 (CN) ++ BOARDNAME := TL-WDR3500 ++ DEVICE_PROFILE := TLWR941 ++ TPLINK_HWID := 0x09410006 ++endef ++TARGET_DEVICES += tl-wr941nd-v6-cn +diff --git a/target/linux/ar71xx/image/tiny.mk b/target/linux/ar71xx/image/tiny.mk +new file mode 100644 +index 0000000000..f89d9df83c +--- /dev/null ++++ b/target/linux/ar71xx/image/tiny.mk +@@ -0,0 +1,31 @@ ++define Build/mkbuffaloimg ++ $(STAGING_DIR_HOST)/bin/mkbuffaloimg -B $(BOARDNAME) \ ++ -R $$(($(subst k, * 1024,$(ROOTFS_SIZE)))) \ ++ -K $$(($(subst k, * 1024,$(KERNEL_SIZE)))) \ ++ -i $@ -o $@.new ++ mv $@.new $@ ++endef ++ ++ ++define Device/bhr-4grv2 ++ DEVICE_TITLE := Buffalo BHR-4GRV2 ++ BOARDNAME := BHR-4GRV2 ++ ROOTFS_SIZE := 14528k ++ KERNEL_SIZE := 1472k ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14528k(rootfs),1472k(kernel),64k(art)ro,16000k@0x50000(firmware) ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs | pad-to $$$$(ROOTFS_SIZE) | append-kernel | check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | mkbuffaloimg ++endef ++ ++define Device/zbt-we1526 ++ DEVICE_TITLE := Zbtlink ZBT-WE1526 ++ DEVICE_PACKAGES := kmod-usb2 ++ BOARDNAME := ZBT-WE1526 ++ IMAGE_SIZE := 16000k ++ KERNEL_SIZE := 1472k ++ ROOTFS_SIZE := 14528k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14528k(rootfs),1472k(kernel),64k(art)ro,16000k@0x50000(firmware) ++ IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs | pad-to $$$$(ROOTFS_SIZE) | append-kernel | check-size $$$$(IMAGE_SIZE) ++endef +diff --git a/target/linux/ar71xx/image/ubinize-nbg6716.ini b/target/linux/ar71xx/image/ubinize-nbg6716.ini +new file mode 100644 +index 0000000000..814b0fbcc8 +--- /dev/null ++++ b/target/linux/ar71xx/image/ubinize-nbg6716.ini +@@ -0,0 +1,24 @@ ++[rootfs] ++# Volume mode (other option is static) ++mode=ubi ++# Source image ++image=ubi_root.img ++# Volume ID in UBI image ++vol_id=0 ++# Allow for dynamic resize ++vol_type=dynamic ++# Volume name ++vol_name=rootfs ++ ++[rootfs_data] ++# Volume mode (other option is static) ++mode=ubi ++# Volume ID in UBI image ++vol_id=1 ++# Allow for dynamic resize ++vol_type=dynamic ++# Volume name ++vol_name=rootfs_data ++# Autoresize volume at first mount ++vol_size=1MiB ++vol_flags=autoresize +diff --git a/target/linux/ar71xx/image/ubinize-wndr4300.ini b/target/linux/ar71xx/image/ubinize-wndr4300.ini +new file mode 100644 +index 0000000000..5bff906ae8 +--- /dev/null ++++ b/target/linux/ar71xx/image/ubinize-wndr4300.ini +@@ -0,0 +1,26 @@ ++[rootfs] ++# Volume mode (other option is static) ++mode=ubi ++# Source image ++image=root.squashfs ++# Volume ID in UBI image ++vol_id=0 ++# Allow for dynamic resize ++vol_type=dynamic ++# Volume name ++vol_name=rootfs ++# Autoresize volume at first mount ++# vol_flags=autoresize ++ ++[rootfs_data] ++# Volume mode (other option is static) ++mode=ubi ++# Volume ID in UBI image ++vol_id=1 ++# Allow for dynamic resize ++vol_type=dynamic ++# Volume name ++vol_name=rootfs_data ++# Autoresize volume at first mount ++vol_flags=autoresize ++vol_size=1MiB +diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default +new file mode 100644 +index 0000000000..eb2f362034 +--- /dev/null ++++ b/target/linux/ar71xx/mikrotik/config-default +@@ -0,0 +1,79 @@ ++CONFIG_ATH79_DEV_AP9X_PCI=y ++CONFIG_ATH79_DEV_ETH=y ++CONFIG_ATH79_DEV_GPIO_BUTTONS=y ++CONFIG_ATH79_DEV_LEDS_GPIO=y ++CONFIG_ATH79_DEV_M25P80=y ++CONFIG_ATH79_DEV_NFC=y ++CONFIG_ATH79_DEV_SPI=y ++CONFIG_ATH79_DEV_USB=y ++CONFIG_ATH79_DEV_WMAC=y ++CONFIG_ATH79_MACH_RB2011=y ++CONFIG_ATH79_MACH_RB4XX=y ++CONFIG_ATH79_MACH_RB750=y ++CONFIG_ATH79_MACH_RB91X=y ++CONFIG_ATH79_MACH_RB922=y ++CONFIG_ATH79_MACH_RB95X=y ++CONFIG_ATH79_MACH_RBSPI=y ++CONFIG_ATH79_MACH_RBSXTLITE=y ++CONFIG_ATH79_PCI_ATH9K_FIXUP=y ++CONFIG_ATH79_ROUTERBOOT=y ++CONFIG_BLK_MQ_PCI=y ++CONFIG_CRC16=y ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_GPIO_LATCH=y ++CONFIG_HW_HAS_PCI=y ++# CONFIG_INTEL_XWAY_PHY is not set ++CONFIG_LEDS_RB750=y ++CONFIG_LZO_DECOMPRESS=y ++# CONFIG_MARVELL_PHY is not set ++CONFIG_MIKROTIK=y ++CONFIG_MIKROTIK_RB_SYSFS=y ++# CONFIG_MTD_CFI is not set ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CMDLINE_PARTS is not set ++# CONFIG_MTD_CYBERTAN_PARTS is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MYLOADER_PARTS is not set ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_AR934X=y ++CONFIG_MTD_NAND_ECC=y ++CONFIG_MTD_NAND_RB4XX=y ++CONFIG_MTD_NAND_RB750=y ++CONFIG_MTD_NAND_RB91X=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y ++# CONFIG_MTD_SPLIT_EVA_FW is not set ++# CONFIG_MTD_SPLIT_LZMA_FW is not set ++# CONFIG_MTD_SPLIT_SEAMA_FW is not set ++# CONFIG_MTD_SPLIT_TPLINK_FW is not set ++# CONFIG_MTD_SPLIT_UIMAGE_FW is not set ++# CONFIG_MTD_SPLIT_WRGG_FW is not set ++# CONFIG_MTD_TPLINK_PARTS is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++CONFIG_MTD_UBI_BLOCK=y ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++# CONFIG_NET_DSA is not set ++CONFIG_PCI=y ++CONFIG_PCI_AR724X=y ++CONFIG_PCI_DISABLE_COMMON_QUIRKS=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_RLE_DECOMPRESS=y ++# CONFIG_RTL8306_PHY is not set ++# CONFIG_RTL8366_SMI is not set ++CONFIG_SOC_AR71XX=y ++CONFIG_SOC_AR724X=y ++CONFIG_SOC_AR934X=y ++CONFIG_SOC_QCA953X=y ++CONFIG_SOC_QCA955X=y ++CONFIG_SPI_RB4XX=y ++CONFIG_SPI_RB4XX_CPLD=y ++CONFIG_UBIFS_FS=y ++CONFIG_UBIFS_FS_ADVANCED_COMPR=y ++# CONFIG_UBIFS_FS_LZO is not set ++CONFIG_UBIFS_FS_ZLIB=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_ZLIB_INFLATE=y +diff --git a/target/linux/ar71xx/mikrotik/profiles/00-default.mk b/target/linux/ar71xx/mikrotik/profiles/00-default.mk +new file mode 100644 +index 0000000000..1dfc62dbb3 +--- /dev/null ++++ b/target/linux/ar71xx/mikrotik/profiles/00-default.mk +@@ -0,0 +1,18 @@ ++# ++# Copyright (C) 2009 OpenWrt.org ++# ++# This is free software, licensed under the GNU General Public License v2. ++# See /LICENSE for more information. ++# ++ ++define Profile/Default ++ NAME:=Default Profile ++ PACKAGES:= \ ++ kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport nand-utils ++ PRIORITY := 1 ++endef ++ ++define Profile/Default/Description ++ Default package set compatible with most boards. ++endef ++$(eval $(call Profile,Default)) +diff --git a/target/linux/ar71xx/mikrotik/target.mk b/target/linux/ar71xx/mikrotik/target.mk +new file mode 100644 +index 0000000000..5ae57fadb3 +--- /dev/null ++++ b/target/linux/ar71xx/mikrotik/target.mk +@@ -0,0 +1,11 @@ ++BOARDNAME:=Mikrotik devices with NAND/NOR flash ++FEATURES += squashfs ramdisk minor nand ++ ++DEFAULT_PACKAGES += nand-utils wpad-basic ++ ++define Target/Description ++ Build firmware images for Atheros AR71xx/AR913x based Mikrotik boards. ++ e.g. MikroTik RB-4xx or RB-750 ++endef ++ ++ +diff --git a/target/linux/ar71xx/modules.mk b/target/linux/ar71xx/modules.mk +new file mode 100644 +index 0000000000..9ead8b451c +--- /dev/null ++++ b/target/linux/ar71xx/modules.mk +@@ -0,0 +1,69 @@ ++# ++# Copyright (C) 2006-2011 OpenWrt.org ++# ++# This is free software, licensed under the GNU General Public License v2. ++# See /LICENSE for more information. ++# ++ ++define KernelPackage/leds-nu801 ++ SUBMENU:=$(LEDS_MENU) ++ TITLE:=Meraki MR18 LED support ++ DEPENDS:=@TARGET_ar71xx ++ KCONFIG:=CONFIG_LEDS_NU801 ++ FILES:=$(LINUX_DIR)/drivers/leds/leds-nu801.ko ++ AUTOLOAD:=$(call AutoLoad,60,leds-nu801) ++endef ++ ++define KernelPackage/leds-nu801/description ++ Kernel module for the nu801 LED driver used on the Meraki MR18. ++endef ++ ++$(eval $(call KernelPackage,leds-nu801)) ++ ++ ++define KernelPackage/leds-rb750 ++ SUBMENU:=$(LEDS_MENU) ++ TITLE:=RouterBOARD 750 LED support ++ DEPENDS:=@TARGET_ar71xx ++ KCONFIG:=CONFIG_LEDS_RB750 ++ FILES:=$(LINUX_DIR)/drivers/leds/leds-rb750.ko ++ AUTOLOAD:=$(call AutoLoad,60,leds-rb750) ++endef ++ ++define KernelPackage/leds-rb750/description ++ Kernel module for the LEDs on the MikroTik RouterBOARD 750. ++endef ++ ++$(eval $(call KernelPackage,leds-rb750)) ++ ++ ++define KernelPackage/leds-wndr3700-usb ++ SUBMENU:=$(LEDS_MENU) ++ TITLE:=WNDR3700 USB LED support ++ DEPENDS:=@TARGET_ar71xx ++ KCONFIG:=CONFIG_LEDS_WNDR3700_USB ++ FILES:=$(LINUX_DIR)/drivers/leds/leds-wndr3700-usb.ko ++ AUTOLOAD:=$(call AutoLoad,60,leds-wndr3700-usb) ++endef ++ ++define KernelPackage/leds-wndr3700-usb/description ++ Kernel module for the USB LED on the NETGEAR WNDR3700 board. ++endef ++ ++$(eval $(call KernelPackage,leds-wndr3700-usb)) ++ ++ ++define KernelPackage/spi-vsc7385 ++ SUBMENU:=$(SPI_MENU) ++ TITLE:=Vitesse VSC7385 ethernet switch driver ++ DEPENDS:=@TARGET_ar71xx ++ KCONFIG:=CONFIG_SPI_VSC7385 ++ FILES:=$(LINUX_DIR)/drivers/spi/spi-vsc7385.ko ++ AUTOLOAD:=$(call AutoLoad,93,spi-vsc7385) ++endef ++ ++define KernelPackage/spi-vsc7385/description ++ This package contains the SPI driver for the Vitesse VSC7385 ethernet switch. ++endef ++ ++$(eval $(call KernelPackage,spi-vsc7385)) +diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default +new file mode 100644 +index 0000000000..39b1ca4995 +--- /dev/null ++++ b/target/linux/ar71xx/nand/config-default +@@ -0,0 +1,70 @@ ++CONFIG_ATH79_DEV_AP9X_PCI=y ++CONFIG_ATH79_DEV_ETH=y ++CONFIG_ATH79_DEV_GPIO_BUTTONS=y ++CONFIG_ATH79_DEV_LEDS_GPIO=y ++CONFIG_ATH79_DEV_M25P80=y ++CONFIG_ATH79_DEV_NFC=y ++CONFIG_ATH79_DEV_SPI=y ++CONFIG_ATH79_DEV_USB=y ++CONFIG_ATH79_DEV_WMAC=y ++CONFIG_ATH79_MACH_C60=y ++CONFIG_ATH79_MACH_DOMYWIFI_DW33D=y ++CONFIG_ATH79_MACH_HIVEAP_121=y ++CONFIG_ATH79_MACH_MR18=y ++CONFIG_ATH79_MACH_NBG6716=y ++CONFIG_ATH79_MACH_R6100=y ++CONFIG_ATH79_MACH_RAMBUTAN=y ++CONFIG_ATH79_MACH_WI2A_AC200I=y ++CONFIG_ATH79_MACH_WNDR4300=y ++CONFIG_ATH79_MACH_Z1=y ++CONFIG_ATH79_NVRAM=y ++CONFIG_ATH79_PCI_ATH9K_FIXUP=y ++CONFIG_BCH=y ++CONFIG_BLK_MQ_PCI=y ++CONFIG_CRC16=y ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_LZO=y ++CONFIG_HW_HAS_PCI=y ++# CONFIG_INTEL_XWAY_PHY is not set ++# CONFIG_IP17XX_PHY is not set ++CONFIG_LEDS_NU801=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_MTD_CFI is not set ++CONFIG_MTD_CFI_I2=y ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MYLOADER_PARTS is not set ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_AR934X=y ++CONFIG_MTD_NAND_AR934X_HW_ECC=y ++CONFIG_MTD_NAND_BCH=y ++CONFIG_MTD_NAND_ECC=y ++CONFIG_MTD_NAND_ECC_BCH=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++# CONFIG_MTD_SPLIT_EVA_FW is not set ++# CONFIG_MTD_SPLIT_SEAMA_FW is not set ++# CONFIG_MTD_SPLIT_TPLINK_FW is not set ++# CONFIG_MTD_TPLINK_PARTS is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++CONFIG_MTD_UBI_BLOCK=y ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_PCI=y ++CONFIG_PCI_AR724X=y ++CONFIG_PCI_DISABLE_COMMON_QUIRKS=y ++CONFIG_PCI_DOMAINS=y ++# CONFIG_RTL8306_PHY is not set ++# CONFIG_RTL8366_SMI is not set ++CONFIG_SOC_AR934X=y ++CONFIG_SOC_QCA955X=y ++CONFIG_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_ZLIB_INFLATE=y +diff --git a/target/linux/ar71xx/nand/profiles/00-default.mk b/target/linux/ar71xx/nand/profiles/00-default.mk +new file mode 100644 +index 0000000000..6e618113a5 +--- /dev/null ++++ b/target/linux/ar71xx/nand/profiles/00-default.mk +@@ -0,0 +1,18 @@ ++# ++# Copyright (C) 2009 OpenWrt.org ++# ++# This is free software, licensed under the GNU General Public License v2. ++# See /LICENSE for more information. ++# ++ ++define Profile/Default ++ NAME:=Default Profile ++ PACKAGES:= \ ++ kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport ++ PRIORITY := 1 ++endef ++ ++define Profile/Default/Description ++ Default package set compatible with most boards. ++endef ++$(eval $(call Profile,Default)) +diff --git a/target/linux/ar71xx/nand/target.mk b/target/linux/ar71xx/nand/target.mk +new file mode 100644 +index 0000000000..d5191b2260 +--- /dev/null ++++ b/target/linux/ar71xx/nand/target.mk +@@ -0,0 +1,9 @@ ++BOARDNAME := Generic devices with NAND flash ++FEATURES += squashfs nand rtc ++ ++DEFAULT_PACKAGES += wpad-basic ++ ++define Target/Description ++ Build firmware images for Atheros AR71xx/AR913x based boards with ++ NAND flash, e.g. Netgear WNDR4300. ++endef +diff --git a/target/linux/ar71xx/patches-4.14/001-spi-cs-gpio.patch b/target/linux/ar71xx/patches-4.14/001-spi-cs-gpio.patch +new file mode 100644 +index 0000000000..7a0b669e43 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/001-spi-cs-gpio.patch +@@ -0,0 +1,20 @@ ++--- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h +++++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h ++@@ -14,6 +14,7 @@ ++ struct ath79_spi_platform_data { ++ unsigned bus_num; ++ unsigned num_chipselect; +++ int *cs_gpios; ++ }; ++ ++ #endif /* _ATH79_SPI_PLATFORM_H */ ++--- a/drivers/spi/spi-ath79.c +++++ b/drivers/spi/spi-ath79.c ++@@ -231,6 +231,7 @@ static int ath79_spi_probe(struct platfo ++ if (pdata) { ++ master->bus_num = pdata->bus_num; ++ master->num_chipselect = pdata->num_chipselect; +++ master->cs_gpios = pdata->cs_gpios; ++ } ++ ++ sp->bitbang.master = master; +diff --git a/target/linux/ar71xx/patches-4.14/002-add_back_gpio_function_select.patch b/target/linux/ar71xx/patches-4.14/002-add_back_gpio_function_select.patch +new file mode 100644 +index 0000000000..5b26a640eb +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/002-add_back_gpio_function_select.patch +@@ -0,0 +1,92 @@ ++--- /dev/null +++++ b/arch/mips/ath79/gpio.c ++@@ -0,0 +1,59 @@ +++/* +++ * Atheros AR71XX/AR724X/AR913X GPIO API support +++ * +++ * Copyright (C) 2010-2011 Jaiganesh Narayanan +++ * Copyright (C) 2008-2011 Gabor Juhos +++ * Copyright (C) 2008 Imre Kaloz +++ * +++ * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP +++ * +++ * 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 "common.h" +++ +++void __iomem *ath79_gpio_base; +++EXPORT_SYMBOL_GPL(ath79_gpio_base); +++ +++static void __iomem *ath79_gpio_get_function_reg(void) +++{ +++ u32 reg = 0; +++ +++ if (soc_is_ar71xx() || +++ soc_is_ar724x() || +++ soc_is_ar913x() || +++ soc_is_ar933x()) +++ reg = AR71XX_GPIO_REG_FUNC; +++ else if (soc_is_ar934x()) +++ reg = AR934X_GPIO_REG_FUNC; +++ else +++ BUG(); +++ +++ return ath79_gpio_base + reg; +++} +++ +++void ath79_gpio_function_setup(u32 set, u32 clear) +++{ +++ void __iomem *reg = ath79_gpio_get_function_reg(); +++ +++ __raw_writel((__raw_readl(reg) & ~clear) | set, reg); +++ /* flush write */ +++ __raw_readl(reg); +++} +++ +++void ath79_gpio_function_enable(u32 mask) +++{ +++ ath79_gpio_function_setup(mask, 0); +++} +++ +++void ath79_gpio_function_disable(u32 mask) +++{ +++ ath79_gpio_function_setup(0, mask); +++} ++--- a/arch/mips/include/asm/mach-ath79/ath79.h +++++ b/arch/mips/include/asm/mach-ath79/ath79.h ++@@ -118,6 +118,7 @@ static inline int soc_is_qca955x(void) ++ void ath79_ddr_wb_flush(unsigned int reg); ++ void ath79_ddr_set_pci_windows(void); ++ +++extern void __iomem *ath79_gpio_base; ++ extern void __iomem *ath79_pll_base; ++ extern void __iomem *ath79_reset_base; ++ ++--- a/arch/mips/ath79/dev-common.c +++++ b/arch/mips/ath79/dev-common.c ++@@ -156,4 +156,5 @@ void __init ath79_gpio_init(void) ++ } ++ ++ platform_device_register(&ath79_gpio_device); +++ ath79_gpio_base = ioremap(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); ++ } ++--- a/arch/mips/ath79/common.h +++++ b/arch/mips/ath79/common.h ++@@ -24,6 +24,9 @@ unsigned long ath79_get_sys_clk_rate(con ++ ++ void ath79_ddr_ctrl_init(void); ++ +++void ath79_gpio_function_enable(u32 mask); +++void ath79_gpio_function_disable(u32 mask); +++void ath79_gpio_function_setup(u32 set, u32 clear); ++ void ath79_gpio_init(void); ++ ++ #endif /* __ATH79_COMMON_H */ +diff --git a/target/linux/ar71xx/patches-4.14/004-register_gpio_driver_earlier.patch b/target/linux/ar71xx/patches-4.14/004-register_gpio_driver_earlier.patch +new file mode 100644 +index 0000000000..cc30e2d91e +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/004-register_gpio_driver_earlier.patch +@@ -0,0 +1,18 @@ ++HACK: register the GPIO driver earlier to ensure that gpio_request calls ++from mach files succeed. ++ ++--- a/drivers/gpio/gpio-ath79.c +++++ b/drivers/gpio/gpio-ath79.c ++@@ -322,7 +322,11 @@ static struct platform_driver ath79_gpio ++ .remove = ath79_gpio_remove, ++ }; ++ ++-module_platform_driver(ath79_gpio_driver); +++static int __init ath79_gpio_init(void) +++{ +++ return platform_driver_register(&ath79_gpio_driver); +++} +++postcore_initcall(ath79_gpio_init); ++ ++ MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support"); ++ MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/ar71xx/patches-4.14/100-MIPS-ath79-Avoid-using-unitialized-reg-variable.patch b/target/linux/ar71xx/patches-4.14/100-MIPS-ath79-Avoid-using-unitialized-reg-variable.patch +new file mode 100644 +index 0000000000..8d5b089986 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/100-MIPS-ath79-Avoid-using-unitialized-reg-variable.patch +@@ -0,0 +1,42 @@ ++From 8b7a76e72fc819753878cd5684e243f33f847c79 Mon Sep 17 00:00:00 2001 ++From: Markos Chandras ++Date: Wed, 21 Aug 2013 11:47:22 +0100 ++Subject: [PATCH] MIPS: ath79: Avoid using unitialized 'reg' variable ++ ++Fixes the following build error: ++arch/mips/include/asm/mach-ath79/ath79.h:139:20: error: 'reg' may be used ++uninitialized in this function [-Werror=maybe-uninitialized] ++arch/mips/ath79/common.c:62:6: note: 'reg' was declared here ++In file included from arch/mips/ath79/common.c:20:0: ++arch/mips/ath79/common.c: In function 'ath79_device_reset_clear': ++arch/mips/include/asm/mach-ath79/ath79.h:139:20: ++error: 'reg' may be used uninitialized in this function ++[-Werror=maybe-uninitialized] ++arch/mips/ath79/common.c:90:6: note: 'reg' was declared here ++ ++Signed-off-by: Markos Chandras ++Acked-by: Gabor Juhos ++--- ++ arch/mips/ath79/common.c | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++--- a/arch/mips/ath79/common.c +++++ b/arch/mips/ath79/common.c ++@@ -106,7 +106,7 @@ void ath79_device_reset_set(u32 mask) ++ else if (soc_is_qca955x()) ++ reg = QCA955X_RESET_REG_RESET_MODULE; ++ else ++- BUG(); +++ panic("Reset register not defined for this SOC"); ++ ++ spin_lock_irqsave(&ath79_device_reset_lock, flags); ++ t = ath79_reset_rr(reg); ++@@ -134,7 +134,7 @@ void ath79_device_reset_clear(u32 mask) ++ else if (soc_is_qca955x()) ++ reg = QCA955X_RESET_REG_RESET_MODULE; ++ else ++- BUG(); +++ panic("Reset register not defined for this SOC"); ++ ++ spin_lock_irqsave(&ath79_device_reset_lock, flags); ++ t = ath79_reset_rr(reg); +diff --git a/target/linux/ar71xx/patches-4.14/106-02-MIPS-ath79-do-AR724x-PCIe-root-complex-init.patch b/target/linux/ar71xx/patches-4.14/106-02-MIPS-ath79-do-AR724x-PCIe-root-complex-init.patch +new file mode 100644 +index 0000000000..3af99bf3b5 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/106-02-MIPS-ath79-do-AR724x-PCIe-root-complex-init.patch +@@ -0,0 +1,113 @@ ++From 460f382c278fe66059a773c41cbcd0db86d53983 Mon Sep 17 00:00:00 2001 ++From: Mathias Kresin ++Date: Thu, 13 Apr 2017 09:47:42 +0200 ++Subject: [PATCH] MIPS: pci-ar724x: get PCIe controller out of reset ++ ++The ar724x pci driver expects the PCIe controller to be brought out of ++reset by the bootloader. ++ ++At least the AVM Fritz 300E bootloader doesn't take care of releasing ++the different PCIe controller related resets which causes an endless ++hang as soon as either the PCIE Reset register (0x180f0018) or the PCI ++Application Control register (0x180f0000) is read from. ++ ++Do the full "PCIE Root Complex Initialization Sequence" if the PCIe ++host controller is still in reset during probing. ++ ++The QCA u-boot sleeps 10ms after the PCIE Application Control bit is ++set to ready. It has been shown that 10ms might not be enough time if ++PCIe should be used right after setting the bit. During my tests it ++took up to 20ms till the link was up. Giving the link up to 100ms ++should work for all cases. ++ ++Signed-off-by: Mathias Kresin ++--- ++ arch/mips/include/asm/mach-ath79/ar71xx_regs.h | 3 ++ ++ arch/mips/pci/pci-ar724x.c | 42 ++++++++++++++++++++++++++ ++ 2 files changed, 45 insertions(+) ++ ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -169,6 +169,9 @@ ++ #define AR724X_PLL_REG_CPU_CONFIG 0x00 ++ #define AR724X_PLL_REG_PCIE_CONFIG 0x10 ++ +++#define AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS BIT(16) +++#define AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET BIT(25) +++ ++ #define AR724X_PLL_FB_SHIFT 0 ++ #define AR724X_PLL_FB_MASK 0x3ff ++ #define AR724X_PLL_REF_DIV_SHIFT 10 ++--- a/arch/mips/pci/pci-ar724x.c +++++ b/arch/mips/pci/pci-ar724x.c ++@@ -12,14 +12,18 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++ +++#define AR724X_PCI_REG_APP 0x0 ++ #define AR724X_PCI_REG_RESET 0x18 ++ #define AR724X_PCI_REG_INT_STATUS 0x4c ++ #define AR724X_PCI_REG_INT_MASK 0x50 ++ +++#define AR724X_PCI_APP_LTSSM_ENABLE BIT(0) +++ ++ #define AR724X_PCI_RESET_LINK_UP BIT(0) ++ ++ #define AR724X_PCI_INT_DEV0 BIT(14) ++@@ -325,6 +329,37 @@ static void ar724x_pci_irq_init(struct a ++ apc); ++ } ++ +++static void ar724x_pci_hw_init(struct ar724x_pci_controller *apc) +++{ +++ u32 ppl, app; +++ int wait = 0; +++ +++ /* deassert PCIe host controller and PCIe PHY reset */ +++ ath79_device_reset_clear(AR724X_RESET_PCIE); +++ ath79_device_reset_clear(AR724X_RESET_PCIE_PHY); +++ +++ /* remove the reset of the PCIE PLL */ +++ ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); +++ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; +++ ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); +++ +++ /* deassert bypass for the PCIE PLL */ +++ ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); +++ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; +++ ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); +++ +++ /* set PCIE Application Control to ready */ +++ app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP); +++ app |= AR724X_PCI_APP_LTSSM_ENABLE; +++ __raw_writel(app, apc->ctrl_base + AR724X_PCI_REG_APP); +++ +++ /* wait up to 100ms for PHY link up */ +++ do { +++ mdelay(10); +++ wait++; +++ } while (wait < 10 && !ar724x_pci_check_link(apc)); +++} +++ ++ static int ar724x_pci_probe(struct platform_device *pdev) ++ { ++ struct ar724x_pci_controller *apc; ++@@ -383,6 +418,13 @@ static int ar724x_pci_probe(struct platf ++ apc->pci_controller.io_resource = &apc->io_res; ++ apc->pci_controller.mem_resource = &apc->mem_res; ++ +++ /* +++ * Do the full PCIE Root Complex Initialization Sequence if the PCIe +++ * host controller is in reset. +++ */ +++ if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE) +++ ar724x_pci_hw_init(apc); +++ ++ apc->link_up = ar724x_pci_check_link(apc); ++ if (!apc->link_up) ++ dev_warn(&pdev->dev, "PCIe link is down\n"); +diff --git a/target/linux/ar71xx/patches-4.14/200-MIPS-ath79-fix-ar933x-wmac-reset.patch b/target/linux/ar71xx/patches-4.14/200-MIPS-ath79-fix-ar933x-wmac-reset.patch +new file mode 100644 +index 0000000000..b7ae0ce649 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/200-MIPS-ath79-fix-ar933x-wmac-reset.patch +@@ -0,0 +1,30 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -62,10 +62,26 @@ static void __init ar913x_wmac_setup(voi ++ ++ static int ar933x_wmac_reset(void) ++ { +++ int retries = 20; +++ ++ ath79_device_reset_set(AR933X_RESET_WMAC); ++ ath79_device_reset_clear(AR933X_RESET_WMAC); ++ ++- return 0; +++ 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 ar933x_r1_get_wmac_revision(void) +diff --git a/target/linux/ar71xx/patches-4.14/201-ar913x_wmac_external_reset.patch b/target/linux/ar71xx/patches-4.14/201-ar913x_wmac_external_reset.patch +new file mode 100644 +index 0000000000..9b704a3c47 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/201-ar913x_wmac_external_reset.patch +@@ -0,0 +1,31 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -44,7 +44,7 @@ static struct platform_device ath79_wmac ++ }, ++ }; ++ ++-static void __init ar913x_wmac_setup(void) +++static int ar913x_wmac_reset(void) ++ { ++ /* reset the WMAC */ ++ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); ++@@ -53,10 +53,19 @@ static void __init ar913x_wmac_setup(voi ++ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); ++ mdelay(10); ++ +++ return 0; +++} +++ +++static void __init ar913x_wmac_setup(void) +++{ +++ ar913x_wmac_reset(); +++ ++ ath79_wmac_resources[0].start = AR913X_WMAC_BASE; ++ ath79_wmac_resources[0].end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1; ++ ath79_wmac_resources[1].start = ATH79_CPU_IRQ(2); ++ ath79_wmac_resources[1].end = ATH79_CPU_IRQ(2); +++ +++ ath79_wmac_data.external_reset = ar913x_wmac_reset; ++ } ++ ++ +diff --git a/target/linux/ar71xx/patches-4.14/202-MIPS-ath79-ar934x-wmac-revision.patch b/target/linux/ar71xx/patches-4.14/202-MIPS-ath79-ar934x-wmac-revision.patch +new file mode 100644 +index 0000000000..0f8016f847 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/202-MIPS-ath79-ar934x-wmac-revision.patch +@@ -0,0 +1,11 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -139,6 +139,8 @@ static void ar934x_wmac_setup(void) ++ ath79_wmac_data.is_clk_25mhz = false; ++ else ++ ath79_wmac_data.is_clk_25mhz = true; +++ +++ ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; ++ } ++ ++ static void qca955x_wmac_setup(void) +diff --git a/target/linux/ar71xx/patches-4.14/220-add_cpu_feature_overrides.patch b/target/linux/ar71xx/patches-4.14/220-add_cpu_feature_overrides.patch +new file mode 100644 +index 0000000000..d925f92624 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/220-add_cpu_feature_overrides.patch +@@ -0,0 +1,28 @@ ++--- a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h +++++ b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h ++@@ -36,6 +36,7 @@ ++ #define cpu_has_mdmx 0 ++ #define cpu_has_mips3d 0 ++ #define cpu_has_smartmips 0 +++#define cpu_has_rixi 0 ++ ++ #define cpu_has_mips32r1 1 ++ #define cpu_has_mips32r2 1 ++@@ -43,6 +44,7 @@ ++ #define cpu_has_mips64r2 0 ++ ++ #define cpu_has_mipsmt 0 +++#define cpu_has_userlocal 0 ++ ++ #define cpu_has_64bits 0 ++ #define cpu_has_64bit_zero_reg 0 ++@@ -51,5 +53,9 @@ ++ ++ #define cpu_dcache_line_size() 32 ++ #define cpu_icache_line_size() 32 +++#define cpu_has_vtag_icache 0 +++#define cpu_has_dc_aliases 1 +++#define cpu_has_ic_fills_f_dc 0 +++#define cpu_has_pindexed_dcache 0 ++ ++ #endif /* __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H */ +diff --git a/target/linux/ar71xx/patches-4.14/300-MIPS-add-MIPS_MACHINE_NONAME-macro.patch b/target/linux/ar71xx/patches-4.14/300-MIPS-add-MIPS_MACHINE_NONAME-macro.patch +new file mode 100644 +index 0000000000..0bc64b7a17 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/300-MIPS-add-MIPS_MACHINE_NONAME-macro.patch +@@ -0,0 +1,21 @@ ++--- a/arch/mips/include/asm/mips_machine.h +++++ b/arch/mips/include/asm/mips_machine.h ++@@ -36,6 +36,18 @@ static struct mips_machine machine_##_ty ++ .mach_setup = _setup, \ ++ }; ++ +++#define MIPS_MACHINE_NONAME(_type, _id, _setup) \ +++static const char machine_id_##_type[] __initconst \ +++ __aligned(1) = _id; \ +++static struct mips_machine machine_##_type \ +++ __used __section(.mips.machines.init) = \ +++{ \ +++ .mach_type = _type, \ +++ .mach_id = machine_id_##_type, \ +++ .mach_name = NULL, \ +++ .mach_setup = _setup, \ +++}; +++ ++ extern long __mips_machines_start; ++ extern long __mips_machines_end; ++ +diff --git a/target/linux/ar71xx/patches-4.14/310-lib-add-rle-decompression.patch b/target/linux/ar71xx/patches-4.14/310-lib-add-rle-decompression.patch +new file mode 100644 +index 0000000000..727f4d8343 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/310-lib-add-rle-decompression.patch +@@ -0,0 +1,124 @@ ++--- a/lib/Kconfig +++++ b/lib/Kconfig ++@@ -265,6 +265,9 @@ config LZMA_COMPRESS ++ config LZMA_DECOMPRESS ++ tristate ++ +++config RLE_DECOMPRESS +++ tristate +++ ++ # ++ # These all provide a common interface (hence the apparent duplication with ++ # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) ++--- a/lib/Makefile +++++ b/lib/Makefile ++@@ -146,6 +146,7 @@ obj-$(CONFIG_XZ_DEC) += xz/ ++ obj-$(CONFIG_RAID6_PQ) += raid6/ ++ obj-$(CONFIG_LZMA_COMPRESS) += lzma/ ++ obj-$(CONFIG_LZMA_DECOMPRESS) += lzma/ +++obj-$(CONFIG_RLE_DECOMPRESS) += rle.o ++ ++ lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o ++ lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o ++--- /dev/null +++++ b/include/linux/rle.h ++@@ -0,0 +1,18 @@ +++#ifndef _RLE_H_ +++#define _RLE_H_ +++ +++#ifdef CONFIG_RLE_DECOMPRESS +++int rle_decode(const unsigned char *src, size_t srclen, +++ unsigned char *dst, size_t dstlen, +++ size_t *src_done, size_t *dst_done); +++#else +++static inline int +++rle_decode(const unsigned char *src, size_t srclen, +++ unsigned char *dst, size_t dstlen, +++ size_t *src_done, size_t *dst_done) +++{ +++ return -ENOTSUPP; +++} +++#endif /* CONFIG_RLE_DECOMPRESS */ +++ +++#endif /* _RLE_H_ */ ++--- /dev/null +++++ b/lib/rle.c ++@@ -0,0 +1,78 @@ +++/* +++ * RLE decoding routine +++ * +++ * Copyright (C) 2012 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. +++ */ +++ +++#include +++#include +++#include +++ +++int rle_decode(const unsigned char *src, size_t srclen, +++ unsigned char *dst, size_t dstlen, +++ size_t *src_done, size_t *dst_done) +++{ +++ size_t srcpos, dstpos; +++ int ret; +++ +++ srcpos = 0; +++ dstpos = 0; +++ ret = -EINVAL; +++ +++ /* sanity checks */ +++ if (!src || !srclen || !dst || !dstlen) +++ goto out; +++ +++ while (1) { +++ char count; +++ +++ if (srcpos >= srclen) +++ break; +++ +++ count = (char) src[srcpos++]; +++ if (count == 0) { +++ ret = 0; +++ break; +++ } +++ +++ if (count > 0) { +++ unsigned char c; +++ +++ if (srcpos >= srclen) +++ break; +++ +++ c = src[srcpos++]; +++ +++ while (count--) { +++ if (dstpos >= dstlen) +++ break; +++ +++ dst[dstpos++] = c; +++ } +++ } else { +++ count *= -1; +++ +++ while (count--) { +++ if (srcpos >= srclen) +++ break; +++ if (dstpos >= dstlen) +++ break; +++ dst[dstpos++] = src[srcpos++]; +++ } +++ } +++ } +++ +++out: +++ if (src_done) +++ *src_done = srcpos; +++ if (dst_done) +++ *dst_done = dstpos; +++ +++ return ret; +++} +++ +++EXPORT_SYMBOL_GPL(rle_decode); +diff --git a/target/linux/ar71xx/patches-4.14/343-MIPS-ath79-Fix-potentially-missed-IRQ-handling-durin.patch b/target/linux/ar71xx/patches-4.14/343-MIPS-ath79-Fix-potentially-missed-IRQ-handling-durin.patch +new file mode 100644 +index 0000000000..05a1d7ef0c +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/343-MIPS-ath79-Fix-potentially-missed-IRQ-handling-durin.patch +@@ -0,0 +1,52 @@ ++From 3fe7841bf5a582dc7fd198e5bf70162ea418a22a Mon Sep 17 00:00:00 2001 ++From: Koen Vandeputte ++Date: Wed, 11 Sep 2019 11:02:19 +0200 ++Subject: [PATCH] MIPS: ath79: Fix potentially missed IRQ handling during ++ dispatch ++ ++If both interrupts are set in the current implementation ++only the 1st will be handled and the 2nd will be skipped ++due to the "if else" condition. ++ ++Fix this by using the same approach as done for QCA955x ++just below it. ++ ++Fixes: fce5cc6e0ddc ("MIPS: ath79: add IRQ handling code for AR934X") ++Signed-off-by: Koen Vandeputte ++CC: Felix Fietkau ++CC: Gabor Juhos ++CC: James Hogan ++CC: Paul Burton ++CC: Ralf Baechle ++CC: stable@vger.kernel.org # v3.2+ ++--- ++ arch/mips/ath79/irq.c | 12 +++++++++--- ++ 1 file changed, 9 insertions(+), 3 deletions(-) ++ ++--- a/arch/mips/ath79/irq.c +++++ b/arch/mips/ath79/irq.c ++@@ -32,15 +32,21 @@ static void ar934x_ip2_irq_dispatch(stru ++ u32 status; ++ ++ status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS); +++ status &= AR934X_PCIE_WMAC_INT_PCIE_ALL | AR934X_PCIE_WMAC_INT_WMAC_ALL; +++ +++ if (status == 0) { +++ spurious_interrupt(); +++ return; +++ } ++ ++ if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) { ++ ath79_ddr_wb_flush(3); ++ generic_handle_irq(ATH79_IP2_IRQ(0)); ++- } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) { +++ } +++ +++ if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) { ++ ath79_ddr_wb_flush(4); ++ generic_handle_irq(ATH79_IP2_IRQ(1)); ++- } else { ++- spurious_interrupt(); ++ } ++ } ++ +diff --git a/target/linux/ar71xx/patches-4.14/401-mtd-physmap-add-lock-unlock.patch b/target/linux/ar71xx/patches-4.14/401-mtd-physmap-add-lock-unlock.patch +new file mode 100644 +index 0000000000..db7b3ca83d +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/401-mtd-physmap-add-lock-unlock.patch +@@ -0,0 +1,94 @@ ++--- a/drivers/mtd/maps/physmap.c +++++ b/drivers/mtd/maps/physmap.c ++@@ -31,6 +31,66 @@ struct physmap_flash_info { ++ int vpp_refcnt; ++ }; ++ +++static struct platform_device *physmap_map2pdev(struct map_info *map) +++{ +++ return (struct platform_device *) map->map_priv_1; +++} +++ +++static void physmap_lock(struct map_info *map) +++{ +++ struct platform_device *pdev; +++ struct physmap_flash_data *physmap_data; +++ +++ pdev = physmap_map2pdev(map); +++ physmap_data = pdev->dev.platform_data; +++ physmap_data->lock(pdev); +++} +++ +++static void physmap_unlock(struct map_info *map) +++{ +++ struct platform_device *pdev; +++ struct physmap_flash_data *physmap_data; +++ +++ pdev = physmap_map2pdev(map); +++ physmap_data = pdev->dev.platform_data; +++ physmap_data->unlock(pdev); +++} +++ +++static map_word physmap_flash_read_lock(struct map_info *map, unsigned long ofs) +++{ +++ map_word ret; +++ +++ physmap_lock(map); +++ ret = inline_map_read(map, ofs); +++ physmap_unlock(map); +++ +++ return ret; +++} +++ +++static void physmap_flash_write_lock(struct map_info *map, map_word d, +++ unsigned long ofs) +++{ +++ physmap_lock(map); +++ inline_map_write(map, d, ofs); +++ physmap_unlock(map); +++} +++ +++static void physmap_flash_copy_from_lock(struct map_info *map, void *to, +++ unsigned long from, ssize_t len) +++{ +++ physmap_lock(map); +++ inline_map_copy_from(map, to, from, len); +++ physmap_unlock(map); +++} +++ +++static void physmap_flash_copy_to_lock(struct map_info *map, unsigned long to, +++ const void *from, ssize_t len) +++{ +++ physmap_lock(map); +++ inline_map_copy_to(map, to, from, len); +++ physmap_unlock(map); +++} +++ ++ static int physmap_flash_remove(struct platform_device *dev) ++ { ++ struct physmap_flash_info *info; ++@@ -153,6 +213,13 @@ static int physmap_flash_probe(struct pl ++ ++ simple_map_init(&info->map[i]); ++ +++ if (physmap_data->lock && physmap_data->unlock) { +++ info->map[i].read = physmap_flash_read_lock; +++ info->map[i].write = physmap_flash_write_lock; +++ info->map[i].copy_from = physmap_flash_copy_from_lock; +++ info->map[i].copy_to = physmap_flash_copy_to_lock; +++ } +++ ++ probe_type = rom_probe_types; ++ if (physmap_data->probe_type == NULL) { ++ for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++) ++--- a/include/linux/mtd/physmap.h +++++ b/include/linux/mtd/physmap.h ++@@ -25,6 +25,8 @@ struct physmap_flash_data { ++ unsigned int width; ++ int (*init)(struct platform_device *); ++ void (*exit)(struct platform_device *); +++ void (*lock)(struct platform_device *); +++ void (*unlock)(struct platform_device *); ++ void (*set_vpp)(struct platform_device *, int); ++ unsigned int nr_parts; ++ unsigned int pfow_base; +diff --git a/target/linux/ar71xx/patches-4.14/402-mtd-SST39VF6401B-support.patch b/target/linux/ar71xx/patches-4.14/402-mtd-SST39VF6401B-support.patch +new file mode 100644 +index 0000000000..0d483ab1a4 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/402-mtd-SST39VF6401B-support.patch +@@ -0,0 +1,29 @@ ++--- a/drivers/mtd/chips/jedec_probe.c +++++ b/drivers/mtd/chips/jedec_probe.c ++@@ -148,6 +148,7 @@ ++ #define SST39LF160 0x2782 ++ #define SST39VF1601 0x234b ++ #define SST39VF3201 0x235b +++#define SST39VF6401B 0x236d ++ #define SST39WF1601 0x274b ++ #define SST39WF1602 0x274a ++ #define SST39LF512 0x00D4 ++@@ -1569,6 +1570,18 @@ static const struct amd_flash_info jedec ++ ERASEINFO(0x10000,64), ++ } ++ }, { +++ .mfr_id = CFI_MFR_SST, +++ .dev_id = SST39VF6401B, +++ .name = "SST 39VF6401B", +++ .devtypes = CFI_DEVICETYPE_X16, +++ .uaddr = MTD_UADDR_0xAAAA_0x5555, +++ .dev_size = SIZE_8MiB, +++ .cmd_set = P_ID_AMD_STD, +++ .nr_regions = 1, +++ .regions = { +++ ERASEINFO(0x10000,128) +++ } +++ }, { ++ .mfr_id = CFI_MFR_ST, ++ .dev_id = M29F800AB, ++ .name = "ST M29F800AB", +diff --git a/target/linux/ar71xx/patches-4.14/404-mtd-cybertan-trx-parser.patch b/target/linux/ar71xx/patches-4.14/404-mtd-cybertan-trx-parser.patch +new file mode 100644 +index 0000000000..4b59abe16b +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/404-mtd-cybertan-trx-parser.patch +@@ -0,0 +1,25 @@ ++--- a/drivers/mtd/Kconfig +++++ b/drivers/mtd/Kconfig ++@@ -178,6 +178,12 @@ menu "Partition parsers" ++ source "drivers/mtd/parsers/Kconfig" ++ endmenu ++ +++config MTD_CYBERTAN_PARTS +++ tristate "Cybertan partitioning support" +++ depends on ATH79 +++ ---help--- +++ Cybertan partitioning support +++ ++ config MTD_MYLOADER_PARTS ++ tristate "MyLoader partition parsing" ++ depends on ADM5120 || ATH25 || ATH79 ++--- a/drivers/mtd/Makefile +++++ b/drivers/mtd/Makefile ++@@ -18,6 +18,7 @@ obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63 ++ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o ++ obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o ++ obj-y += parsers/ +++obj-$(CONFIG_MTD_CYBERTAN_PARTS) += cybertan_part.o ++ ++ # 'Users' - code which presents functionality to userspace. ++ obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o +diff --git a/target/linux/ar71xx/patches-4.14/405-mtd-tp-link-partition-parser.patch b/target/linux/ar71xx/patches-4.14/405-mtd-tp-link-partition-parser.patch +new file mode 100644 +index 0000000000..899ab893f0 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/405-mtd-tp-link-partition-parser.patch +@@ -0,0 +1,25 @@ ++--- a/drivers/mtd/Kconfig +++++ b/drivers/mtd/Kconfig ++@@ -200,6 +200,12 @@ config MTD_MYLOADER_PARTS ++ You will still need the parsing functions to be called by the driver ++ for your particular device. It won't happen automatically. ++ +++config MTD_TPLINK_PARTS +++ tristate "TP-Link AR7XXX/AR9XXX partitioning support" +++ depends on ATH79 +++ ---help--- +++ TBD. +++ ++ comment "User Modules And Translation Layers" ++ ++ # ++--- a/drivers/mtd/Makefile +++++ b/drivers/mtd/Makefile ++@@ -18,6 +18,7 @@ obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63 ++ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o ++ obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o ++ obj-y += parsers/ +++obj-$(CONFIG_MTD_TPLINK_PARTS) += tplinkpart.o ++ obj-$(CONFIG_MTD_CYBERTAN_PARTS) += cybertan_part.o ++ ++ # 'Users' - code which presents functionality to userspace. +diff --git a/target/linux/ar71xx/patches-4.14/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch b/target/linux/ar71xx/patches-4.14/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch +new file mode 100644 +index 0000000000..13999064cb +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch +@@ -0,0 +1,34 @@ ++--- a/drivers/mtd/devices/m25p80.c +++++ b/drivers/mtd/devices/m25p80.c ++@@ -235,6 +235,7 @@ static ssize_t m25p80_read(struct spi_no ++ */ ++ static int m25p_probe(struct spi_device *spi) ++ { +++ struct mtd_part_parser_data ppdata = {0,}; ++ struct flash_platform_data *data; ++ struct m25p *flash; ++ struct spi_nor *nor; ++@@ -300,8 +301,11 @@ static int m25p_probe(struct spi_device ++ if (ret) ++ return ret; ++ ++- return mtd_device_register(&nor->mtd, data ? data->parts : NULL, ++- data ? data->nr_parts : 0); +++ return mtd_device_parse_register(&nor->mtd, +++ data ? data->part_probes : NULL, +++ &ppdata, +++ data ? data->parts : NULL, +++ data ? data->nr_parts : 0); ++ } ++ ++ ++--- a/include/linux/spi/flash.h +++++ b/include/linux/spi/flash.h ++@@ -25,6 +25,7 @@ struct flash_platform_data { ++ unsigned int nr_parts; ++ ++ char *type; +++ const char **part_probes; ++ ++ /* we'll likely add more ... use JEDEC IDs, etc */ ++ }; +diff --git a/target/linux/ar71xx/patches-4.14/408-mtd-redboot_partition_scan.patch b/target/linux/ar71xx/patches-4.14/408-mtd-redboot_partition_scan.patch +new file mode 100644 +index 0000000000..cd41e7ceb2 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/408-mtd-redboot_partition_scan.patch +@@ -0,0 +1,44 @@ ++--- a/drivers/mtd/redboot.c +++++ b/drivers/mtd/redboot.c ++@@ -76,12 +76,18 @@ static int parse_redboot_partitions(stru ++ static char nullstring[] = "unallocated"; ++ #endif ++ +++ buf = vmalloc(master->erasesize); +++ if (!buf) +++ return -ENOMEM; +++ +++ restart: ++ if ( directory < 0 ) { ++ offset = master->size + directory * master->erasesize; ++ while (mtd_block_isbad(master, offset)) { ++ if (!offset) { ++ nogood: ++ printk(KERN_NOTICE "Failed to find a non-bad block to check for RedBoot partition table\n"); +++ vfree(buf); ++ return -EIO; ++ } ++ offset -= master->erasesize; ++@@ -94,10 +100,6 @@ static int parse_redboot_partitions(stru ++ goto nogood; ++ } ++ } ++- buf = vmalloc(master->erasesize); ++- ++- if (!buf) ++- return -ENOMEM; ++ ++ printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n", ++ master->name, offset); ++@@ -170,6 +172,11 @@ static int parse_redboot_partitions(stru ++ } ++ if (i == numslots) { ++ /* Didn't find it */ +++ if (offset + master->erasesize < master->size) { +++ /* not at the end of the flash yet, maybe next block :) */ +++ directory++; +++ goto restart; +++ } ++ printk(KERN_NOTICE "No RedBoot partition table detected in %s\n", ++ master->name); ++ ret = 0; +diff --git a/target/linux/ar71xx/patches-4.14/409-mtd-rb4xx_nand_driver.patch b/target/linux/ar71xx/patches-4.14/409-mtd-rb4xx_nand_driver.patch +new file mode 100644 +index 0000000000..c4b26ecb72 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/409-mtd-rb4xx_nand_driver.patch +@@ -0,0 +1,21 @@ ++--- a/drivers/mtd/nand/Kconfig +++++ b/drivers/mtd/nand/Kconfig ++@@ -563,4 +563,8 @@ config MTD_NAND_MTK ++ Enables support for NAND controller on MTK SoCs. ++ This controller is found on mt27xx, mt81xx, mt65xx SoCs. ++ +++config MTD_NAND_RB4XX +++ tristate "NAND flash driver for RouterBoard 4xx series" +++ depends on MTD_NAND && ATH79_MACH_RB4XX +++ ++ endif # MTD_NAND ++--- a/drivers/mtd/nand/Makefile +++++ b/drivers/mtd/nand/Makefile ++@@ -34,6 +34,7 @@ obj-$(CONFIG_MTD_NAND_CM_X270) += cmx27 ++ obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o ++ obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o ++ obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o +++obj-$(CONFIG_MTD_NAND_RB4XX) += rb4xx_nand.o ++ obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o ++ obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o ++ obj-$(CONFIG_MTD_NAND_OXNAS) += oxnas_nand.o +diff --git a/target/linux/ar71xx/patches-4.14/410-mtd-rb750-nand-driver.patch b/target/linux/ar71xx/patches-4.14/410-mtd-rb750-nand-driver.patch +new file mode 100644 +index 0000000000..08960f4358 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/410-mtd-rb750-nand-driver.patch +@@ -0,0 +1,21 @@ ++--- a/drivers/mtd/nand/Kconfig +++++ b/drivers/mtd/nand/Kconfig ++@@ -567,4 +567,8 @@ config MTD_NAND_RB4XX ++ tristate "NAND flash driver for RouterBoard 4xx series" ++ depends on MTD_NAND && ATH79_MACH_RB4XX ++ +++config MTD_NAND_RB750 +++ tristate "NAND flash driver for the RouterBoard 750" +++ depends on MTD_NAND && ATH79_MACH_RB750 +++ ++ endif # MTD_NAND ++--- a/drivers/mtd/nand/Makefile +++++ b/drivers/mtd/nand/Makefile ++@@ -35,6 +35,7 @@ obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx ++ obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o ++ obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o ++ obj-$(CONFIG_MTD_NAND_RB4XX) += rb4xx_nand.o +++obj-$(CONFIG_MTD_NAND_RB750) += rb750_nand.o ++ obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o ++ obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o ++ obj-$(CONFIG_MTD_NAND_OXNAS) += oxnas_nand.o +diff --git a/target/linux/ar71xx/patches-4.14/411-mtd-cfi_cmdset_0002-force-word-write.patch b/target/linux/ar71xx/patches-4.14/411-mtd-cfi_cmdset_0002-force-word-write.patch +new file mode 100644 +index 0000000000..5a5320968f +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/411-mtd-cfi_cmdset_0002-force-word-write.patch +@@ -0,0 +1,61 @@ ++--- a/drivers/mtd/chips/cfi_cmdset_0002.c +++++ b/drivers/mtd/chips/cfi_cmdset_0002.c ++@@ -40,7 +40,7 @@ ++ #include ++ ++ #define AMD_BOOTLOC_BUG ++-#define FORCE_WORD_WRITE 0 +++#define FORCE_WORD_WRITE 1 ++ ++ #define MAX_RETRIES 3 ++ ++@@ -51,7 +51,9 @@ ++ ++ static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); ++ static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +++#if !FORCE_WORD_WRITE ++ static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +++#endif ++ static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); ++ static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); ++ static void cfi_amdstd_sync (struct mtd_info *); ++@@ -202,6 +204,7 @@ static void fixup_amd_bootblock(struct m ++ } ++ #endif ++ +++#if !FORCE_WORD_WRITE ++ static void fixup_use_write_buffers(struct mtd_info *mtd) ++ { ++ struct map_info *map = mtd->priv; ++@@ -211,6 +214,7 @@ static void fixup_use_write_buffers(stru ++ mtd->_write = cfi_amdstd_write_buffers; ++ } ++ } +++#endif /* !FORCE_WORD_WRITE */ ++ ++ /* Atmel chips don't use the same PRI format as AMD chips */ ++ static void fixup_convert_atmel_pri(struct mtd_info *mtd) ++@@ -1798,6 +1802,7 @@ static int cfi_amdstd_write_words(struct ++ /* ++ * FIXME: interleaved mode not tested, and probably not supported! ++ */ +++#if !FORCE_WORD_WRITE ++ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, ++ unsigned long adr, const u_char *buf, ++ int len) ++@@ -1930,7 +1935,6 @@ static int __xipram do_write_buffer(stru ++ return ret; ++ } ++ ++- ++ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, const u_char *buf) ++ { ++@@ -2005,6 +2009,7 @@ static int cfi_amdstd_write_buffers(stru ++ ++ return 0; ++ } +++#endif /* !FORCE_WORD_WRITE */ ++ ++ /* ++ * Wait for the flash chip to become ready to write data +diff --git a/target/linux/ar71xx/patches-4.14/413-mtd-ar934x-nand-driver.patch b/target/linux/ar71xx/patches-4.14/413-mtd-ar934x-nand-driver.patch +new file mode 100644 +index 0000000000..a2f34f6776 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/413-mtd-ar934x-nand-driver.patch +@@ -0,0 +1,25 @@ ++--- a/drivers/mtd/nand/Kconfig +++++ b/drivers/mtd/nand/Kconfig ++@@ -571,4 +571,12 @@ config MTD_NAND_RB750 ++ tristate "NAND flash driver for the RouterBoard 750" ++ depends on MTD_NAND && ATH79_MACH_RB750 ++ +++config MTD_NAND_AR934X +++ tristate "NAND flash driver for the Qualcomm Atheros AR934x/QCA955x SoCs" +++ depends on (SOC_AR934X || SOC_QCA955X) +++ +++config MTD_NAND_AR934X_HW_ECC +++ bool "Hardware ECC support for the AR934X NAND Controller (EXPERIMENTAL)" +++ depends on MTD_NAND_AR934X +++ ++ endif # MTD_NAND ++--- a/drivers/mtd/nand/Makefile +++++ b/drivers/mtd/nand/Makefile ++@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams- ++ obj-$(CONFIG_MTD_NAND_DENALI) += denali.o ++ obj-$(CONFIG_MTD_NAND_DENALI_PCI) += denali_pci.o ++ obj-$(CONFIG_MTD_NAND_DENALI_DT) += denali_dt.o +++obj-$(CONFIG_MTD_NAND_AR934X) += ar934x_nfc.o ++ obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o ++ obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o ++ obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o +diff --git a/target/linux/ar71xx/patches-4.14/414-mtd-rb91x-nand-driver.patch b/target/linux/ar71xx/patches-4.14/414-mtd-rb91x-nand-driver.patch +new file mode 100644 +index 0000000000..f9784a2d13 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/414-mtd-rb91x-nand-driver.patch +@@ -0,0 +1,23 @@ ++--- a/drivers/mtd/nand/Kconfig +++++ b/drivers/mtd/nand/Kconfig ++@@ -571,6 +571,10 @@ config MTD_NAND_RB750 ++ tristate "NAND flash driver for the RouterBoard 750" ++ depends on MTD_NAND && ATH79_MACH_RB750 ++ +++config MTD_NAND_RB91X +++ tristate "NAND flash driver for the RouterBOARD 91x series" +++ depends on MTD_NAND && ATH79_MACH_RB91X +++ ++ config MTD_NAND_AR934X ++ tristate "NAND flash driver for the Qualcomm Atheros AR934x/QCA955x SoCs" ++ depends on (SOC_AR934X || SOC_QCA955X) ++--- a/drivers/mtd/nand/Makefile +++++ b/drivers/mtd/nand/Makefile ++@@ -37,6 +37,7 @@ obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nan ++ obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o ++ obj-$(CONFIG_MTD_NAND_RB4XX) += rb4xx_nand.o ++ obj-$(CONFIG_MTD_NAND_RB750) += rb750_nand.o +++obj-$(CONFIG_MTD_NAND_RB91X) += rb91x_nand.o ++ obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o ++ obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o ++ obj-$(CONFIG_MTD_NAND_OXNAS) += oxnas_nand.o +diff --git a/target/linux/ar71xx/patches-4.14/420-net-ar71xx_mac_driver.patch b/target/linux/ar71xx/patches-4.14/420-net-ar71xx_mac_driver.patch +new file mode 100644 +index 0000000000..6377db0ac2 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/420-net-ar71xx_mac_driver.patch +@@ -0,0 +1,28 @@ ++--- a/drivers/net/ethernet/atheros/Kconfig +++++ b/drivers/net/ethernet/atheros/Kconfig ++@@ -5,7 +5,7 @@ ++ config NET_VENDOR_ATHEROS ++ bool "Atheros devices" ++ default y ++- depends on PCI +++ depends on (PCI || ATH79) ++ ---help--- ++ If you have a network (Ethernet) card belonging to this class, say Y. ++ ++@@ -78,4 +78,6 @@ config ALX ++ To compile this driver as a module, choose M here. The module ++ will be called alx. ++ +++source drivers/net/ethernet/atheros/ag71xx/Kconfig +++ ++ endif # NET_VENDOR_ATHEROS ++--- a/drivers/net/ethernet/atheros/Makefile +++++ b/drivers/net/ethernet/atheros/Makefile ++@@ -3,6 +3,7 @@ ++ # Makefile for the Atheros network device drivers. ++ # ++ +++obj-$(CONFIG_AG71XX) += ag71xx/ ++ obj-$(CONFIG_ATL1) += atlx/ ++ obj-$(CONFIG_ATL2) += atlx/ ++ obj-$(CONFIG_ATL1E) += atl1e/ +diff --git a/target/linux/ar71xx/patches-4.14/423-dsa-add-88e6063-driver.patch b/target/linux/ar71xx/patches-4.14/423-dsa-add-88e6063-driver.patch +new file mode 100644 +index 0000000000..94172d01b7 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/423-dsa-add-88e6063-driver.patch +@@ -0,0 +1,27 @@ ++--- a/drivers/net/dsa/Kconfig +++++ b/drivers/net/dsa/Kconfig ++@@ -3,6 +3,14 @@ menu "Distributed Switch Architecture dr ++ ++ source "drivers/net/dsa/b53/Kconfig" ++ +++config NET_DSA_MV88E6063 +++ bool "Marvell 88E6063 ethernet switch chip support" +++ depends on NET_DSA +++ select NET_DSA_TAG_TRAILER +++ ---help--- +++ This enables support for the Marvell 88E6063 ethernet switch +++ chip +++ ++ config NET_DSA_BCM_SF2 ++ tristate "Broadcom Starfighter 2 Ethernet switch support" ++ depends on HAS_IOMEM && NET_DSA && OF_MDIO ++--- a/drivers/net/dsa/Makefile +++++ b/drivers/net/dsa/Makefile ++@@ -7,6 +7,7 @@ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdi ++ endif ++ obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o ++ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o +++obj-$(CONFIG_NET_DSA_MV88E6063) += mv88e6063.o ++ obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o ++ obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o ++ obj-$(CONFIG_NET_DSA_SMSC_LAN9303_I2C) += lan9303_i2c.o +diff --git a/target/linux/ar71xx/patches-4.14/430-drivers-link-spi-before-mtd.patch b/target/linux/ar71xx/patches-4.14/430-drivers-link-spi-before-mtd.patch +new file mode 100644 +index 0000000000..2f1549710b +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/430-drivers-link-spi-before-mtd.patch +@@ -0,0 +1,12 @@ ++--- a/drivers/Makefile +++++ b/drivers/Makefile ++@@ -83,8 +83,8 @@ obj-$(CONFIG_SCSI) += scsi/ ++ obj-y += nvme/ ++ obj-$(CONFIG_ATA) += ata/ ++ obj-$(CONFIG_TARGET_CORE) += target/ ++-obj-$(CONFIG_MTD) += mtd/ ++ obj-$(CONFIG_SPI) += spi/ +++obj-$(CONFIG_MTD) += mtd/ ++ obj-$(CONFIG_SPMI) += spmi/ ++ obj-$(CONFIG_HSI) += hsi/ ++ obj-y += net/ +diff --git a/target/linux/ar71xx/patches-4.14/432-spi-rb4xx-spi-driver.patch b/target/linux/ar71xx/patches-4.14/432-spi-rb4xx-spi-driver.patch +new file mode 100644 +index 0000000000..9b0148998f +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/432-spi-rb4xx-spi-driver.patch +@@ -0,0 +1,25 @@ ++--- a/drivers/spi/Kconfig +++++ b/drivers/spi/Kconfig ++@@ -563,6 +563,12 @@ config SPI_QUP ++ This driver can also be built as a module. If so, the module ++ will be called spi_qup. ++ +++config SPI_RB4XX +++ tristate "Mikrotik RB4XX SPI master" +++ depends on SPI_MASTER && ATH79_MACH_RB4XX +++ help +++ SPI controller driver for the Mikrotik RB4xx series boards. +++ ++ config SPI_S3C24XX ++ tristate "Samsung S3C24XX series SPI" ++ depends on ARCH_S3C24XX ++--- a/drivers/spi/Makefile +++++ b/drivers/spi/Makefile ++@@ -77,6 +77,7 @@ obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx. ++ spi-pxa2xx-platform-objs := spi-pxa2xx.o spi-pxa2xx-dma.o ++ obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o ++ obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o +++obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o ++ obj-$(CONFIG_SPI_QUP) += spi-qup.o ++ obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o ++ obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o +diff --git a/target/linux/ar71xx/patches-4.14/433-spi-rb4xx-cpld-driver.patch b/target/linux/ar71xx/patches-4.14/433-spi-rb4xx-cpld-driver.patch +new file mode 100644 +index 0000000000..02c30c6631 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/433-spi-rb4xx-cpld-driver.patch +@@ -0,0 +1,26 @@ ++--- a/drivers/spi/Kconfig +++++ b/drivers/spi/Kconfig ++@@ -801,6 +801,13 @@ config SPI_TLE62X0 ++ sysfs interface, with each line presented as a kind of GPIO ++ exposing both switch control and diagnostic feedback. ++ +++config SPI_RB4XX_CPLD +++ tristate "MikroTik RB4XX CPLD driver" +++ depends on ATH79_MACH_RB4XX +++ help +++ SPI driver for the Xilinx CPLD chip present on the +++ MikroTik RB4xx boards. +++ ++ # ++ # Add new SPI protocol masters in alphabetical order above this line ++ # ++--- a/drivers/spi/Makefile +++++ b/drivers/spi/Makefile ++@@ -78,6 +78,7 @@ spi-pxa2xx-platform-objs := spi-pxa2xx. ++ obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o ++ obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o ++ obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o +++obj-$(CONFIG_SPI_RB4XX_CPLD) += spi-rb4xx-cpld.o ++ obj-$(CONFIG_SPI_QUP) += spi-qup.o ++ obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o ++ obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o +diff --git a/target/linux/ar71xx/patches-4.14/435-spi-vsc7385_driver.patch b/target/linux/ar71xx/patches-4.14/435-spi-vsc7385_driver.patch +new file mode 100644 +index 0000000000..bef0c86761 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/435-spi-vsc7385_driver.patch +@@ -0,0 +1,24 @@ ++--- a/drivers/spi/Kconfig +++++ b/drivers/spi/Kconfig ++@@ -808,6 +808,11 @@ config SPI_RB4XX_CPLD ++ SPI driver for the Xilinx CPLD chip present on the ++ MikroTik RB4xx boards. ++ +++config SPI_VSC7385 +++ tristate "Vitesse VSC7385 ethernet switch driver" +++ help +++ SPI driver for the Vitesse VSC7385 ethernet switch. +++ ++ # ++ # Add new SPI protocol masters in alphabetical order above this line ++ # ++--- a/drivers/spi/Makefile +++++ b/drivers/spi/Makefile ++@@ -105,6 +105,7 @@ spi-thunderx-objs := spi-cavium.o spi- ++ obj-$(CONFIG_SPI_THUNDERX) += spi-thunderx.o ++ obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o ++ obj-$(CONFIG_SPI_TXX9) += spi-txx9.o +++obj-$(CONFIG_SPI_VSC7385) += spi-vsc7385.o ++ obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o ++ obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o ++ obj-$(CONFIG_SPI_XLP) += spi-xlp.o +diff --git a/target/linux/ar71xx/patches-4.14/440-leds-wndr3700-usb-led-driver.patch b/target/linux/ar71xx/patches-4.14/440-leds-wndr3700-usb-led-driver.patch +new file mode 100644 +index 0000000000..e5f7cc5c00 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/440-leds-wndr3700-usb-led-driver.patch +@@ -0,0 +1,26 @@ ++--- a/drivers/leds/Kconfig +++++ b/drivers/leds/Kconfig ++@@ -696,6 +696,13 @@ config LEDS_NIC78BX ++ To compile this driver as a module, choose M here: the module ++ will be called leds-nic78bx. ++ +++config LEDS_WNDR3700_USB +++ tristate "NETGEAR WNDR3700 USB LED driver" +++ depends on LEDS_CLASS && ATH79_MACH_WNDR3700 +++ help +++ This option enables support for the USB LED found on the +++ NETGEAR WNDR3700 board. +++ ++ comment "LED Triggers" ++ source "drivers/leds/trigger/Kconfig" ++ ++--- a/drivers/leds/Makefile +++++ b/drivers/leds/Makefile ++@@ -51,6 +51,7 @@ obj-$(CONFIG_LEDS_DA9052) += leds-da905 ++ obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o ++ obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o ++ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o +++obj-${CONFIG_LEDS_WNDR3700_USB} += leds-wndr3700-usb.o ++ obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o ++ obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o ++ obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o +diff --git a/target/linux/ar71xx/patches-4.14/441-leds-rb750-led-driver.patch b/target/linux/ar71xx/patches-4.14/441-leds-rb750-led-driver.patch +new file mode 100644 +index 0000000000..012e6b4380 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/441-leds-rb750-led-driver.patch +@@ -0,0 +1,23 @@ ++--- a/drivers/leds/Kconfig +++++ b/drivers/leds/Kconfig ++@@ -703,6 +703,10 @@ config LEDS_WNDR3700_USB ++ This option enables support for the USB LED found on the ++ NETGEAR WNDR3700 board. ++ +++config LEDS_RB750 +++ tristate "LED driver for the Mikrotik RouterBOARD 750" +++ depends on LEDS_CLASS && ATH79_MACH_RB750 +++ ++ comment "LED Triggers" ++ source "drivers/leds/trigger/Kconfig" ++ ++--- a/drivers/leds/Makefile +++++ b/drivers/leds/Makefile ++@@ -57,6 +57,7 @@ obj-$(CONFIG_LEDS_INTEL_SS4200) += leds ++ obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o ++ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o ++ obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o +++obj-$(CONFIG_LEDS_RB750) += leds-rb750.o ++ obj-$(CONFIG_LEDS_NS2) += leds-ns2.o ++ obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o ++ obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o +diff --git a/target/linux/ar71xx/patches-4.14/442-leds-gpio-allow-to-use-OPEN_-DRAIN-SOURCE-flags-with.patch b/target/linux/ar71xx/patches-4.14/442-leds-gpio-allow-to-use-OPEN_-DRAIN-SOURCE-flags-with.patch +new file mode 100644 +index 0000000000..3dbf68b1ed +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/442-leds-gpio-allow-to-use-OPEN_-DRAIN-SOURCE-flags-with.patch +@@ -0,0 +1,45 @@ ++From 183148e0789bee1cd5c46ba49afcb211f636f8a2 Mon Sep 17 00:00:00 2001 ++From: Gabor Juhos ++Date: Mon, 15 Jan 2018 15:01:14 +0100 ++Subject: [PATCH] leds: gpio: allow to use OPEN_{DRAIN,SOURCE} flags with ++ legacy GPIOs ++ ++LEDs which are connected to open-source or open-drain type of GPIO lines ++can be used only, if those are defined via devicetree. ++Add two new fields to 'struct gpio_led' in order to make it possible to ++specify this type of GPIO lines to the leds-gpio driver via platform data. ++Also update the create_gpio_led() function to set the GPIOF_OPEN_DRAIN and ++GPIOF_OPEN_SOURCE flags for the given GPIO line. ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/leds/leds-gpio.c | 6 ++++++ ++ include/linux/leds.h | 2 ++ ++ 2 files changed, 8 insertions(+) ++ ++--- a/drivers/leds/leds-gpio.c +++++ b/drivers/leds/leds-gpio.c ++@@ -100,6 +100,12 @@ static int create_gpio_led(const struct ++ if (template->active_low) ++ flags |= GPIOF_ACTIVE_LOW; ++ +++ if (template->open_drain) +++ flags |= GPIOF_OPEN_DRAIN; +++ +++ if (template->open_source) +++ flags |= GPIOF_OPEN_SOURCE; +++ ++ ret = devm_gpio_request_one(parent, template->gpio, flags, ++ template->name); ++ if (ret < 0) ++--- a/include/linux/leds.h +++++ b/include/linux/leds.h ++@@ -395,6 +395,8 @@ struct gpio_led { ++ unsigned default_state : 2; ++ unsigned retain_state_shutdown : 1; ++ /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */ +++ unsigned open_drain : 1; +++ unsigned open_source : 1; ++ struct gpio_desc *gpiod; ++ }; ++ #define LEDS_GPIO_DEFSTATE_OFF 0 +diff --git a/target/linux/ar71xx/patches-4.14/450-gpio-nxp-74hc153-gpio-chip-driver.patch b/target/linux/ar71xx/patches-4.14/450-gpio-nxp-74hc153-gpio-chip-driver.patch +new file mode 100644 +index 0000000000..48a36cc4ec +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/450-gpio-nxp-74hc153-gpio-chip-driver.patch +@@ -0,0 +1,25 @@ ++--- a/drivers/gpio/Kconfig +++++ b/drivers/gpio/Kconfig ++@@ -1300,4 +1300,12 @@ config GPIO_VIPERBOARD ++ ++ endmenu ++ +++comment "Other GPIO expanders" +++ +++config GPIO_NXP_74HC153 +++ tristate "NXP 74HC153 Dual 4-input multiplexer" +++ help +++ Platform driver for NXP 74HC153 Dual 4-input Multiplexer. This +++ provides a GPIO interface supporting input mode only. +++ ++ endif ++--- a/drivers/gpio/Makefile +++++ b/drivers/gpio/Makefile ++@@ -89,6 +89,7 @@ obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o ++ obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o ++ obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o ++ obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o +++obj-$(CONFIG_GPIO_NXP_74HC153) += gpio-nxp-74hc153.o ++ obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o ++ obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o ++ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o +diff --git a/target/linux/ar71xx/patches-4.14/451-gpio-74x164-improve-platform-device-support.patch b/target/linux/ar71xx/patches-4.14/451-gpio-74x164-improve-platform-device-support.patch +new file mode 100644 +index 0000000000..b3c990ccec +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/451-gpio-74x164-improve-platform-device-support.patch +@@ -0,0 +1,119 @@ ++--- a/drivers/gpio/gpio-74x164.c +++++ b/drivers/gpio/gpio-74x164.c ++@@ -13,6 +13,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -105,9 +106,16 @@ static int gen_74x164_direction_output(s ++ static int gen_74x164_probe(struct spi_device *spi) ++ { ++ struct gen_74x164_chip *chip; +++ struct gen_74x164_chip_platform_data *pdata = spi->dev.platform_data; +++ struct device_node *np = spi->dev.of_node; ++ u32 nregs; ++ int ret; ++ +++ if (!np && !pdata) { +++ dev_err(&spi->dev, "No configuration data available.\n"); +++ return -EINVAL; +++ } +++ ++ /* ++ * bits_per_word cannot be configured in platform data ++ */ ++@@ -117,12 +125,15 @@ static int gen_74x164_probe(struct spi_d ++ if (ret < 0) ++ return ret; ++ ++- if (of_property_read_u32(spi->dev.of_node, "registers-number", ++- &nregs)) { ++- dev_err(&spi->dev, ++- "Missing registers-number property in the DT.\n"); ++- return -EINVAL; ++- } +++ if (np) { +++ if (of_property_read_u32(np, "registers-number", &nregs)) { +++ dev_err(&spi->dev, +++ "Missing registers-number property in the DT.\n"); +++ return -EINVAL; +++ } +++ } else if (pdata) { +++ nregs = pdata->num_registers; +++ } ++ ++ chip = devm_kzalloc(&spi->dev, sizeof(*chip) + nregs, GFP_KERNEL); ++ if (!chip) ++@@ -142,7 +153,11 @@ static int gen_74x164_probe(struct spi_d ++ chip->gpio_chip.get = gen_74x164_get_value; ++ chip->gpio_chip.set = gen_74x164_set_value; ++ chip->gpio_chip.set_multiple = gen_74x164_set_multiple; ++- chip->gpio_chip.base = -1; +++ if (np) +++ chip->gpio_chip.base = -1; +++ else if (pdata) +++ chip->gpio_chip.base = pdata->base; +++ ++ ++ chip->registers = nregs; ++ chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; ++@@ -151,6 +166,9 @@ static int gen_74x164_probe(struct spi_d ++ chip->gpio_chip.parent = &spi->dev; ++ chip->gpio_chip.owner = THIS_MODULE; ++ +++ if (pdata && pdata->init_data) +++ memcpy(chip->buffer, pdata->init_data, chip->registers); +++ ++ mutex_init(&chip->lock); ++ ++ ret = __gen_74x164_write_config(chip); ++@@ -180,17 +198,19 @@ static int gen_74x164_remove(struct spi_ ++ return 0; ++ } ++ +++#ifdef CONFIG_OF ++ static const struct of_device_id gen_74x164_dt_ids[] = { ++ { .compatible = "fairchild,74hc595" }, ++ { .compatible = "nxp,74lvc594" }, ++ {}, ++ }; ++ MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids); +++#endif ++ ++ static struct spi_driver gen_74x164_driver = { ++ .driver = { ++ .name = "74x164", ++- .of_match_table = gen_74x164_dt_ids, +++ .of_match_table = of_match_ptr(gen_74x164_dt_ids), ++ }, ++ .probe = gen_74x164_probe, ++ .remove = gen_74x164_remove, ++--- /dev/null +++++ b/include/linux/spi/74x164.h ++@@ -0,0 +1,13 @@ +++#ifndef LINUX_SPI_74X164_H +++#define LINUX_SPI_74X164_H +++ +++struct gen_74x164_chip_platform_data { +++ /* number assigned to the first GPIO */ +++ unsigned base; +++ /* number of chained registers */ +++ unsigned num_registers; +++ /* address of a buffer containing initial data */ +++ u8 *init_data; +++}; +++ +++#endif ++--- a/drivers/gpio/Kconfig +++++ b/drivers/gpio/Kconfig ++@@ -1252,7 +1252,6 @@ menu "SPI GPIO expanders" ++ ++ config GPIO_74X164 ++ tristate "74x164 serial-in/parallel-out 8-bits shift register" ++- depends on OF_GPIO ++ help ++ Driver for 74x164 compatible serial-in/parallel-out 8-outputs ++ shift registers. This driver can be used to provide access +diff --git a/target/linux/ar71xx/patches-4.14/452-gpio-add-gpio-latch-driver.patch b/target/linux/ar71xx/patches-4.14/452-gpio-add-gpio-latch-driver.patch +new file mode 100644 +index 0000000000..98e9123ce7 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/452-gpio-add-gpio-latch-driver.patch +@@ -0,0 +1,22 @@ ++--- a/drivers/gpio/Kconfig +++++ b/drivers/gpio/Kconfig ++@@ -1307,4 +1307,9 @@ config GPIO_NXP_74HC153 ++ Platform driver for NXP 74HC153 Dual 4-input Multiplexer. This ++ provides a GPIO interface supporting input mode only. ++ +++config GPIO_LATCH +++ tristate "GPIO latch driver" +++ help +++ Say yes here to enable a GPIO latch driver. +++ ++ endif ++--- a/drivers/gpio/Makefile +++++ b/drivers/gpio/Makefile ++@@ -63,6 +63,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz ++ obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o ++ obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o ++ obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o +++obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o ++ obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o ++ obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o ++ obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o +diff --git a/target/linux/ar71xx/patches-4.14/461-spi-ath79-add-fast-flash-read.patch b/target/linux/ar71xx/patches-4.14/461-spi-ath79-add-fast-flash-read.patch +new file mode 100644 +index 0000000000..45f6dfbf1b +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/461-spi-ath79-add-fast-flash-read.patch +@@ -0,0 +1,60 @@ ++--- a/drivers/spi/spi-ath79.c +++++ b/drivers/spi/spi-ath79.c ++@@ -102,9 +102,6 @@ static void ath79_spi_enable(struct ath7 ++ /* save CTRL register */ ++ sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); ++ sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); ++- ++- /* TODO: setup speed? */ ++- ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); ++ } ++ ++ static void ath79_spi_disable(struct ath79_spi *sp) ++@@ -204,6 +201,38 @@ static u32 ath79_spi_txrx_mode0(struct s ++ return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS); ++ } ++ +++static bool ath79_spi_flash_read_supported(struct spi_device *spi) +++{ +++ if (spi->chip_select || gpio_is_valid(spi->cs_gpio)) +++ return false; +++ +++ return true; +++} +++ +++static int ath79_spi_read_flash_data(struct spi_device *spi, +++ struct spi_flash_read_message *msg) +++{ +++ struct ath79_spi *sp = ath79_spidev_to_sp(spi); +++ +++ if (msg->addr_width > 3) +++ return -EOPNOTSUPP; +++ +++ /* disable GPIO mode */ +++ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); +++ +++ memcpy_fromio(msg->buf, sp->base + msg->from, msg->len); +++ +++ /* enable GPIO mode */ +++ ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); +++ +++ /* restore IOC register */ +++ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); +++ +++ msg->retlen = msg->len; +++ +++ return 0; +++} +++ ++ static int ath79_spi_probe(struct platform_device *pdev) ++ { ++ struct spi_master *master; ++@@ -233,6 +262,8 @@ static int ath79_spi_probe(struct platfo ++ master->num_chipselect = pdata->num_chipselect; ++ master->cs_gpios = pdata->cs_gpios; ++ } +++ master->spi_flash_read = ath79_spi_read_flash_data; +++ master->flash_read_supported = ath79_spi_flash_read_supported; ++ ++ sp->bitbang.master = master; ++ sp->bitbang.chipselect = ath79_spi_chipselect; +diff --git a/target/linux/ar71xx/patches-4.14/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch b/target/linux/ar71xx/patches-4.14/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch +new file mode 100644 +index 0000000000..efd7d8d82b +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch +@@ -0,0 +1,111 @@ ++--- /dev/null +++++ b/arch/mips/include/asm/mach-ath79/mangle-port.h ++@@ -0,0 +1,37 @@ +++/* +++ * Copyright (C) 2012 Gabor Juhos +++ * +++ * This file was derived from: inlude/asm-mips/mach-generic/mangle-port.h +++ * Copyright (C) 2003, 2004 Ralf Baechle +++ * +++ * 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 __ASM_MACH_ATH79_MANGLE_PORT_H +++#define __ASM_MACH_ATH79_MANGLE_PORT_H +++ +++#ifdef CONFIG_PCI +++extern unsigned long (ath79_pci_swizzle_b)(unsigned long port); +++extern unsigned long (ath79_pci_swizzle_w)(unsigned long port); +++#else +++#define ath79_pci_swizzle_b(port) (port) +++#define ath79_pci_swizzle_w(port) (port) +++#endif +++ +++#define __swizzle_addr_b(port) ath79_pci_swizzle_b(port) +++#define __swizzle_addr_w(port) ath79_pci_swizzle_w(port) +++#define __swizzle_addr_l(port) (port) +++#define __swizzle_addr_q(port) (port) +++ +++# define ioswabb(a, x) (x) +++# define __mem_ioswabb(a, x) (x) +++# define ioswabw(a, x) (x) +++# define __mem_ioswabw(a, x) cpu_to_le16(x) +++# define ioswabl(a, x) (x) +++# define __mem_ioswabl(a, x) cpu_to_le32(x) +++# define ioswabq(a, x) (x) +++# define __mem_ioswabq(a, x) cpu_to_le64(x) +++ +++#endif /* __ASM_MACH_ATH79_MANGLE_PORT_H */ ++--- a/arch/mips/ath79/pci.c +++++ b/arch/mips/ath79/pci.c ++@@ -13,6 +13,7 @@ ++ */ ++ ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -25,6 +26,9 @@ static int (*ath79_pci_plat_dev_init)(st ++ static const struct ath79_pci_irq *ath79_pci_irq_map; ++ static unsigned ath79_pci_nr_irqs; ++ +++static unsigned long (*__ath79_pci_swizzle_b)(unsigned long port); +++static unsigned long (*__ath79_pci_swizzle_w)(unsigned long port); +++ ++ static const struct ath79_pci_irq ar71xx_pci_irq_map[] = { ++ { ++ .slot = 17, ++@@ -212,12 +216,50 @@ ath79_register_pci_ar724x(int id, ++ return pdev; ++ } ++ +++static inline bool ar71xx_is_pci_addr(unsigned long port) +++{ +++ unsigned long phys = CPHYSADDR(port); +++ +++ return (phys >= AR71XX_PCI_MEM_BASE && +++ phys < AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE); +++} +++ +++static unsigned long ar71xx_pci_swizzle_b(unsigned long port) +++{ +++ return ar71xx_is_pci_addr(port) ? port ^ 3 : port; +++} +++ +++static unsigned long ar71xx_pci_swizzle_w(unsigned long port) +++{ +++ return ar71xx_is_pci_addr(port) ? port ^ 2 : port; +++} +++ +++unsigned long ath79_pci_swizzle_b(unsigned long port) +++{ +++ if (__ath79_pci_swizzle_b) +++ return __ath79_pci_swizzle_b(port); +++ +++ return port; +++} +++EXPORT_SYMBOL(ath79_pci_swizzle_b); +++ +++unsigned long ath79_pci_swizzle_w(unsigned long port) +++{ +++ if (__ath79_pci_swizzle_w) +++ return __ath79_pci_swizzle_w(port); +++ +++ return port; +++} +++EXPORT_SYMBOL(ath79_pci_swizzle_w); +++ ++ int __init ath79_register_pci(void) ++ { ++ struct platform_device *pdev = NULL; ++ ++ if (soc_is_ar71xx()) { ++ pdev = ath79_register_pci_ar71xx(); +++ __ath79_pci_swizzle_b = ar71xx_pci_swizzle_b; +++ __ath79_pci_swizzle_w = ar71xx_pci_swizzle_w; ++ } else if (soc_is_ar724x()) { ++ pdev = ath79_register_pci_ar724x(-1, ++ AR724X_PCI_CFG_BASE, +diff --git a/target/linux/ar71xx/patches-4.14/490-usb-ehci-add-quirks-for-qca-socs.patch b/target/linux/ar71xx/patches-4.14/490-usb-ehci-add-quirks-for-qca-socs.patch +new file mode 100644 +index 0000000000..f9ee417bb4 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/490-usb-ehci-add-quirks-for-qca-socs.patch +@@ -0,0 +1,103 @@ ++--- a/drivers/usb/host/ehci-hcd.c +++++ b/drivers/usb/host/ehci-hcd.c ++@@ -252,6 +252,37 @@ int ehci_reset(struct ehci_hcd *ehci) ++ command |= CMD_RESET; ++ dbg_cmd (ehci, "reset", command); ++ ehci_writel(ehci, command, &ehci->regs->command); +++ +++ if (ehci->qca_force_host_mode) { +++ u32 usbmode; +++ +++ udelay(1000); +++ +++ usbmode = ehci_readl(ehci, &ehci->regs->usbmode); +++ usbmode |= USBMODE_CM_HC | (1 << 4); +++ ehci_writel(ehci, usbmode, &ehci->regs->usbmode); +++ +++ ehci_dbg(ehci, "forced host mode, usbmode: %08x\n", +++ ehci_readl(ehci, &ehci->regs->usbmode)); +++ } +++ +++ if (ehci->qca_force_16bit_ptw) { +++ u32 port_status; +++ +++ udelay(1000); +++ +++ /* enable 16-bit UTMI interface */ +++ port_status = ehci_readl(ehci, &ehci->regs->port_status[0]); +++ port_status |= BIT(28); +++ ehci_writel(ehci, port_status, &ehci->regs->port_status[0]); +++ +++ ehci_dbg(ehci, "16-bit UTMI interface enabled, status: %08x\n", +++ ehci_readl(ehci, &ehci->regs->port_status[0])); +++ } +++ +++ if (ehci->reset_notifier) +++ ehci->reset_notifier(ehci_to_hcd(ehci)); +++ ++ ehci->rh_state = EHCI_RH_HALTED; ++ ehci->next_statechange = jiffies; ++ retval = ehci_handshake(ehci, &ehci->regs->command, ++--- a/drivers/usb/host/ehci.h +++++ b/drivers/usb/host/ehci.h ++@@ -232,6 +232,10 @@ struct ehci_hcd { /* one per controlle ++ unsigned need_oc_pp_cycle:1; /* MPC834X port power */ ++ unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ ++ unsigned ignore_oc:1; +++ unsigned qca_force_host_mode:1; +++ unsigned qca_force_16bit_ptw:1; /* force 16 bit UTMI */ +++ +++ void (*reset_notifier)(struct usb_hcd *hcd); ++ ++ /* required for usb32 quirk */ ++ #define OHCI_CTRL_HCFS (3 << 6) ++--- a/include/linux/usb/ehci_pdriver.h +++++ b/include/linux/usb/ehci_pdriver.h ++@@ -50,6 +50,8 @@ struct usb_ehci_pdata { ++ unsigned reset_on_resume:1; ++ unsigned dma_mask_64:1; ++ unsigned ignore_oc:1; +++ unsigned qca_force_host_mode:1; +++ unsigned qca_force_16bit_ptw:1; ++ ++ /* Turn on all power and clocks */ ++ int (*power_on)(struct platform_device *pdev); ++@@ -59,6 +61,7 @@ struct usb_ehci_pdata { ++ * turn off everything else */ ++ void (*power_suspend)(struct platform_device *pdev); ++ int (*pre_setup)(struct usb_hcd *hcd); +++ void (*reset_notifier)(struct platform_device *pdev); ++ }; ++ ++ #endif /* __USB_CORE_EHCI_PDRIVER_H */ ++--- a/drivers/usb/host/ehci-platform.c +++++ b/drivers/usb/host/ehci-platform.c ++@@ -53,6 +53,14 @@ struct ehci_platform_priv { ++ ++ static const char hcd_name[] = "ehci-platform"; ++ +++static void ehci_platform_reset_notifier(struct usb_hcd *hcd) +++{ +++ struct platform_device *pdev = to_platform_device(hcd->self.controller); +++ struct usb_ehci_pdata *pdata = pdev->dev.platform_data; +++ +++ pdata->reset_notifier(pdev); +++} +++ ++ static int ehci_platform_reset(struct usb_hcd *hcd) ++ { ++ struct platform_device *pdev = to_platform_device(hcd->self.controller); ++@@ -265,6 +273,13 @@ static int ehci_platform_probe(struct pl ++ priv->reset_on_resume = true; ++ if (pdata->ignore_oc) ++ ehci->ignore_oc = 1; +++ if (pdata->qca_force_host_mode) +++ ehci->qca_force_host_mode = 1; +++ if (pdata->qca_force_16bit_ptw) +++ ehci->qca_force_16bit_ptw = 1; +++ +++ if (pdata->reset_notifier) +++ ehci->reset_notifier = ehci_platform_reset_notifier; ++ ++ #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO ++ if (ehci->big_endian_mmio) { +diff --git a/target/linux/ar71xx/patches-4.14/500-MIPS-fw-myloader.patch b/target/linux/ar71xx/patches-4.14/500-MIPS-fw-myloader.patch +new file mode 100644 +index 0000000000..1fdd05a4d9 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/500-MIPS-fw-myloader.patch +@@ -0,0 +1,22 @@ ++--- a/arch/mips/Makefile +++++ b/arch/mips/Makefile ++@@ -228,6 +228,7 @@ cflags-$(toolchain-virt) += -DTOOLCHAIN ++ # ++ libs-$(CONFIG_FW_ARC) += arch/mips/fw/arc/ ++ libs-$(CONFIG_FW_CFE) += arch/mips/fw/cfe/ +++libs-$(CONFIG_MYLOADER) += arch/mips/fw/myloader/ ++ libs-$(CONFIG_FW_SNIPROM) += arch/mips/fw/sni/ ++ libs-y += arch/mips/fw/lib/ ++ ++--- a/arch/mips/Kconfig +++++ b/arch/mips/Kconfig ++@@ -1153,6 +1153,9 @@ config MIPS_MSC ++ config MIPS_NILE4 ++ bool ++ +++config MYLOADER +++ bool +++ ++ config SYNC_R4K ++ bool ++ +diff --git a/target/linux/ar71xx/patches-4.14/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch b/target/linux/ar71xx/patches-4.14/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch +new file mode 100644 +index 0000000000..12ab3b50d6 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch +@@ -0,0 +1,70 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -15,6 +15,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ ++@@ -22,6 +23,7 @@ ++ #include ++ #include "dev-wmac.h" ++ +++static u8 ath79_wmac_mac[ETH_ALEN]; ++ static struct ath9k_platform_data ath79_wmac_data; ++ ++ static struct resource ath79_wmac_resources[] = { ++@@ -161,7 +163,7 @@ static void qca955x_wmac_setup(void) ++ ath79_wmac_data.is_clk_25mhz = true; ++ } ++ ++-void __init ath79_register_wmac(u8 *cal_data) +++void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) ++ { ++ if (soc_is_ar913x()) ++ ar913x_wmac_setup(); ++@@ -178,5 +180,10 @@ void __init ath79_register_wmac(u8 *cal_ ++ memcpy(ath79_wmac_data.eeprom_data, cal_data, ++ sizeof(ath79_wmac_data.eeprom_data)); ++ +++ if (mac_addr) { +++ memcpy(ath79_wmac_mac, mac_addr, sizeof(ath79_wmac_mac)); +++ ath79_wmac_data.macaddr = ath79_wmac_mac; +++ } +++ ++ platform_device_register(&ath79_wmac_device); ++ } ++--- a/arch/mips/ath79/dev-wmac.h +++++ b/arch/mips/ath79/dev-wmac.h ++@@ -12,6 +12,6 @@ ++ #ifndef _ATH79_DEV_WMAC_H ++ #define _ATH79_DEV_WMAC_H ++ ++-void ath79_register_wmac(u8 *cal_data); +++void ath79_register_wmac(u8 *cal_data, u8 *mac_addr); ++ ++ #endif /* _ATH79_DEV_WMAC_H */ ++--- a/arch/mips/ath79/mach-db120.c +++++ b/arch/mips/ath79/mach-db120.c ++@@ -128,7 +128,7 @@ static void __init db120_setup(void) ++ ath79_register_spi(&db120_spi_data, db120_spi_info, ++ ARRAY_SIZE(db120_spi_info)); ++ ath79_register_usb(); ++- ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET); +++ ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET, NULL); ++ db120_pci_init(art + DB120_PCIE_CALDATA_OFFSET); ++ } ++ ++--- a/arch/mips/ath79/mach-ap121.c +++++ b/arch/mips/ath79/mach-ap121.c ++@@ -85,7 +85,7 @@ static void __init ap121_setup(void) ++ ath79_register_spi(&ap121_spi_data, ap121_spi_info, ++ ARRAY_SIZE(ap121_spi_info)); ++ ath79_register_usb(); ++- ath79_register_wmac(cal_data); +++ ath79_register_wmac(cal_data, NULL); ++ } ++ ++ MIPS_MACHINE(ATH79_MACH_AP121, "AP121", "Atheros AP121 reference board", +diff --git a/target/linux/ar71xx/patches-4.14/504-MIPS-ath79-add-ath79_device_reset_get.patch b/target/linux/ar71xx/patches-4.14/504-MIPS-ath79-add-ath79_device_reset_get.patch +new file mode 100644 +index 0000000000..c0e96b2729 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/504-MIPS-ath79-add-ath79_device_reset_get.patch +@@ -0,0 +1,42 @@ ++--- a/arch/mips/include/asm/mach-ath79/ath79.h +++++ b/arch/mips/include/asm/mach-ath79/ath79.h ++@@ -145,6 +145,7 @@ static inline u32 ath79_reset_rr(unsigne ++ ++ void ath79_device_reset_set(u32 mask); ++ void ath79_device_reset_clear(u32 mask); +++u32 ath79_device_reset_get(u32 mask); ++ ++ void ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3); ++ void ath79_misc_irq_init(void __iomem *regs, int irq, ++--- a/arch/mips/ath79/common.c +++++ b/arch/mips/ath79/common.c ++@@ -142,3 +142,29 @@ void ath79_device_reset_clear(u32 mask) ++ spin_unlock_irqrestore(&ath79_device_reset_lock, flags); ++ } ++ EXPORT_SYMBOL_GPL(ath79_device_reset_clear); +++ +++u32 ath79_device_reset_get(u32 mask) +++{ +++ unsigned long flags; +++ u32 reg; +++ u32 ret; +++ +++ if (soc_is_ar71xx()) +++ reg = AR71XX_RESET_REG_RESET_MODULE; +++ else if (soc_is_ar724x()) +++ reg = AR724X_RESET_REG_RESET_MODULE; +++ else if (soc_is_ar913x()) +++ reg = AR913X_RESET_REG_RESET_MODULE; +++ else if (soc_is_ar933x()) +++ reg = AR933X_RESET_REG_RESET_MODULE; +++ else if (soc_is_ar934x()) +++ reg = AR934X_RESET_REG_RESET_MODULE; +++ else +++ BUG(); +++ +++ spin_lock_irqsave(&ath79_device_reset_lock, flags); +++ ret = ath79_reset_rr(reg); +++ spin_unlock_irqrestore(&ath79_device_reset_lock, flags); +++ return ret; +++} +++EXPORT_SYMBOL_GPL(ath79_device_reset_get); +diff --git a/target/linux/ar71xx/patches-4.14/505-MIPS-ath79-add-ath79_gpio_function_select.patch b/target/linux/ar71xx/patches-4.14/505-MIPS-ath79-add-ath79_gpio_function_select.patch +new file mode 100644 +index 0000000000..278e781539 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/505-MIPS-ath79-add-ath79_gpio_function_select.patch +@@ -0,0 +1,39 @@ ++--- a/arch/mips/ath79/common.h +++++ b/arch/mips/ath79/common.h ++@@ -27,6 +27,7 @@ void ath79_ddr_ctrl_init(void); ++ void ath79_gpio_function_enable(u32 mask); ++ void ath79_gpio_function_disable(u32 mask); ++ void ath79_gpio_function_setup(u32 set, u32 clear); +++void ath79_gpio_output_select(unsigned gpio, u8 val); ++ void ath79_gpio_init(void); ++ ++ #endif /* __ATH79_COMMON_H */ ++--- a/arch/mips/ath79/gpio.c +++++ b/arch/mips/ath79/gpio.c ++@@ -57,3 +57,26 @@ void ath79_gpio_function_disable(u32 mas ++ { ++ ath79_gpio_function_setup(0, mask); ++ } +++ +++void __init ath79_gpio_output_select(unsigned gpio, u8 val) +++{ +++ void __iomem *base = ath79_gpio_base; +++ unsigned int reg; +++ u32 t, s; +++ +++ BUG_ON(!soc_is_ar934x()); +++ +++ if (gpio >= AR934X_GPIO_COUNT) +++ return; +++ +++ reg = AR934X_GPIO_REG_OUT_FUNC0 + 4 * (gpio / 4); +++ s = 8 * (gpio % 4); +++ +++ t = __raw_readl(base + reg); +++ t &= ~(0xff << s); +++ t |= val << s; +++ __raw_writel(t, base + reg); +++ +++ /* flush write */ +++ (void) __raw_readl(base + reg); +++} +diff --git a/target/linux/ar71xx/patches-4.14/506-MIPS-ath79-prom-parse-redboot-args.patch b/target/linux/ar71xx/patches-4.14/506-MIPS-ath79-prom-parse-redboot-args.patch +new file mode 100644 +index 0000000000..46beeffeea +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/506-MIPS-ath79-prom-parse-redboot-args.patch +@@ -0,0 +1,42 @@ ++--- a/arch/mips/ath79/prom.c +++++ b/arch/mips/ath79/prom.c ++@@ -22,10 +22,39 @@ ++ ++ #include "common.h" ++ +++static char ath79_cmdline_buf[COMMAND_LINE_SIZE] __initdata; +++ +++static void __init ath79_prom_append_cmdline(const char *name, +++ const char *value) +++{ +++ snprintf(ath79_cmdline_buf, sizeof(ath79_cmdline_buf), +++ " %s=%s", name, value); +++ strlcat(arcs_cmdline, ath79_cmdline_buf, sizeof(arcs_cmdline)); +++} +++ ++ void __init prom_init(void) ++ { +++ const char *env; +++ ++ fw_init_cmdline(); ++ +++ env = fw_getenv("ethaddr"); +++ if (env) +++ ath79_prom_append_cmdline("ethaddr", env); +++ +++ env = fw_getenv("board"); +++ if (env) { +++ /* Workaround for buggy bootloaders */ +++ if (strcmp(env, "RouterStation") == 0 || +++ strcmp(env, "Ubiquiti AR71xx-based board") == 0) +++ env = "UBNT-RS"; +++ +++ if (strcmp(env, "RouterStation PRO") == 0) +++ env = "UBNT-RSPRO"; +++ +++ ath79_prom_append_cmdline("board", env); +++ } +++ ++ #ifdef CONFIG_BLK_DEV_INITRD ++ /* Read the initrd address from the firmware environment */ ++ initrd_start = fw_getenvl("initrd_start"); +diff --git a/target/linux/ar71xx/patches-4.14/507-MIPS-ath79-prom-add-myloader-support.patch b/target/linux/ar71xx/patches-4.14/507-MIPS-ath79-prom-add-myloader-support.patch +new file mode 100644 +index 0000000000..17a97335d2 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/507-MIPS-ath79-prom-add-myloader-support.patch +@@ -0,0 +1,55 @@ ++--- a/arch/mips/ath79/prom.c +++++ b/arch/mips/ath79/prom.c ++@@ -19,6 +19,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "common.h" ++ ++@@ -32,10 +33,44 @@ static void __init ath79_prom_append_cmd ++ strlcat(arcs_cmdline, ath79_cmdline_buf, sizeof(arcs_cmdline)); ++ } ++ +++static int __init ath79_prom_init_myloader(void) +++{ +++ struct myloader_info *mylo; +++ char mac_buf[32]; +++ unsigned char *mac; +++ +++ mylo = myloader_get_info(); +++ if (!mylo) +++ return 0; +++ +++ switch (mylo->did) { +++ case DEVID_COMPEX_WP543: +++ ath79_prom_append_cmdline("board", "WP543"); +++ break; +++ case DEVID_COMPEX_WPE72: +++ ath79_prom_append_cmdline("board", "WPE72"); +++ break; +++ default: +++ pr_warn("prom: unknown device id: %x\n", mylo->did); +++ return 0; +++ } +++ +++ mac = mylo->macs[0]; +++ snprintf(mac_buf, sizeof(mac_buf), "%02x:%02x:%02x:%02x:%02x:%02x", +++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +++ +++ ath79_prom_append_cmdline("ethaddr", mac_buf); +++ +++ return 1; +++} +++ ++ void __init prom_init(void) ++ { ++ const char *env; ++ +++ if (ath79_prom_init_myloader()) +++ return; +++ ++ fw_init_cmdline(); ++ ++ env = fw_getenv("ethaddr"); +diff --git a/target/linux/ar71xx/patches-4.14/508-MIPS-ath79-prom-image-command-line-hack.patch b/target/linux/ar71xx/patches-4.14/508-MIPS-ath79-prom-image-command-line-hack.patch +new file mode 100644 +index 0000000000..cfa5e72eec +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/508-MIPS-ath79-prom-image-command-line-hack.patch +@@ -0,0 +1,73 @@ ++--- a/arch/mips/ath79/prom.c +++++ b/arch/mips/ath79/prom.c ++@@ -33,6 +33,41 @@ static void __init ath79_prom_append_cmd ++ strlcat(arcs_cmdline, ath79_cmdline_buf, sizeof(arcs_cmdline)); ++ } ++ +++#ifdef CONFIG_IMAGE_CMDLINE_HACK +++extern char __image_cmdline[]; +++ +++static int __init ath79_use_image_cmdline(void) +++{ +++ char *p = __image_cmdline; +++ int replace = 0; +++ +++ if (*p == '-') { +++ replace = 1; +++ p++; +++ } +++ +++ if (*p == '\0') +++ return 0; +++ +++ if (replace) { +++ strlcpy(arcs_cmdline, p, sizeof(arcs_cmdline)); +++ } else { +++ strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); +++ strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); +++ } +++ +++ /* Validate and setup environment pointer */ +++ if (fw_arg2 < CKSEG0) +++ _fw_envp = NULL; +++ else +++ _fw_envp = (int *)fw_arg2; +++ +++ return 1; +++} +++#else +++static inline int ath79_use_image_cmdline(void) { return 0; } +++#endif +++ ++ static int __init ath79_prom_init_myloader(void) ++ { ++ struct myloader_info *mylo; ++@@ -61,6 +96,8 @@ static int __init ath79_prom_init_myload ++ ++ ath79_prom_append_cmdline("ethaddr", mac_buf); ++ +++ ath79_use_image_cmdline(); +++ ++ return 1; ++ } ++ ++@@ -71,7 +108,8 @@ void __init prom_init(void) ++ if (ath79_prom_init_myloader()) ++ return; ++ ++- fw_init_cmdline(); +++ if (!ath79_use_image_cmdline()) +++ fw_init_cmdline(); ++ ++ env = fw_getenv("ethaddr"); ++ if (env) ++--- a/arch/mips/fw/lib/cmdline.c +++++ b/arch/mips/fw/lib/cmdline.c ++@@ -35,6 +35,7 @@ void __init fw_init_cmdline(void) ++ else ++ _fw_envp = (int *)fw_arg2; ++ +++ arcs_cmdline[0] = '\0'; ++ for (i = 1; i < fw_argc; i++) { ++ strlcat(arcs_cmdline, fw_argv(i), COMMAND_LINE_SIZE); ++ if (i < (fw_argc - 1)) +diff --git a/target/linux/ar71xx/patches-4.14/509-MIPS-ath79-process-board-kernel-option.patch b/target/linux/ar71xx/patches-4.14/509-MIPS-ath79-process-board-kernel-option.patch +new file mode 100644 +index 0000000000..139b09c1b0 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/509-MIPS-ath79-process-board-kernel-option.patch +@@ -0,0 +1,11 @@ ++--- a/arch/mips/ath79/setup.c +++++ b/arch/mips/ath79/setup.c ++@@ -277,6 +277,8 @@ void __init plat_time_init(void) ++ mips_hpt_frequency = cpu_clk_rate / 2; ++ } ++ +++__setup("board=", mips_machtype_setup); +++ ++ static int __init ath79_setup(void) ++ { ++ if (mips_machtype == ATH79_MACH_GENERIC_OF) +diff --git a/target/linux/ar71xx/patches-4.14/510-MIPS-ath79-init-gpio-pin-of-wmac-device.patch b/target/linux/ar71xx/patches-4.14/510-MIPS-ath79-init-gpio-pin-of-wmac-device.patch +new file mode 100644 +index 0000000000..2d2235e292 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/510-MIPS-ath79-init-gpio-pin-of-wmac-device.patch +@@ -0,0 +1,14 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -24,7 +24,10 @@ ++ #include "dev-wmac.h" ++ ++ static u8 ath79_wmac_mac[ETH_ALEN]; ++-static struct ath9k_platform_data ath79_wmac_data; +++ +++static struct ath9k_platform_data ath79_wmac_data = { +++ .led_pin = -1, +++}; ++ ++ static struct resource ath79_wmac_resources[] = { ++ { +diff --git a/target/linux/ar71xx/patches-4.14/520-MIPS-ath79-enable-UART-function.patch b/target/linux/ar71xx/patches-4.14/520-MIPS-ath79-enable-UART-function.patch +new file mode 100644 +index 0000000000..c8649b7494 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/520-MIPS-ath79-enable-UART-function.patch +@@ -0,0 +1,18 @@ ++--- a/arch/mips/ath79/dev-common.c +++++ b/arch/mips/ath79/dev-common.c ++@@ -81,6 +81,15 @@ void __init ath79_register_uart(void) ++ ++ uart_clk_rate = ath79_get_sys_clk_rate("uart"); ++ +++ if (soc_is_ar71xx()) +++ ath79_gpio_function_enable(AR71XX_GPIO_FUNC_UART_EN); +++ else if (soc_is_ar724x()) +++ ath79_gpio_function_enable(AR724X_GPIO_FUNC_UART_EN); +++ else if (soc_is_ar913x()) +++ ath79_gpio_function_enable(AR913X_GPIO_FUNC_UART_EN); +++ else if (soc_is_ar933x()) +++ ath79_gpio_function_enable(AR933X_GPIO_FUNC_UART_EN); +++ ++ if (soc_is_ar71xx() || ++ soc_is_ar724x() || ++ soc_is_ar913x() || +diff --git a/target/linux/ar71xx/patches-4.14/521-MIPS-ath79-enable-UART-for-early_serial.patch b/target/linux/ar71xx/patches-4.14/521-MIPS-ath79-enable-UART-for-early_serial.patch +new file mode 100644 +index 0000000000..e546ff26fe +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/521-MIPS-ath79-enable-UART-for-early_serial.patch +@@ -0,0 +1,61 @@ ++--- a/arch/mips/ath79/early_printk.c +++++ b/arch/mips/ath79/early_printk.c ++@@ -58,6 +58,46 @@ static void prom_putchar_dummy(unsigned ++ /* nothing to do */ ++ } ++ +++static void prom_enable_uart(u32 id) +++{ +++ void __iomem *gpio_base; +++ u32 uart_en; +++ u32 t; +++ +++ switch (id) { +++ case REV_ID_MAJOR_AR71XX: +++ uart_en = AR71XX_GPIO_FUNC_UART_EN; +++ break; +++ +++ case REV_ID_MAJOR_AR7240: +++ case REV_ID_MAJOR_AR7241: +++ case REV_ID_MAJOR_AR7242: +++ uart_en = AR724X_GPIO_FUNC_UART_EN; +++ break; +++ +++ case REV_ID_MAJOR_AR913X: +++ uart_en = AR913X_GPIO_FUNC_UART_EN; +++ break; +++ +++ case REV_ID_MAJOR_AR9330: +++ case REV_ID_MAJOR_AR9331: +++ uart_en = AR933X_GPIO_FUNC_UART_EN; +++ break; +++ +++ case REV_ID_MAJOR_AR9341: +++ case REV_ID_MAJOR_AR9342: +++ case REV_ID_MAJOR_AR9344: +++ /* TODO */ +++ default: +++ return; +++ } +++ +++ gpio_base = (void __iomem *)(KSEG1ADDR(AR71XX_GPIO_BASE)); +++ t = __raw_readl(gpio_base + AR71XX_GPIO_REG_FUNC); +++ t |= uart_en; +++ __raw_writel(t, gpio_base + AR71XX_GPIO_REG_FUNC); +++} +++ ++ static void prom_putchar_init(void) ++ { ++ void __iomem *base; ++@@ -88,8 +128,10 @@ static void prom_putchar_init(void) ++ ++ default: ++ _prom_putchar = prom_putchar_dummy; ++- break; +++ return; ++ } +++ +++ prom_enable_uart(id); ++ } ++ ++ void prom_putchar(unsigned char ch) +diff --git a/target/linux/ar71xx/patches-4.14/522-MIPS-ath79-add-ath79_wmac_register_simple-helper.patch b/target/linux/ar71xx/patches-4.14/522-MIPS-ath79-add-ath79_wmac_register_simple-helper.patch +new file mode 100644 +index 0000000000..2d5559cb9d +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/522-MIPS-ath79-add-ath79_wmac_register_simple-helper.patch +@@ -0,0 +1,21 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -190,3 +190,9 @@ void __init ath79_register_wmac(u8 *cal_ ++ ++ platform_device_register(&ath79_wmac_device); ++ } +++ +++void __init ath79_register_wmac_simple(void) +++{ +++ ath79_register_wmac(NULL, NULL); +++ ath79_wmac_data.eeprom_name = "soc_wmac.eeprom"; +++} ++--- a/arch/mips/ath79/dev-wmac.h +++++ b/arch/mips/ath79/dev-wmac.h ++@@ -13,5 +13,6 @@ ++ #define _ATH79_DEV_WMAC_H ++ ++ void ath79_register_wmac(u8 *cal_data, u8 *mac_addr); +++void ath79_register_wmac_simple(void); ++ ++ #endif /* _ATH79_DEV_WMAC_H */ +diff --git a/target/linux/ar71xx/patches-4.14/523-MIPS-ath79-OTP-support.patch b/target/linux/ar71xx/patches-4.14/523-MIPS-ath79-OTP-support.patch +new file mode 100644 +index 0000000000..d11d418f17 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/523-MIPS-ath79-OTP-support.patch +@@ -0,0 +1,192 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -166,6 +166,149 @@ static void qca955x_wmac_setup(void) ++ ath79_wmac_data.is_clk_25mhz = true; ++ } ++ +++#define AR93XX_WMAC_SIZE \ +++ (soc_is_ar934x() ? AR934X_WMAC_SIZE : AR933X_WMAC_SIZE) +++#define AR93XX_WMAC_BASE \ +++ (soc_is_ar934x() ? AR934X_WMAC_BASE : AR933X_WMAC_BASE) +++ +++#define AR93XX_OTP_BASE \ +++ (soc_is_ar934x() ? AR934X_OTP_BASE : AR9300_OTP_BASE) +++#define AR93XX_OTP_STATUS \ +++ (soc_is_ar934x() ? AR934X_OTP_STATUS : AR9300_OTP_STATUS) +++#define AR93XX_OTP_READ_DATA \ +++ (soc_is_ar934x() ? AR934X_OTP_READ_DATA : AR9300_OTP_READ_DATA) +++ +++static bool __init +++ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data) +++{ +++ int timeout = 1000; +++ u32 val; +++ +++ __raw_readl(base + AR93XX_OTP_BASE + (4 * addr)); +++ while (timeout--) { +++ val = __raw_readl(base + AR93XX_OTP_STATUS); +++ if ((val & AR9300_OTP_STATUS_TYPE) == AR9300_OTP_STATUS_VALID) +++ break; +++ +++ udelay(10); +++ } +++ +++ if (!timeout) +++ return false; +++ +++ *data = __raw_readl(base + AR93XX_OTP_READ_DATA); +++ return true; +++} +++ +++static bool __init +++ar93xx_wmac_otp_read(void __iomem *base, int addr, u8 *dest, int len) +++{ +++ u32 data; +++ int i; +++ +++ for (i = 0; i < len; i++) { +++ int offset = 8 * ((addr - i) % 4); +++ +++ if (!ar93xx_wmac_otp_read_word(base, (addr - i) / 4, &data)) +++ return false; +++ +++ dest[i] = (data >> offset) & 0xff; +++ } +++ +++ return true; +++} +++ +++static bool __init +++ar93xx_wmac_otp_uncompress(void __iomem *base, int addr, int len, u8 *dest, +++ int dest_start, int dest_len) +++{ +++ int dest_bytes = 0; +++ int offset = 0; +++ int end = addr - len; +++ u8 hdr[2]; +++ +++ while (addr > end) { +++ if (!ar93xx_wmac_otp_read(base, addr, hdr, 2)) +++ return false; +++ +++ addr -= 2; +++ offset += hdr[0]; +++ +++ if (offset <= dest_start + dest_len && +++ offset + len >= dest_start) { +++ int data_offset = 0; +++ int dest_offset = 0; +++ int copy_len; +++ +++ if (offset < dest_start) +++ data_offset = dest_start - offset; +++ else +++ dest_offset = offset - dest_start; +++ +++ copy_len = len - data_offset; +++ if (copy_len > dest_len - dest_offset) +++ copy_len = dest_len - dest_offset; +++ +++ ar93xx_wmac_otp_read(base, addr - data_offset, +++ dest + dest_offset, +++ copy_len); +++ +++ dest_bytes += copy_len; +++ } +++ addr -= hdr[1]; +++ } +++ return !!dest_bytes; +++} +++ +++bool __init ar93xx_wmac_read_mac_address(u8 *dest) +++{ +++ void __iomem *base; +++ bool ret = false; +++ int addr = 0x1ff; +++ unsigned int len; +++ u32 hdr_u32; +++ u8 *hdr = (u8 *) &hdr_u32; +++ u8 mac[6] = { 0x00, 0x02, 0x03, 0x04, 0x05, 0x06 }; +++ int mac_start = 2, mac_end = 8; +++ +++ BUG_ON(!soc_is_ar933x() && !soc_is_ar934x()); +++ base = ioremap_nocache(AR93XX_WMAC_BASE, AR93XX_WMAC_SIZE); +++ while (addr > sizeof(hdr_u32)) { +++ if (!ar93xx_wmac_otp_read(base, addr, hdr, sizeof(hdr_u32))) +++ break; +++ +++ if (hdr_u32 == 0 || hdr_u32 == ~0) +++ break; +++ +++ len = (hdr[1] << 4) | (hdr[2] >> 4); +++ addr -= 4; +++ +++ switch (hdr[0] >> 5) { +++ case 0: +++ if (len < mac_end) +++ break; +++ +++ ar93xx_wmac_otp_read(base, addr - mac_start, mac, 6); +++ ret = true; +++ break; +++ case 3: +++ ret |= ar93xx_wmac_otp_uncompress(base, addr, len, mac, +++ mac_start, 6); +++ break; +++ default: +++ break; +++ } +++ +++ addr -= len + 2; +++ } +++ +++ iounmap(base); +++ if (ret) +++ memcpy(dest, mac, 6); +++ +++ return ret; +++} +++ ++ void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) ++ { ++ if (soc_is_ar913x()) ++--- a/arch/mips/ath79/dev-wmac.h +++++ b/arch/mips/ath79/dev-wmac.h ++@@ -14,5 +14,6 @@ ++ ++ void ath79_register_wmac(u8 *cal_data, u8 *mac_addr); ++ void ath79_register_wmac_simple(void); +++bool ar93xx_wmac_read_mac_address(u8 *dest); ++ ++ #endif /* _ATH79_DEV_WMAC_H */ ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -112,6 +112,14 @@ ++ #define QCA955X_EHCI1_BASE 0x1b400000 ++ #define QCA955X_EHCI_SIZE 0x1000 ++ +++#define AR9300_OTP_BASE 0x14000 +++#define AR9300_OTP_STATUS 0x15f18 +++#define AR9300_OTP_STATUS_TYPE 0x7 +++#define AR9300_OTP_STATUS_VALID 0x4 +++#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 +++#define AR9300_OTP_STATUS_SM_BUSY 0x1 +++#define AR9300_OTP_READ_DATA 0x15f1c +++ ++ /* ++ * DDR_CTRL block ++ */ ++@@ -149,6 +157,13 @@ ++ #define AR934X_DDR_REG_FLUSH_PCIE 0xa8 ++ #define AR934X_DDR_REG_FLUSH_WMAC 0xac ++ +++#define AR934X_OTP_BASE 0x30000 +++#define AR934X_OTP_STATUS 0x31018 +++#define AR934X_OTP_READ_DATA 0x3101c +++#define AR934X_OTP_INTF2_ADDRESS 0x31008 +++#define AR934X_OTP_INTF3_ADDRESS 0x3100c +++#define AR934X_OTP_PGENB_SETUP_HOLD_TIME_ADDRESS 0x31034 +++ ++ /* ++ * PLL block ++ */ +diff --git a/target/linux/ar71xx/patches-4.14/524-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch b/target/linux/ar71xx/patches-4.14/524-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch +new file mode 100644 +index 0000000000..91e037e247 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/524-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch +@@ -0,0 +1,31 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -309,6 +309,16 @@ bool __init ar93xx_wmac_read_mac_address ++ return ret; ++ } ++ +++void __init ath79_wmac_disable_2ghz(void) +++{ +++ ath79_wmac_data.disable_2ghz = true; +++} +++ +++void __init ath79_wmac_disable_5ghz(void) +++{ +++ ath79_wmac_data.disable_5ghz = true; +++} +++ ++ void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) ++ { ++ if (soc_is_ar913x()) ++--- a/arch/mips/ath79/dev-wmac.h +++++ b/arch/mips/ath79/dev-wmac.h ++@@ -14,6 +14,9 @@ ++ ++ void ath79_register_wmac(u8 *cal_data, u8 *mac_addr); ++ void ath79_register_wmac_simple(void); +++void ath79_wmac_disable_2ghz(void); +++void ath79_wmac_disable_5ghz(void); +++ ++ bool ar93xx_wmac_read_mac_address(u8 *dest); ++ ++ #endif /* _ATH79_DEV_WMAC_H */ +diff --git a/target/linux/ar71xx/patches-4.14/525-MIPS-ath79-enable-qca-usb-quirks.patch b/target/linux/ar71xx/patches-4.14/525-MIPS-ath79-enable-qca-usb-quirks.patch +new file mode 100644 +index 0000000000..3cafbe290c +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/525-MIPS-ath79-enable-qca-usb-quirks.patch +@@ -0,0 +1,101 @@ ++--- a/arch/mips/ath79/dev-usb.c +++++ b/arch/mips/ath79/dev-usb.c ++@@ -37,6 +37,8 @@ static struct usb_ehci_pdata ath79_ehci_ ++ static struct usb_ehci_pdata ath79_ehci_pdata_v2 = { ++ .caps_offset = 0x100, ++ .has_tt = 1, +++ .qca_force_host_mode = 1, +++ .qca_force_16bit_ptw = 1, ++ }; ++ ++ static void __init ath79_usb_register(const char *name, int id, ++@@ -159,6 +161,9 @@ static void __init ar913x_usb_setup(void ++ ath79_device_reset_clear(AR913X_RESET_USB_PHY); ++ mdelay(10); ++ +++ ath79_ehci_pdata_v2.qca_force_host_mode = 0; +++ ath79_ehci_pdata_v2.qca_force_16bit_ptw = 0; +++ ++ ath79_usb_register("ehci-platform", -1, ++ AR913X_EHCI_BASE, AR913X_EHCI_SIZE, ++ ATH79_CPU_IRQ(3), ++@@ -182,14 +187,34 @@ static void __init ar933x_usb_setup(void ++ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); ++ } ++ ++-static void __init ar934x_usb_setup(void) +++static void enable_tx_tx_idp_violation_fix(unsigned base) ++ { ++- u32 bootstrap; +++ void __iomem *phy_reg; +++ u32 t; +++ +++ phy_reg = ioremap(base, 4); +++ if (!phy_reg) +++ return; +++ +++ t = ioread32(phy_reg); +++ t &= ~0xff; +++ t |= 0x58; +++ iowrite32(t, phy_reg); +++ +++ iounmap(phy_reg); +++} ++ ++- bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); ++- if (bootstrap & AR934X_BOOTSTRAP_USB_MODE_DEVICE) +++static void ar934x_usb_reset_notifier(struct platform_device *pdev) +++{ +++ if (pdev->id != -1) ++ return; ++ +++ enable_tx_tx_idp_violation_fix(0x18116c94); +++ dev_info(&pdev->dev, "TX-TX IDP fix enabled\n"); +++} +++ +++static void __init ar934x_usb_setup(void) +++{ ++ ath79_device_reset_set(AR934X_RESET_USBSUS_OVERRIDE); ++ udelay(1000); ++ ++@@ -202,14 +227,40 @@ static void __init ar934x_usb_setup(void ++ ath79_device_reset_clear(AR934X_RESET_USB_HOST); ++ udelay(1000); ++ +++ if (ath79_soc_rev >= 3) +++ ath79_ehci_pdata_v2.reset_notifier = ar934x_usb_reset_notifier; +++ ++ ath79_usb_register("ehci-platform", -1, ++ AR934X_EHCI_BASE, AR934X_EHCI_SIZE, ++ ATH79_CPU_IRQ(3), ++ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); ++ } ++ +++static void qca955x_usb_reset_notifier(struct platform_device *pdev) +++{ +++ u32 base; +++ +++ switch (pdev->id) { +++ case 0: +++ base = 0x18116d94; +++ break; +++ +++ case 1: +++ base = 0x18116e54; +++ break; +++ +++ default: +++ return; +++ } +++ +++ enable_tx_tx_idp_violation_fix(base); +++ dev_info(&pdev->dev, "TX-TX IDP fix enabled\n"); +++} +++ ++ static void __init qca955x_usb_setup(void) ++ { +++ ath79_ehci_pdata_v2.reset_notifier = qca955x_usb_reset_notifier; +++ ++ ath79_usb_register("ehci-platform", 0, ++ QCA955X_EHCI0_BASE, QCA955X_EHCI_SIZE, ++ ATH79_IP3_IRQ(0), +diff --git a/target/linux/ar71xx/patches-4.14/601-MIPS-ath79-add-more-register-defines.patch b/target/linux/ar71xx/patches-4.14/601-MIPS-ath79-add-more-register-defines.patch +new file mode 100644 +index 0000000000..d0f5b78901 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/601-MIPS-ath79-add-more-register-defines.patch +@@ -0,0 +1,455 @@ ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -20,6 +20,10 @@ ++ #include ++ ++ #define AR71XX_APB_BASE 0x18000000 +++#define AR71XX_GE0_BASE 0x19000000 +++#define AR71XX_GE0_SIZE 0x10000 +++#define AR71XX_GE1_BASE 0x1a000000 +++#define AR71XX_GE1_SIZE 0x10000 ++ #define AR71XX_EHCI_BASE 0x1b000000 ++ #define AR71XX_EHCI_SIZE 0x1000 ++ #define AR71XX_OHCI_BASE 0x1c000000 ++@@ -39,6 +43,8 @@ ++ #define AR71XX_PLL_SIZE 0x100 ++ #define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000) ++ #define AR71XX_RESET_SIZE 0x100 +++#define AR71XX_MII_BASE (AR71XX_APB_BASE + 0x00070000) +++#define AR71XX_MII_SIZE 0x100 ++ ++ #define AR71XX_PCI_MEM_BASE 0x10000000 ++ #define AR71XX_PCI_MEM_SIZE 0x07000000 ++@@ -81,15 +87,21 @@ ++ ++ #define AR933X_UART_BASE (AR71XX_APB_BASE + 0x00020000) ++ #define AR933X_UART_SIZE 0x14 +++#define AR933X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +++#define AR933X_GMAC_SIZE 0x04 ++ #define AR933X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) ++ #define AR933X_WMAC_SIZE 0x20000 ++ #define AR933X_EHCI_BASE 0x1b000000 ++ #define AR933X_EHCI_SIZE 0x1000 ++ +++#define AR934X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +++#define AR934X_GMAC_SIZE 0x14 ++ #define AR934X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) ++ #define AR934X_WMAC_SIZE 0x20000 ++ #define AR934X_EHCI_BASE 0x1b000000 ++ #define AR934X_EHCI_SIZE 0x200 +++#define AR934X_NFC_BASE 0x1b000200 +++#define AR934X_NFC_SIZE 0xb8 ++ #define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) ++ #define AR934X_SRIF_SIZE 0x1000 ++ ++@@ -106,11 +118,15 @@ ++ #define QCA955X_PCI_CTRL_BASE1 (AR71XX_APB_BASE + 0x00280000) ++ #define QCA955X_PCI_CTRL_SIZE 0x100 ++ +++#define QCA955X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +++#define QCA955X_GMAC_SIZE 0x40 ++ #define QCA955X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) ++ #define QCA955X_WMAC_SIZE 0x20000 ++ #define QCA955X_EHCI0_BASE 0x1b000000 ++ #define QCA955X_EHCI1_BASE 0x1b400000 ++ #define QCA955X_EHCI_SIZE 0x1000 +++#define QCA955X_NFC_BASE 0x1b800200 +++#define QCA955X_NFC_SIZE 0xb8 ++ ++ #define AR9300_OTP_BASE 0x14000 ++ #define AR9300_OTP_STATUS 0x15f18 ++@@ -181,6 +197,9 @@ ++ #define AR71XX_AHB_DIV_SHIFT 20 ++ #define AR71XX_AHB_DIV_MASK 0x7 ++ +++#define AR71XX_ETH0_PLL_SHIFT 17 +++#define AR71XX_ETH1_PLL_SHIFT 19 +++ ++ #define AR724X_PLL_REG_CPU_CONFIG 0x00 ++ #define AR724X_PLL_REG_PCIE_CONFIG 0x10 ++ ++@@ -196,6 +215,8 @@ ++ #define AR724X_DDR_DIV_SHIFT 22 ++ #define AR724X_DDR_DIV_MASK 0x3 ++ +++#define AR7242_PLL_REG_ETH0_INT_CLOCK 0x2c +++ ++ #define AR913X_PLL_REG_CPU_CONFIG 0x00 ++ #define AR913X_PLL_REG_ETH_CONFIG 0x04 ++ #define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14 ++@@ -208,6 +229,9 @@ ++ #define AR913X_AHB_DIV_SHIFT 19 ++ #define AR913X_AHB_DIV_MASK 0x1 ++ +++#define AR913X_ETH0_PLL_SHIFT 20 +++#define AR913X_ETH1_PLL_SHIFT 22 +++ ++ #define AR933X_PLL_CPU_CONFIG_REG 0x00 ++ #define AR933X_PLL_CLOCK_CTRL_REG 0x08 ++ ++@@ -229,6 +253,8 @@ ++ #define AR934X_PLL_CPU_CONFIG_REG 0x00 ++ #define AR934X_PLL_DDR_CONFIG_REG 0x04 ++ #define AR934X_PLL_CPU_DDR_CLK_CTRL_REG 0x08 +++#define AR934X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 +++#define AR934X_PLL_ETH_XMII_CONTROL_REG 0x2c ++ ++ #define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 ++ #define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f ++@@ -261,9 +287,13 @@ ++ #define AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) ++ #define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) ++ +++#define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL BIT(6) +++ ++ #define QCA955X_PLL_CPU_CONFIG_REG 0x00 ++ #define QCA955X_PLL_DDR_CONFIG_REG 0x04 ++ #define QCA955X_PLL_CLK_CTRL_REG 0x08 +++#define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28 +++#define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48 ++ ++ #define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 ++ #define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f ++@@ -388,16 +418,83 @@ ++ #define AR913X_RESET_USB_HOST BIT(5) ++ #define AR913X_RESET_USB_PHY BIT(4) ++ +++#define AR933X_RESET_GE1_MDIO BIT(23) +++#define AR933X_RESET_GE0_MDIO BIT(22) +++#define AR933X_RESET_GE1_MAC BIT(13) ++ #define AR933X_RESET_WMAC BIT(11) +++#define AR933X_RESET_GE0_MAC BIT(9) ++ #define AR933X_RESET_USB_HOST BIT(5) ++ #define AR933X_RESET_USB_PHY BIT(4) ++ #define AR933X_RESET_USBSUS_OVERRIDE BIT(3) ++ +++#define AR934X_RESET_HOST BIT(31) +++#define AR934X_RESET_SLIC BIT(30) +++#define AR934X_RESET_HDMA BIT(29) +++#define AR934X_RESET_EXTERNAL BIT(28) +++#define AR934X_RESET_RTC BIT(27) +++#define AR934X_RESET_PCIE_EP_INT BIT(26) +++#define AR934X_RESET_CHKSUM_ACC BIT(25) +++#define AR934X_RESET_FULL_CHIP BIT(24) +++#define AR934X_RESET_GE1_MDIO BIT(23) +++#define AR934X_RESET_GE0_MDIO BIT(22) +++#define AR934X_RESET_CPU_NMI BIT(21) +++#define AR934X_RESET_CPU_COLD BIT(20) +++#define AR934X_RESET_HOST_RESET_INT BIT(19) +++#define AR934X_RESET_PCIE_EP BIT(18) +++#define AR934X_RESET_UART1 BIT(17) +++#define AR934X_RESET_DDR BIT(16) +++#define AR934X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +++#define AR934X_RESET_NANDF BIT(14) +++#define AR934X_RESET_GE1_MAC BIT(13) +++#define AR934X_RESET_ETH_SWITCH_ANALOG BIT(12) ++ #define AR934X_RESET_USB_PHY_ANALOG BIT(11) +++#define AR934X_RESET_HOST_DMA_INT BIT(10) +++#define AR934X_RESET_GE0_MAC BIT(9) +++#define AR934X_RESET_ETH_SWITCH BIT(8) +++#define AR934X_RESET_PCIE_PHY BIT(7) +++#define AR934X_RESET_PCIE BIT(6) ++ #define AR934X_RESET_USB_HOST BIT(5) ++ #define AR934X_RESET_USB_PHY BIT(4) ++ #define AR934X_RESET_USBSUS_OVERRIDE BIT(3) +++#define AR934X_RESET_LUT BIT(2) +++#define AR934X_RESET_MBOX BIT(1) +++#define AR934X_RESET_I2S BIT(0) +++ +++#define QCA955X_RESET_HOST BIT(31) +++#define QCA955X_RESET_SLIC BIT(30) +++#define QCA955X_RESET_HDMA BIT(29) +++#define QCA955X_RESET_EXTERNAL BIT(28) +++#define QCA955X_RESET_RTC BIT(27) +++#define QCA955X_RESET_PCIE_EP_INT BIT(26) +++#define QCA955X_RESET_CHKSUM_ACC BIT(25) +++#define QCA955X_RESET_FULL_CHIP BIT(24) +++#define QCA955X_RESET_GE1_MDIO BIT(23) +++#define QCA955X_RESET_GE0_MDIO BIT(22) +++#define QCA955X_RESET_CPU_NMI BIT(21) +++#define QCA955X_RESET_CPU_COLD BIT(20) +++#define QCA955X_RESET_HOST_RESET_INT BIT(19) +++#define QCA955X_RESET_PCIE_EP BIT(18) +++#define QCA955X_RESET_UART1 BIT(17) +++#define QCA955X_RESET_DDR BIT(16) +++#define QCA955X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +++#define QCA955X_RESET_NANDF BIT(14) +++#define QCA955X_RESET_GE1_MAC BIT(13) +++#define QCA955X_RESET_SGMII_ANALOG BIT(12) +++#define QCA955X_RESET_USB_PHY_ANALOG BIT(11) +++#define QCA955X_RESET_HOST_DMA_INT BIT(10) +++#define QCA955X_RESET_GE0_MAC BIT(9) +++#define QCA955X_RESET_SGMII BIT(8) +++#define QCA955X_RESET_PCIE_PHY BIT(7) +++#define QCA955X_RESET_PCIE BIT(6) +++#define QCA955X_RESET_USB_HOST BIT(5) +++#define QCA955X_RESET_USB_PHY BIT(4) +++#define QCA955X_RESET_USBSUS_OVERRIDE BIT(3) +++#define QCA955X_RESET_LUT BIT(2) +++#define QCA955X_RESET_MBOX BIT(1) +++#define QCA955X_RESET_I2S BIT(0) ++ +++#define AR933X_BOOTSTRAP_MDIO_GPIO_EN BIT(18) +++#define AR933X_BOOTSTRAP_EEPBUSY BIT(4) ++ #define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0) ++ ++ #define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23) ++@@ -539,8 +636,22 @@ ++ #define AR71XX_GPIO_REG_INT_ENABLE 0x24 ++ #define AR71XX_GPIO_REG_FUNC 0x28 ++ +++#define AR934X_GPIO_REG_OUT_FUNC0 0x2c +++#define AR934X_GPIO_REG_OUT_FUNC1 0x30 +++#define AR934X_GPIO_REG_OUT_FUNC2 0x34 +++#define AR934X_GPIO_REG_OUT_FUNC3 0x38 +++#define AR934X_GPIO_REG_OUT_FUNC4 0x3c +++#define AR934X_GPIO_REG_OUT_FUNC5 0x40 ++ #define AR934X_GPIO_REG_FUNC 0x6c ++ +++#define QCA955X_GPIO_REG_OUT_FUNC0 0x2c +++#define QCA955X_GPIO_REG_OUT_FUNC1 0x30 +++#define QCA955X_GPIO_REG_OUT_FUNC2 0x34 +++#define QCA955X_GPIO_REG_OUT_FUNC3 0x38 +++#define QCA955X_GPIO_REG_OUT_FUNC4 0x3c +++#define QCA955X_GPIO_REG_OUT_FUNC5 0x40 +++#define QCA955X_GPIO_REG_FUNC 0x6c +++ ++ #define AR71XX_GPIO_COUNT 16 ++ #define AR7240_GPIO_COUNT 18 ++ #define AR7241_GPIO_COUNT 20 ++@@ -570,4 +681,235 @@ ++ #define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 ++ #define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 ++ +++#define AR71XX_GPIO_FUNC_STEREO_EN BIT(17) +++#define AR71XX_GPIO_FUNC_SLIC_EN BIT(16) +++#define AR71XX_GPIO_FUNC_SPI_CS2_EN BIT(13) +++#define AR71XX_GPIO_FUNC_SPI_CS1_EN BIT(12) +++#define AR71XX_GPIO_FUNC_UART_EN BIT(8) +++#define AR71XX_GPIO_FUNC_USB_OC_EN BIT(4) +++#define AR71XX_GPIO_FUNC_USB_CLK_EN BIT(0) +++ +++#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN BIT(19) +++#define AR724X_GPIO_FUNC_SPI_EN BIT(18) +++#define AR724X_GPIO_FUNC_SPI_CS_EN2 BIT(14) +++#define AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13) +++#define AR724X_GPIO_FUNC_CLK_OBS5_EN BIT(12) +++#define AR724X_GPIO_FUNC_CLK_OBS4_EN BIT(11) +++#define AR724X_GPIO_FUNC_CLK_OBS3_EN BIT(10) +++#define AR724X_GPIO_FUNC_CLK_OBS2_EN BIT(9) +++#define AR724X_GPIO_FUNC_CLK_OBS1_EN BIT(8) +++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) +++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) +++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) +++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) +++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) +++#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) +++#define AR724X_GPIO_FUNC_UART_EN BIT(1) +++#define AR724X_GPIO_FUNC_JTAG_DISABLE BIT(0) +++ +++#define AR913X_GPIO_FUNC_WMAC_LED_EN BIT(22) +++#define AR913X_GPIO_FUNC_EXP_PORT_CS_EN BIT(21) +++#define AR913X_GPIO_FUNC_I2S_REFCLKEN BIT(20) +++#define AR913X_GPIO_FUNC_I2S_MCKEN BIT(19) +++#define AR913X_GPIO_FUNC_I2S1_EN BIT(18) +++#define AR913X_GPIO_FUNC_I2S0_EN BIT(17) +++#define AR913X_GPIO_FUNC_SLIC_EN BIT(16) +++#define AR913X_GPIO_FUNC_UART_RTSCTS_EN BIT(9) +++#define AR913X_GPIO_FUNC_UART_EN BIT(8) +++#define AR913X_GPIO_FUNC_USB_CLK_EN BIT(4) +++ +++#define AR933X_GPIO_FUNC_SPDIF2TCK BIT(31) +++#define AR933X_GPIO_FUNC_SPDIF_EN BIT(30) +++#define AR933X_GPIO_FUNC_I2SO_22_18_EN BIT(29) +++#define AR933X_GPIO_FUNC_I2S_MCK_EN BIT(27) +++#define AR933X_GPIO_FUNC_I2SO_EN BIT(26) +++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_DUPL BIT(25) +++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_COLL BIT(24) +++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_ACT BIT(23) +++#define AR933X_GPIO_FUNC_SPI_EN BIT(18) +++#define AR933X_GPIO_FUNC_SPI_CS_EN2 BIT(14) +++#define AR933X_GPIO_FUNC_SPI_CS_EN1 BIT(13) +++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) +++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) +++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) +++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) +++#define AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) +++#define AR933X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) +++#define AR933X_GPIO_FUNC_UART_EN BIT(1) +++#define AR933X_GPIO_FUNC_JTAG_DISABLE BIT(0) +++ +++#define AR934X_GPIO_FUNC_CLK_OBS7_EN BIT(9) +++#define AR934X_GPIO_FUNC_CLK_OBS6_EN BIT(8) +++#define AR934X_GPIO_FUNC_CLK_OBS5_EN BIT(7) +++#define AR934X_GPIO_FUNC_CLK_OBS4_EN BIT(6) +++#define AR934X_GPIO_FUNC_CLK_OBS3_EN BIT(5) +++#define AR934X_GPIO_FUNC_CLK_OBS2_EN BIT(4) +++#define AR934X_GPIO_FUNC_CLK_OBS1_EN BIT(3) +++#define AR934X_GPIO_FUNC_CLK_OBS0_EN BIT(2) +++#define AR934X_GPIO_FUNC_JTAG_DISABLE BIT(1) +++ +++#define AR934X_GPIO_OUT_GPIO 0 +++#define AR934X_GPIO_OUT_SPI_CS1 7 +++#define AR934X_GPIO_OUT_LED_LINK0 41 +++#define AR934X_GPIO_OUT_LED_LINK1 42 +++#define AR934X_GPIO_OUT_LED_LINK2 43 +++#define AR934X_GPIO_OUT_LED_LINK3 44 +++#define AR934X_GPIO_OUT_LED_LINK4 45 +++#define AR934X_GPIO_OUT_EXT_LNA0 46 +++#define AR934X_GPIO_OUT_EXT_LNA1 47 +++ +++#define QCA955X_GPIO_FUNC_CLK_OBS7_EN BIT(9) +++#define QCA955X_GPIO_FUNC_CLK_OBS6_EN BIT(8) +++#define QCA955X_GPIO_FUNC_CLK_OBS5_EN BIT(7) +++#define QCA955X_GPIO_FUNC_CLK_OBS4_EN BIT(6) +++#define QCA955X_GPIO_FUNC_CLK_OBS3_EN BIT(5) +++#define QCA955X_GPIO_FUNC_CLK_OBS2_EN BIT(4) +++#define QCA955X_GPIO_FUNC_CLK_OBS1_EN BIT(3) +++#define QCA955X_GPIO_FUNC_JTAG_DISABLE BIT(1) +++ +++#define QCA955X_GPIO_OUT_GPIO 0 +++#define QCA955X_MII_EXT_MDI 1 +++#define QCA955X_SLIC_DATA_OUT 3 +++#define QCA955X_SLIC_PCM_FS 4 +++#define QCA955X_SLIC_PCM_CLK 5 +++#define QCA955X_SPI_CLK 8 +++#define QCA955X_SPI_CS_0 9 +++#define QCA955X_SPI_CS_1 10 +++#define QCA955X_SPI_CS_2 11 +++#define QCA955X_SPI_MISO 12 +++#define QCA955X_I2S_CLK 13 +++#define QCA955X_I2S_WS 14 +++#define QCA955X_I2S_SD 15 +++#define QCA955X_I2S_MCK 16 +++#define QCA955X_SPDIF_OUT 17 +++#define QCA955X_UART1_TD 18 +++#define QCA955X_UART1_RTS 19 +++#define QCA955X_UART1_RD 20 +++#define QCA955X_UART1_CTS 21 +++#define QCA955X_UART0_SOUT 22 +++#define QCA955X_SPDIF2_OUT 23 +++#define QCA955X_LED_SGMII_SPEED0 24 +++#define QCA955X_LED_SGMII_SPEED1 25 +++#define QCA955X_LED_SGMII_DUPLEX 26 +++#define QCA955X_LED_SGMII_LINK_UP 27 +++#define QCA955X_SGMII_SPEED0_INVERT 28 +++#define QCA955X_SGMII_SPEED1_INVERT 29 +++#define QCA955X_SGMII_DUPLEX_INVERT 30 +++#define QCA955X_SGMII_LINK_UP_INVERT 31 +++#define QCA955X_GE1_MII_MDO 32 +++#define QCA955X_GE1_MII_MDC 33 +++#define QCA955X_SWCOM2 38 +++#define QCA955X_SWCOM3 39 +++#define QCA955X_MAC2_GPIO 40 +++#define QCA955X_MAC3_GPIO 41 +++#define QCA955X_ATT_LED 42 +++#define QCA955X_PWR_LED 43 +++#define QCA955X_TX_FRAME 44 +++#define QCA955X_RX_CLEAR_EXTERNAL 45 +++#define QCA955X_LED_NETWORK_EN 46 +++#define QCA955X_LED_POWER_EN 47 +++#define QCA955X_WMAC_GLUE_WOW 68 +++#define QCA955X_RX_CLEAR_EXTENSION 70 +++#define QCA955X_CP_NAND_CS1 73 +++#define QCA955X_USB_SUSPEND 74 +++#define QCA955X_ETH_TX_ERR 75 +++#define QCA955X_DDR_DQ_OE 76 +++#define QCA955X_CLKREQ_N_EP 77 +++#define QCA955X_CLKREQ_N_RC 78 +++#define QCA955X_CLK_OBS0 79 +++#define QCA955X_CLK_OBS1 80 +++#define QCA955X_CLK_OBS2 81 +++#define QCA955X_CLK_OBS3 82 +++#define QCA955X_CLK_OBS4 83 +++#define QCA955X_CLK_OBS5 84 +++ +++/* +++ * MII_CTRL block +++ */ +++#define AR71XX_MII_REG_MII0_CTRL 0x00 +++#define AR71XX_MII_REG_MII1_CTRL 0x04 +++ +++#define AR71XX_MII_CTRL_IF_MASK 3 +++#define AR71XX_MII_CTRL_SPEED_SHIFT 4 +++#define AR71XX_MII_CTRL_SPEED_MASK 3 +++#define AR71XX_MII_CTRL_SPEED_10 0 +++#define AR71XX_MII_CTRL_SPEED_100 1 +++#define AR71XX_MII_CTRL_SPEED_1000 2 +++ +++#define AR71XX_MII0_CTRL_IF_GMII 0 +++#define AR71XX_MII0_CTRL_IF_MII 1 +++#define AR71XX_MII0_CTRL_IF_RGMII 2 +++#define AR71XX_MII0_CTRL_IF_RMII 3 +++ +++#define AR71XX_MII1_CTRL_IF_RGMII 0 +++#define AR71XX_MII1_CTRL_IF_RMII 1 +++ +++/* +++ * AR933X GMAC interface +++ */ +++#define AR933X_GMAC_REG_ETH_CFG 0x00 +++ +++#define AR933X_ETH_CFG_RGMII_GE0 BIT(0) +++#define AR933X_ETH_CFG_MII_GE0 BIT(1) +++#define AR933X_ETH_CFG_GMII_GE0 BIT(2) +++#define AR933X_ETH_CFG_MII_GE0_MASTER BIT(3) +++#define AR933X_ETH_CFG_MII_GE0_SLAVE BIT(4) +++#define AR933X_ETH_CFG_MII_GE0_ERR_EN BIT(5) +++#define AR933X_ETH_CFG_SW_PHY_SWAP BIT(7) +++#define AR933X_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8) +++#define AR933X_ETH_CFG_RMII_GE0 BIT(9) +++#define AR933X_ETH_CFG_RMII_GE0_SPD_10 0 +++#define AR933X_ETH_CFG_RMII_GE0_SPD_100 BIT(10) +++ +++/* +++ * AR934X GMAC Interface +++ */ +++#define AR934X_GMAC_REG_ETH_CFG 0x00 +++ +++#define AR934X_ETH_CFG_RGMII_GMAC0 BIT(0) +++#define AR934X_ETH_CFG_MII_GMAC0 BIT(1) +++#define AR934X_ETH_CFG_GMII_GMAC0 BIT(2) +++#define AR934X_ETH_CFG_MII_GMAC0_MASTER BIT(3) +++#define AR934X_ETH_CFG_MII_GMAC0_SLAVE BIT(4) +++#define AR934X_ETH_CFG_MII_GMAC0_ERR_EN BIT(5) +++#define AR934X_ETH_CFG_SW_ONLY_MODE BIT(6) +++#define AR934X_ETH_CFG_SW_PHY_SWAP BIT(7) +++#define AR934X_ETH_CFG_SW_APB_ACCESS BIT(9) +++#define AR934X_ETH_CFG_RMII_GMAC0 BIT(10) +++#define AR933X_ETH_CFG_MII_CNTL_SPEED BIT(11) +++#define AR934X_ETH_CFG_RMII_GMAC0_MASTER BIT(12) +++#define AR933X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) +++#define AR934X_ETH_CFG_RXD_DELAY BIT(14) +++#define AR934X_ETH_CFG_RXD_DELAY_MASK 0x3 +++#define AR934X_ETH_CFG_RXD_DELAY_SHIFT 14 +++#define AR934X_ETH_CFG_RDV_DELAY BIT(16) +++#define AR934X_ETH_CFG_RDV_DELAY_MASK 0x3 +++#define AR934X_ETH_CFG_RDV_DELAY_SHIFT 16 +++ +++/* +++ * QCA955X GMAC Interface +++ */ +++ +++#define QCA955X_GMAC_REG_ETH_CFG 0x00 +++ +++#define QCA955X_ETH_CFG_RGMII_EN BIT(0) +++#define QCA955X_ETH_CFG_MII_GE0 BIT(1) +++#define QCA955X_ETH_CFG_GMII_GE0 BIT(2) +++#define QCA955X_ETH_CFG_MII_GE0_MASTER BIT(3) +++#define QCA955X_ETH_CFG_MII_GE0_SLAVE BIT(4) +++#define QCA955X_ETH_CFG_GE0_ERR_EN BIT(5) +++#define QCA955X_ETH_CFG_GE0_SGMII BIT(6) +++#define QCA955X_ETH_CFG_RMII_GE0 BIT(10) +++#define QCA955X_ETH_CFG_MII_CNTL_SPEED BIT(11) +++#define QCA955X_ETH_CFG_RMII_GE0_MASTER BIT(12) +++#define QCA955X_ETH_CFG_RXD_DELAY_MASK 0x3 +++#define QCA955X_ETH_CFG_RXD_DELAY_SHIFT 14 +++#define QCA955X_ETH_CFG_RDV_DELAY BIT(16) +++#define QCA955X_ETH_CFG_RDV_DELAY_MASK 0x3 +++#define QCA955X_ETH_CFG_RDV_DELAY_SHIFT 16 +++#define QCA955X_ETH_CFG_TXD_DELAY_MASK 0x3 +++#define QCA955X_ETH_CFG_TXD_DELAY_SHIFT 18 +++#define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3 +++#define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20 +++ ++ #endif /* __ASM_MACH_AR71XX_REGS_H */ +diff --git a/target/linux/ar71xx/patches-4.14/602-MIPS-ath79-add-openwrt-stuff.patch b/target/linux/ar71xx/patches-4.14/602-MIPS-ath79-add-openwrt-stuff.patch +new file mode 100644 +index 0000000000..047be0c7fd +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/602-MIPS-ath79-add-openwrt-stuff.patch +@@ -0,0 +1,49 @@ ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -99,6 +99,20 @@ config SOC_QCA955X ++ select PCI_AR724X if PCI ++ def_bool n ++ +++config ATH79_DEV_M25P80 +++ select ATH79_DEV_SPI +++ def_bool n +++ +++config ATH79_DEV_AP9X_PCI +++ select ATH79_PCI_ATH9K_FIXUP +++ def_bool n +++ +++config ATH79_DEV_DSA +++ def_bool n +++ +++config ATH79_DEV_ETH +++ def_bool n +++ ++ config PCI_AR724X ++ def_bool n ++ ++@@ -108,6 +122,10 @@ config ATH79_DEV_GPIO_BUTTONS ++ config ATH79_DEV_LEDS_GPIO ++ def_bool n ++ +++config ATH79_DEV_NFC +++ depends on (SOC_AR934X || SOC_QCA955X) +++ def_bool n +++ ++ config ATH79_DEV_SPI ++ def_bool n ++ ++@@ -118,4 +136,14 @@ config ATH79_DEV_WMAC ++ depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA955X) ++ def_bool n ++ +++config ATH79_NVRAM +++ def_bool n +++ +++config ATH79_PCI_ATH9K_FIXUP +++ def_bool n +++ +++config ATH79_ROUTERBOOT +++ select LZO_DECOMPRESS +++ def_bool n +++ ++ endif +diff --git a/target/linux/ar71xx/patches-4.14/603-MIPS-ath79-ap121-fixes.patch b/target/linux/ar71xx/patches-4.14/603-MIPS-ath79-ap121-fixes.patch +new file mode 100644 +index 0000000000..672f38e938 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/603-MIPS-ath79-ap121-fixes.patch +@@ -0,0 +1,149 @@ ++--- a/arch/mips/ath79/mach-ap121.c +++++ b/arch/mips/ath79/mach-ap121.c ++@@ -1,19 +1,21 @@ ++ /* ++ * Atheros AP121 board support ++ * ++- * Copyright (C) 2011 Gabor Juhos +++ * Copyright (C) 2011-2012 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. ++ */ ++ ++-#include "machtypes.h" +++#include "dev-eth.h" ++ #include "dev-gpio-buttons.h" ++ #include "dev-leds-gpio.h" +++#include "dev-m25p80.h" ++ #include "dev-spi.h" ++ #include "dev-usb.h" ++ #include "dev-wmac.h" +++#include "machtypes.h" ++ ++ #define AP121_GPIO_LED_WLAN 0 ++ #define AP121_GPIO_LED_USB 1 ++@@ -24,7 +26,14 @@ ++ #define AP121_KEYS_POLL_INTERVAL 20 /* msecs */ ++ #define AP121_KEYS_DEBOUNCE_INTERVAL (3 * AP121_KEYS_POLL_INTERVAL) ++ ++-#define AP121_CAL_DATA_ADDR 0x1fff1000 +++#define AP121_MAC0_OFFSET 0x0000 +++#define AP121_MAC1_OFFSET 0x0006 +++#define AP121_CALDATA_OFFSET 0x1000 +++#define AP121_WMAC_MAC_OFFSET 0x1002 +++ +++#define AP121_MINI_GPIO_LED_WLAN 0 +++#define AP121_MINI_GPIO_BTN_JUMPSTART 12 +++#define AP121_MINI_GPIO_BTN_RESET 11 ++ ++ static struct gpio_led ap121_leds_gpio[] __initdata = { ++ { ++@@ -58,35 +67,78 @@ static struct gpio_keys_button ap121_gpi ++ } ++ }; ++ ++-static struct spi_board_info ap121_spi_info[] = { +++static struct gpio_led ap121_mini_leds_gpio[] __initdata = { ++ { ++- .bus_num = 0, ++- .chip_select = 0, ++- .max_speed_hz = 25000000, ++- .modalias = "mx25l1606e", ++- } +++ .name = "ap121:green:wlan", +++ .gpio = AP121_MINI_GPIO_LED_WLAN, +++ .active_low = 0, +++ }, ++ }; ++ ++-static struct ath79_spi_platform_data ap121_spi_data = { ++- .bus_num = 0, ++- .num_chipselect = 1, +++static struct gpio_keys_button ap121_mini_gpio_keys[] __initdata = { +++ { +++ .desc = "jumpstart button", +++ .type = EV_KEY, +++ .code = KEY_WPS_BUTTON, +++ .debounce_interval = AP121_KEYS_DEBOUNCE_INTERVAL, +++ .gpio = AP121_MINI_GPIO_BTN_JUMPSTART, +++ .active_low = 1, +++ }, +++ { +++ .desc = "reset button", +++ .type = EV_KEY, +++ .code = KEY_RESTART, +++ .debounce_interval = AP121_KEYS_DEBOUNCE_INTERVAL, +++ .gpio = AP121_MINI_GPIO_BTN_RESET, +++ .active_low = 1, +++ } ++ }; ++ +++static void __init ap121_common_setup(void) +++{ +++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); +++ +++ ath79_register_m25p80(NULL); +++ ath79_register_wmac(art + AP121_CALDATA_OFFSET, +++ art + AP121_WMAC_MAC_OFFSET); +++ +++ ath79_init_mac(ath79_eth0_data.mac_addr, art + AP121_MAC0_OFFSET, 0); +++ ath79_init_mac(ath79_eth1_data.mac_addr, art + AP121_MAC1_OFFSET, 0); +++ +++ ath79_register_mdio(0, 0x0); +++ +++ /* LAN ports */ +++ ath79_register_eth(1); +++ +++ /* WAN port */ +++ ath79_register_eth(0); +++} +++ ++ static void __init ap121_setup(void) ++ { ++- u8 *cal_data = (u8 *) KSEG1ADDR(AP121_CAL_DATA_ADDR); +++ ap121_common_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap121_leds_gpio), ++ ap121_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, AP121_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(ap121_gpio_keys), ++ ap121_gpio_keys); ++- ++- ath79_register_spi(&ap121_spi_data, ap121_spi_info, ++- ARRAY_SIZE(ap121_spi_info)); ++ ath79_register_usb(); ++- ath79_register_wmac(cal_data, NULL); ++ } ++ ++ MIPS_MACHINE(ATH79_MACH_AP121, "AP121", "Atheros AP121 reference board", ++ ap121_setup); +++ +++static void __init ap121_mini_setup(void) +++{ +++ ap121_common_setup(); +++ +++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap121_mini_leds_gpio), +++ ap121_mini_leds_gpio); +++ ath79_register_gpio_keys_polled(-1, AP121_KEYS_POLL_INTERVAL, +++ ARRAY_SIZE(ap121_mini_gpio_keys), +++ ap121_mini_gpio_keys); +++} +++ +++MIPS_MACHINE(ATH79_MACH_AP121_MINI, "AP121-MINI", "Atheros AP121-MINI", +++ ap121_mini_setup); ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -6,9 +6,10 @@ menu "Atheros AR71XX/AR724X/AR913X machi ++ config ATH79_MACH_AP121 ++ bool "Atheros AP121 reference board" ++ select SOC_AR933X +++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++- select ATH79_DEV_SPI +++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ help +diff --git a/target/linux/ar71xx/patches-4.14/604-MIPS-ath79-no-of.patch b/target/linux/ar71xx/patches-4.14/604-MIPS-ath79-no-of.patch +new file mode 100644 +index 0000000000..2e7d5d8232 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/604-MIPS-ath79-no-of.patch +@@ -0,0 +1,70 @@ ++--- a/arch/mips/Kconfig +++++ b/arch/mips/Kconfig ++@@ -203,7 +203,6 @@ config ATH79 ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select SYS_SUPPORTS_MIPS16 ++ select SYS_SUPPORTS_ZBOOT_UART_PROM ++- select USE_OF ++ help ++ Support for the Atheros AR71XX/AR724X/AR913X SoCs. ++ ++--- a/arch/mips/ath79/setup.c +++++ b/arch/mips/ath79/setup.c ++@@ -190,16 +190,20 @@ unsigned int get_c0_compare_int(void) ++ ++ void __init plat_mem_setup(void) ++ { +++#ifdef CONFIG_OF ++ unsigned long fdt_start; +++#endif ++ ++ set_io_port_base(KSEG1); ++ +++#ifdef CONFIG_OF ++ /* Get the position of the FDT passed by the bootloader */ ++ fdt_start = fw_getenvl("fdt_start"); ++ if (fdt_start) ++ __dt_setup_arch((void *)KSEG0ADDR(fdt_start)); ++ else if (fw_passed_dtb) ++ __dt_setup_arch((void *)KSEG0ADDR(fw_passed_dtb)); +++#endif ++ ++ if (mips_machtype != ATH79_MACH_GENERIC_OF) { ++ ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE, ++@@ -295,17 +299,21 @@ static int __init ath79_setup(void) ++ ++ arch_initcall(ath79_setup); ++ +++#ifdef CONFIG_OF ++ void __init device_tree_init(void) ++ { ++ unflatten_and_copy_device_tree(); ++ } +++#endif ++ ++ MIPS_MACHINE(ATH79_MACH_GENERIC, ++ "Generic", ++ "Generic AR71XX/AR724X/AR913X based board", ++ NULL); ++ +++#ifdef CONFIG_OF ++ MIPS_MACHINE(ATH79_MACH_GENERIC_OF, ++ "DTB", ++ "Generic AR71XX/AR724X/AR913X based board (DT)", ++ NULL); +++#endif ++--- a/arch/mips/ath79/clock.c +++++ b/arch/mips/ath79/clock.c ++@@ -32,10 +32,12 @@ ++ #define AR724X_BASE_FREQ 40000000 ++ ++ static struct clk *clks[ATH79_CLK_END]; +++#ifdef CONFIG_OF ++ static struct clk_onecell_data clk_data = { ++ .clks = clks, ++ .clk_num = ARRAY_SIZE(clks), ++ }; +++#endif ++ ++ static struct clk *__init ath79_add_sys_clkdev( ++ const char *id, unsigned long rate) +diff --git a/target/linux/ar71xx/patches-4.14/605-MIPS-ath79-db120-fixes.patch b/target/linux/ar71xx/patches-4.14/605-MIPS-ath79-db120-fixes.patch +new file mode 100644 +index 0000000000..44335f2ff7 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/605-MIPS-ath79-db120-fixes.patch +@@ -0,0 +1,204 @@ ++--- a/arch/mips/ath79/mach-db120.c +++++ b/arch/mips/ath79/mach-db120.c ++@@ -2,7 +2,7 @@ ++ * Atheros DB120 reference board support ++ * ++ * Copyright (c) 2011 Qualcomm Atheros ++- * Copyright (c) 2011 Gabor Juhos +++ * Copyright (c) 2011-2012 Gabor Juhos ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++@@ -19,16 +19,26 @@ ++ */ ++ ++ #include +++#include +++#include ++ #include +++#include ++ ++-#include "machtypes.h" +++#include +++ +++#include "common.h" +++#include "dev-ap9x-pci.h" +++#include "dev-eth.h" ++ #include "dev-gpio-buttons.h" ++ #include "dev-leds-gpio.h" +++#include "dev-m25p80.h" +++#include "dev-nfc.h" ++ #include "dev-spi.h" ++ #include "dev-usb.h" ++ #include "dev-wmac.h" ++-#include "pci.h" +++#include "machtypes.h" ++ +++#define DB120_GPIO_LED_USB 11 ++ #define DB120_GPIO_LED_WLAN_5G 12 ++ #define DB120_GPIO_LED_WLAN_2G 13 ++ #define DB120_GPIO_LED_STATUS 14 ++@@ -39,8 +49,10 @@ ++ #define DB120_KEYS_POLL_INTERVAL 20 /* msecs */ ++ #define DB120_KEYS_DEBOUNCE_INTERVAL (3 * DB120_KEYS_POLL_INTERVAL) ++ ++-#define DB120_WMAC_CALDATA_OFFSET 0x1000 ++-#define DB120_PCIE_CALDATA_OFFSET 0x5000 +++#define DB120_MAC0_OFFSET 0 +++#define DB120_MAC1_OFFSET 6 +++#define DB120_WMAC_CALDATA_OFFSET 0x1000 +++#define DB120_PCIE_CALDATA_OFFSET 0x5000 ++ ++ static struct gpio_led db120_leds_gpio[] __initdata = { ++ { ++@@ -63,6 +75,11 @@ static struct gpio_led db120_leds_gpio[] ++ .gpio = DB120_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, +++ { +++ .name = "db120:green:usb", +++ .gpio = DB120_GPIO_LED_USB, +++ .active_low = 1, +++ } ++ }; ++ ++ static struct gpio_keys_button db120_gpio_keys[] __initdata = { ++@@ -76,60 +93,85 @@ static struct gpio_keys_button db120_gpi ++ }, ++ }; ++ ++-static struct spi_board_info db120_spi_info[] = { ++- { ++- .bus_num = 0, ++- .chip_select = 0, ++- .max_speed_hz = 25000000, ++- .modalias = "s25sl064a", ++- } +++static struct ar8327_pad_cfg db120_ar8327_pad0_cfg = { +++ .mode = AR8327_PAD_MAC_RGMII, +++ .txclk_delay_en = true, +++ .rxclk_delay_en = true, +++ .txclk_delay_sel = AR8327_CLK_DELAY_SEL1, +++ .rxclk_delay_sel = AR8327_CLK_DELAY_SEL2, ++ }; ++ ++-static struct ath79_spi_platform_data db120_spi_data = { ++- .bus_num = 0, ++- .num_chipselect = 1, +++static struct ar8327_led_cfg db120_ar8327_led_cfg = { +++ .led_ctrl0 = 0x00000000, +++ .led_ctrl1 = 0xc737c737, +++ .led_ctrl2 = 0x00000000, +++ .led_ctrl3 = 0x00c30c00, +++ .open_drain = true, ++ }; ++ ++-#ifdef CONFIG_PCI ++-static struct ath9k_platform_data db120_ath9k_data; ++- ++-static int db120_pci_plat_dev_init(struct pci_dev *dev) ++-{ ++- switch (PCI_SLOT(dev->devfn)) { ++- case 0: ++- dev->dev.platform_data = &db120_ath9k_data; ++- break; ++- } ++- ++- return 0; ++-} ++- ++-static void __init db120_pci_init(u8 *eeprom) ++-{ ++- memcpy(db120_ath9k_data.eeprom_data, eeprom, ++- sizeof(db120_ath9k_data.eeprom_data)); +++static struct ar8327_platform_data db120_ar8327_data = { +++ .pad0_cfg = &db120_ar8327_pad0_cfg, +++ .port0_cfg = { +++ .force_link = 1, +++ .speed = AR8327_PORT_SPEED_1000, +++ .duplex = 1, +++ .txpause = 1, +++ .rxpause = 1, +++ }, +++ .led_cfg = &db120_ar8327_led_cfg, +++}; ++ ++- ath79_pci_set_plat_dev_init(db120_pci_plat_dev_init); ++- ath79_register_pci(); ++-} ++-#else ++-static inline void db120_pci_init(u8 *eeprom) {} ++-#endif /* CONFIG_PCI */ +++static struct mdio_board_info db120_mdio0_info[] = { +++ { +++ .bus_id = "ag71xx-mdio.0", +++ .mdio_addr = 0, +++ .platform_data = &db120_ar8327_data, +++ }, +++}; ++ ++ static void __init db120_setup(void) ++ { ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ +++ ath79_gpio_output_select(DB120_GPIO_LED_USB, AR934X_GPIO_OUT_GPIO); +++ ath79_register_m25p80(NULL); +++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(db120_leds_gpio), ++ db120_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, DB120_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(db120_gpio_keys), ++ db120_gpio_keys); ++- ath79_register_spi(&db120_spi_data, db120_spi_info, ++- ARRAY_SIZE(db120_spi_info)); ++ ath79_register_usb(); ++ ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET, NULL); ++- db120_pci_init(art + DB120_PCIE_CALDATA_OFFSET); +++ ap91_pci_init(art + DB120_PCIE_CALDATA_OFFSET, NULL); +++ +++ ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 | +++ AR934X_ETH_CFG_SW_ONLY_MODE); +++ +++ ath79_register_mdio(1, 0x0); +++ ath79_register_mdio(0, 0x0); +++ +++ ath79_init_mac(ath79_eth0_data.mac_addr, art + DB120_MAC0_OFFSET, 0); +++ +++ mdiobus_register_board_info(db120_mdio0_info, +++ ARRAY_SIZE(db120_mdio0_info)); +++ +++ /* GMAC0 is connected to an AR8327 switch */ +++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; +++ ath79_eth0_data.phy_mask = BIT(0); +++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; +++ ath79_eth0_pll_data.pll_1000 = 0x06000000; +++ ath79_register_eth(0); +++ +++ /* GMAC1 is connected to the internal switch */ +++ ath79_init_mac(ath79_eth1_data.mac_addr, art + DB120_MAC1_OFFSET, 0); +++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; +++ ath79_eth1_data.speed = SPEED_1000; +++ ath79_eth1_data.duplex = DUPLEX_FULL; +++ +++ ath79_register_eth(1); +++ +++ ath79_register_nfc(); ++ } ++ ++ MIPS_MACHINE(ATH79_MACH_DB120, "DB120", "Atheros DB120 reference board", ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -43,9 +43,12 @@ config ATH79_MACH_AP81 ++ config ATH79_MACH_DB120 ++ bool "Atheros DB120 reference board" ++ select SOC_AR934X +++ select ATH79_DEV_AP9X_PCI if PCI +++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++- select ATH79_DEV_SPI +++ select ATH79_DEV_M25P80 +++ select ATH79_DEV_NFC ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ help +diff --git a/target/linux/ar71xx/patches-4.14/606-MIPS-ath79-pb44-fixes.patch b/target/linux/ar71xx/patches-4.14/606-MIPS-ath79-pb44-fixes.patch +new file mode 100644 +index 0000000000..c9cb7e5c00 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/606-MIPS-ath79-pb44-fixes.patch +@@ -0,0 +1,144 @@ ++--- a/arch/mips/ath79/mach-pb44.c +++++ b/arch/mips/ath79/mach-pb44.c ++@@ -8,23 +8,47 @@ ++ * by the Free Software Foundation. ++ */ ++ +++#include ++ #include ++ #include ++ #include ++ #include ++ #include +++#include +++#include ++ ++ #include "machtypes.h" +++#include +++#include +++#include "dev-eth.h" ++ #include "dev-gpio-buttons.h" ++ #include "dev-leds-gpio.h" ++ #include "dev-spi.h" ++ #include "dev-usb.h" +++#include "machtypes.h" ++ #include "pci.h" ++ ++ #define PB44_GPIO_I2C_SCL 0 ++ #define PB44_GPIO_I2C_SDA 1 ++ +++#define PB44_PCF8757_VSC7395_CS 0 +++#define PB44_PCF8757_STEREO_CS 1 +++#define PB44_PCF8757_SLIC_CS0 2 +++#define PB44_PCF8757_SLIC_TEST 3 +++#define PB44_PCF8757_SLIC_INT0 4 +++#define PB44_PCF8757_SLIC_INT1 5 +++#define PB44_PCF8757_SW_RESET 6 +++#define PB44_PCF8757_SW_JUMP 8 +++#define PB44_PCF8757_LED_JUMP1 9 +++#define PB44_PCF8757_LED_JUMP2 10 +++#define PB44_PCF8757_TP24 11 +++#define PB44_PCF8757_TP25 12 +++#define PB44_PCF8757_TP26 13 +++#define PB44_PCF8757_TP27 14 +++#define PB44_PCF8757_TP28 15 +++ ++ #define PB44_GPIO_EXP_BASE 16 +++#define PB44_GPIO_VSC7395_CS (PB44_GPIO_EXP_BASE + PB44_PCF8757_VSC7395_CS) ++ #define PB44_GPIO_SW_RESET (PB44_GPIO_EXP_BASE + 6) ++ #define PB44_GPIO_SW_JUMP (PB44_GPIO_EXP_BASE + 8) ++ #define PB44_GPIO_LED_JUMP1 (PB44_GPIO_EXP_BASE + 9) ++@@ -87,20 +111,59 @@ static struct gpio_keys_button pb44_gpio ++ } ++ }; ++ +++static void pb44_vsc7395_reset(void) +++{ +++ ath79_device_reset_set(AR71XX_RESET_GE1_PHY); +++ udelay(10); +++ ath79_device_reset_clear(AR71XX_RESET_GE1_PHY); +++ mdelay(50); +++} +++ +++static struct vsc7385_platform_data pb44_vsc7395_data = { +++ .reset = pb44_vsc7395_reset, +++ .ucode_name = "vsc7395_ucode_pb44.bin", +++ .mac_cfg = { +++ .tx_ipg = 6, +++ .bit2 = 1, +++ .clk_sel = 0, +++ }, +++}; +++ +++static const char *pb44_part_probes[] = { +++ "RedBoot", +++ NULL, +++}; +++ +++static struct flash_platform_data pb44_flash_data = { +++ .part_probes = pb44_part_probes, +++}; +++ ++ static struct spi_board_info pb44_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p64", +++ .platform_data = &pb44_flash_data, ++ }, +++ { +++ .bus_num = 0, +++ .chip_select = 1, +++ .max_speed_hz = 25000000, +++ .modalias = "spi-vsc7385", +++ .platform_data = &pb44_vsc7395_data, +++ } ++ }; ++ ++ static struct ath79_spi_platform_data pb44_spi_data = { ++ .bus_num = 0, ++- .num_chipselect = 1, +++ .num_chipselect = 2, ++ }; ++ +++#define PB44_WAN_PHYMASK BIT(0) +++#define PB44_LAN_PHYMASK 0 +++#define PB44_MDIO_PHYMASK (PB44_LAN_PHYMASK | PB44_WAN_PHYMASK) +++ ++ static void __init pb44_init(void) ++ { ++ i2c_register_board_info(0, pb44_i2c_board_info, ++@@ -116,6 +179,22 @@ static void __init pb44_init(void) ++ ARRAY_SIZE(pb44_spi_info)); ++ ath79_register_usb(); ++ ath79_register_pci(); +++ +++ ath79_register_mdio(0, ~PB44_MDIO_PHYMASK); +++ +++ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); +++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; +++ ath79_eth0_data.phy_mask = PB44_WAN_PHYMASK; +++ +++ ath79_register_eth(0); +++ +++ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); +++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; +++ ath79_eth1_data.speed = SPEED_1000; +++ ath79_eth1_data.duplex = DUPLEX_FULL; +++ ath79_eth1_pll_data.pll_1000 = 0x110000; +++ +++ ath79_register_eth(1); ++ } ++ ++ MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board", ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -58,6 +58,7 @@ config ATH79_MACH_DB120 ++ config ATH79_MACH_PB44 ++ bool "Atheros PB44 reference board" ++ select SOC_AR71XX +++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_SPI +diff --git a/target/linux/ar71xx/patches-4.14/607-MIPS-ath79-ubnt-xm-fixes.patch b/target/linux/ar71xx/patches-4.14/607-MIPS-ath79-ubnt-xm-fixes.patch +new file mode 100644 +index 0000000000..4699c82746 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/607-MIPS-ath79-ubnt-xm-fixes.patch +@@ -0,0 +1,14 @@ ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -70,9 +70,10 @@ config ATH79_MACH_PB44 ++ config ATH79_MACH_UBNT_XM ++ bool "Ubiquiti Networks XM (rev 1.0) board" ++ select SOC_AR724X +++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++- select ATH79_DEV_SPI +++ select ATH79_DEV_M25P80 ++ help ++ Say 'Y' here if you want your kernel to support the ++ Ubiquiti Networks XM (rev 1.0) board. +diff --git a/target/linux/ar71xx/patches-4.14/608-MIPS-ath79-ubnt-xm-add-more-boards.patch b/target/linux/ar71xx/patches-4.14/608-MIPS-ath79-ubnt-xm-add-more-boards.patch +new file mode 100644 +index 0000000000..b33db4dd0d +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/608-MIPS-ath79-ubnt-xm-add-more-boards.patch +@@ -0,0 +1,20 @@ ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -68,12 +68,16 @@ config ATH79_MACH_PB44 ++ Atheros PB44 reference board. ++ ++ config ATH79_MACH_UBNT_XM ++- bool "Ubiquiti Networks XM (rev 1.0) board" +++ bool "Ubiquiti Networks XM/UniFi boards" ++ select SOC_AR724X +++ select SOC_AR934X ++ select ATH79_DEV_AP9X_PCI if PCI +++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 +++ select ATH79_DEV_USB +++ select ATH79_DEV_WMAC ++ help ++ Say 'Y' here if you want your kernel to support the ++ Ubiquiti Networks XM (rev 1.0) board. +diff --git a/target/linux/ar71xx/patches-4.14/609-MIPS-ath79-ap136-fixes.patch b/target/linux/ar71xx/patches-4.14/609-MIPS-ath79-ap136-fixes.patch +new file mode 100644 +index 0000000000..7f3a242cad +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/609-MIPS-ath79-ap136-fixes.patch +@@ -0,0 +1,300 @@ ++--- a/arch/mips/ath79/mach-ap136.c +++++ b/arch/mips/ath79/mach-ap136.c ++@@ -18,23 +18,29 @@ ++ * ++ */ ++ ++-#include ++-#include +++#include +++#include ++ ++-#include "machtypes.h" +++#include +++ +++#include "common.h" +++#include "pci.h" +++#include "dev-ap9x-pci.h" ++ #include "dev-gpio-buttons.h" +++#include "dev-eth.h" ++ #include "dev-leds-gpio.h" ++-#include "dev-spi.h" +++#include "dev-m25p80.h" +++#include "dev-nfc.h" ++ #include "dev-usb.h" ++ #include "dev-wmac.h" ++-#include "pci.h" +++#include "machtypes.h" ++ ++-#define AP136_GPIO_LED_STATUS_RED 14 ++-#define AP136_GPIO_LED_STATUS_GREEN 19 ++ #define AP136_GPIO_LED_USB 4 ++-#define AP136_GPIO_LED_WLAN_2G 13 ++ #define AP136_GPIO_LED_WLAN_5G 12 +++#define AP136_GPIO_LED_WLAN_2G 13 +++#define AP136_GPIO_LED_STATUS_RED 14 ++ #define AP136_GPIO_LED_WPS_RED 15 +++#define AP136_GPIO_LED_STATUS_GREEN 19 ++ #define AP136_GPIO_LED_WPS_GREEN 20 ++ ++ #define AP136_GPIO_BTN_WPS 16 ++@@ -43,37 +49,39 @@ ++ #define AP136_KEYS_POLL_INTERVAL 20 /* msecs */ ++ #define AP136_KEYS_DEBOUNCE_INTERVAL (3 * AP136_KEYS_POLL_INTERVAL) ++ ++-#define AP136_WMAC_CALDATA_OFFSET 0x1000 ++-#define AP136_PCIE_CALDATA_OFFSET 0x5000 +++#define AP136_MAC0_OFFSET 0 +++#define AP136_MAC1_OFFSET 6 +++#define AP136_WMAC_CALDATA_OFFSET 0x1000 +++#define AP136_PCIE_CALDATA_OFFSET 0x5000 ++ ++ static struct gpio_led ap136_leds_gpio[] __initdata = { ++ { ++- .name = "qca:green:status", +++ .name = "ap136:green:status", ++ .gpio = AP136_GPIO_LED_STATUS_GREEN, ++ .active_low = 1, ++ }, ++ { ++- .name = "qca:red:status", +++ .name = "ap136:red:status", ++ .gpio = AP136_GPIO_LED_STATUS_RED, ++ .active_low = 1, ++ }, ++ { ++- .name = "qca:green:wps", +++ .name = "ap136:green:wps", ++ .gpio = AP136_GPIO_LED_WPS_GREEN, ++ .active_low = 1, ++ }, ++ { ++- .name = "qca:red:wps", +++ .name = "ap136:red:wps", ++ .gpio = AP136_GPIO_LED_WPS_RED, ++ .active_low = 1, ++ }, ++ { ++- .name = "qca:red:wlan-2g", +++ .name = "ap136:red:wlan-2g", ++ .gpio = AP136_GPIO_LED_WLAN_2G, ++ .active_low = 1, ++ }, ++ { ++- .name = "qca:red:usb", +++ .name = "ap136:red:usb", ++ .gpio = AP136_GPIO_LED_USB, ++ .active_low = 1, ++ } ++@@ -98,59 +106,151 @@ static struct gpio_keys_button ap136_gpi ++ }, ++ }; ++ ++-static struct spi_board_info ap136_spi_info[] = { ++- { ++- .bus_num = 0, ++- .chip_select = 0, ++- .max_speed_hz = 25000000, ++- .modalias = "mx25l6405d", ++- } +++static struct ar8327_pad_cfg ap136_ar8327_pad0_cfg; +++static struct ar8327_pad_cfg ap136_ar8327_pad6_cfg; +++ +++static struct ar8327_platform_data ap136_ar8327_data = { +++ .pad0_cfg = &ap136_ar8327_pad0_cfg, +++ .pad6_cfg = &ap136_ar8327_pad6_cfg, +++ .port0_cfg = { +++ .force_link = 1, +++ .speed = AR8327_PORT_SPEED_1000, +++ .duplex = 1, +++ .txpause = 1, +++ .rxpause = 1, +++ }, +++ .port6_cfg = { +++ .force_link = 1, +++ .speed = AR8327_PORT_SPEED_1000, +++ .duplex = 1, +++ .txpause = 1, +++ .rxpause = 1, +++ }, ++ }; ++ ++-static struct ath79_spi_platform_data ap136_spi_data = { ++- .bus_num = 0, ++- .num_chipselect = 1, +++static struct mdio_board_info ap136_mdio0_info[] = { +++ { +++ .bus_id = "ag71xx-mdio.0", +++ .mdio_addr = 0, +++ .platform_data = &ap136_ar8327_data, +++ }, ++ }; ++ ++-#ifdef CONFIG_PCI ++-static struct ath9k_platform_data ap136_ath9k_data; +++static void __init ap136_common_setup(void) +++{ +++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); +++ +++ ath79_register_m25p80(NULL); +++ +++ ath79_register_leds_gpio(-1, ARRAY_SIZE(ap136_leds_gpio), +++ ap136_leds_gpio); +++ ath79_register_gpio_keys_polled(-1, AP136_KEYS_POLL_INTERVAL, +++ ARRAY_SIZE(ap136_gpio_keys), +++ ap136_gpio_keys); +++ +++ ath79_register_usb(); +++ ath79_register_nfc(); +++ +++ ath79_register_wmac(art + AP136_WMAC_CALDATA_OFFSET, NULL); +++ +++ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); ++ ++-static int ap136_pci_plat_dev_init(struct pci_dev *dev) +++ ath79_register_mdio(0, 0x0); +++ ath79_init_mac(ath79_eth0_data.mac_addr, art + AP136_MAC0_OFFSET, 0); +++ +++ mdiobus_register_board_info(ap136_mdio0_info, +++ ARRAY_SIZE(ap136_mdio0_info)); +++ +++ /* GMAC0 is connected to the RMGII interface */ +++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; +++ ath79_eth0_data.phy_mask = BIT(0); +++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; +++ +++ ath79_register_eth(0); +++ +++ /* GMAC1 is connected tot eh SGMII interface */ +++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; +++ ath79_eth1_data.speed = SPEED_1000; +++ ath79_eth1_data.duplex = DUPLEX_FULL; +++ +++ ath79_register_eth(1); +++} +++ +++static void __init ap136_010_setup(void) ++ { ++- if (dev->bus->number == 1 && (PCI_SLOT(dev->devfn)) == 0) ++- dev->dev.platform_data = &ap136_ath9k_data; +++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++- return 0; +++ /* GMAC0 of the AR8327 switch is connected to GMAC0 via RGMII */ +++ ap136_ar8327_pad0_cfg.mode = AR8327_PAD_MAC_RGMII; +++ ap136_ar8327_pad0_cfg.txclk_delay_en = true; +++ ap136_ar8327_pad0_cfg.rxclk_delay_en = true; +++ ap136_ar8327_pad0_cfg.txclk_delay_sel = AR8327_CLK_DELAY_SEL1; +++ ap136_ar8327_pad0_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL2; +++ +++ /* GMAC6 of the AR8327 switch is connected to GMAC1 via SGMII */ +++ ap136_ar8327_pad6_cfg.mode = AR8327_PAD_MAC_SGMII; +++ ap136_ar8327_pad6_cfg.rxclk_delay_en = true; +++ ap136_ar8327_pad6_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL0; +++ +++ ath79_eth0_pll_data.pll_1000 = 0xa6000000; +++ ath79_eth1_pll_data.pll_1000 = 0x03000101; +++ +++ ap136_common_setup(); +++ ap91_pci_init(art + AP136_PCIE_CALDATA_OFFSET, NULL); ++ } ++ ++-static void __init ap136_pci_init(u8 *eeprom) +++MIPS_MACHINE(ATH79_MACH_AP136_010, "AP136-010", +++ "Atheros AP136-010 reference board", +++ ap136_010_setup); +++ +++static void __init ap136_020_common_setup(void) ++ { ++- memcpy(ap136_ath9k_data.eeprom_data, eeprom, ++- sizeof(ap136_ath9k_data.eeprom_data)); +++ /* GMAC0 of the AR8327 switch is connected to GMAC1 via SGMII */ +++ ap136_ar8327_pad0_cfg.mode = AR8327_PAD_MAC_SGMII; +++ ap136_ar8327_pad0_cfg.sgmii_delay_en = true; +++ +++ /* GMAC6 of the AR8327 switch is connected to GMAC0 via RGMII */ +++ ap136_ar8327_pad6_cfg.mode = AR8327_PAD_MAC_RGMII; +++ ap136_ar8327_pad6_cfg.txclk_delay_en = true; +++ ap136_ar8327_pad6_cfg.rxclk_delay_en = true; +++ ap136_ar8327_pad6_cfg.txclk_delay_sel = AR8327_CLK_DELAY_SEL1; +++ ap136_ar8327_pad6_cfg.rxclk_delay_sel = AR8327_CLK_DELAY_SEL2; ++ ++- ath79_pci_set_plat_dev_init(ap136_pci_plat_dev_init); ++- ath79_register_pci(); +++ ath79_eth0_pll_data.pll_1000 = 0x56000000; +++ ath79_eth1_pll_data.pll_1000 = 0x03000101; +++ +++ ap136_common_setup(); ++ } ++-#else ++-static inline void ap136_pci_init(u8 *eeprom) {} ++-#endif /* CONFIG_PCI */ ++ ++-static void __init ap136_setup(void) +++static void __init ap136_020_setup(void) ++ { ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++- ath79_register_leds_gpio(-1, ARRAY_SIZE(ap136_leds_gpio), ++- ap136_leds_gpio); ++- ath79_register_gpio_keys_polled(-1, AP136_KEYS_POLL_INTERVAL, ++- ARRAY_SIZE(ap136_gpio_keys), ++- ap136_gpio_keys); ++- ath79_register_spi(&ap136_spi_data, ap136_spi_info, ++- ARRAY_SIZE(ap136_spi_info)); ++- ath79_register_usb(); ++- ath79_register_wmac(art + AP136_WMAC_CALDATA_OFFSET); ++- ap136_pci_init(art + AP136_PCIE_CALDATA_OFFSET); +++ ap136_020_common_setup(); +++ ap91_pci_init(art + AP136_PCIE_CALDATA_OFFSET, NULL); ++ } ++ ++-MIPS_MACHINE(ATH79_MACH_AP136_010, "AP136-010", ++- "Atheros AP136-010 reference board", ++- ap136_setup); +++MIPS_MACHINE(ATH79_MACH_AP136_020, "AP136-020", +++ "Atheros AP136-020 reference board", +++ ap136_020_setup); +++ +++/* +++ * AP135-020 is similar to AP136-020, any future AP135 specific init +++ * code can be added here. +++ */ +++static void __init ap135_020_setup(void) +++{ +++ ap136_leds_gpio[0].name = "ap135:green:status"; +++ ap136_leds_gpio[1].name = "ap135:red:status"; +++ ap136_leds_gpio[2].name = "ap135:green:wps"; +++ ap136_leds_gpio[3].name = "ap135:red:wps"; +++ ap136_leds_gpio[4].name = "ap135:red:wlan-2g"; +++ ap136_leds_gpio[5].name = "ap135:red:usb"; +++ +++ ap136_020_common_setup(); +++ ath79_register_pci(); +++} +++ +++MIPS_MACHINE(ATH79_MACH_AP135_020, "AP135-020", +++ "Atheros AP135-020 reference board", +++ ap135_020_setup); ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -17,16 +17,17 @@ config ATH79_MACH_AP121 ++ Atheros AP121 reference board. ++ ++ config ATH79_MACH_AP136 ++- bool "Atheros AP136 reference board" +++ bool "Atheros AP136/AP135 reference board" ++ select SOC_QCA955X ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO +++ select ATH79_DEV_NFC ++ select ATH79_DEV_SPI ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ help ++ Say 'Y' here if you want your kernel to support the ++- Atheros AP136 reference board. +++ Atheros AP136 or AP135 reference boards. ++ ++ config ATH79_MACH_AP81 ++ bool "Atheros AP81 reference board" +diff --git a/target/linux/ar71xx/patches-4.14/611-MIPS-ath79-wdt-timeout.patch b/target/linux/ar71xx/patches-4.14/611-MIPS-ath79-wdt-timeout.patch +new file mode 100644 +index 0000000000..0927d5a977 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/611-MIPS-ath79-wdt-timeout.patch +@@ -0,0 +1,25 @@ ++MIPS: ath79: fix maximum timeout ++ ++If the userland tries to set a timeout higher than the max_timeout, then we should fallback to max_timeout. ++ ++Signed-off-by: John Crispin ++ ++--- a/drivers/watchdog/ath79_wdt.c +++++ b/drivers/watchdog/ath79_wdt.c ++@@ -115,10 +115,14 @@ static inline void ath79_wdt_disable(voi ++ ++ static int ath79_wdt_set_timeout(int val) ++ { ++- if (val < 1 || val > max_timeout) +++ if (val < 1) ++ return -EINVAL; ++ ++- timeout = val; +++ if (val > max_timeout) +++ timeout = max_timeout; +++ else +++ timeout = val; +++ ++ ath79_wdt_keepalive(); ++ ++ return 0; +diff --git a/target/linux/ar71xx/patches-4.14/612-MIPS-ath79-set-buffalo-txgain.patch b/target/linux/ar71xx/patches-4.14/612-MIPS-ath79-set-buffalo-txgain.patch +new file mode 100644 +index 0000000000..3d100e0549 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/612-MIPS-ath79-set-buffalo-txgain.patch +@@ -0,0 +1,24 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -319,6 +319,11 @@ void __init ath79_wmac_disable_5ghz(void ++ ath79_wmac_data.disable_5ghz = true; ++ } ++ +++void __init ath79_wmac_set_tx_gain_buffalo(void) +++{ +++ ath79_wmac_data.tx_gain_buffalo = true; +++} +++ ++ void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) ++ { ++ if (soc_is_ar913x()) ++--- a/arch/mips/ath79/dev-wmac.h +++++ b/arch/mips/ath79/dev-wmac.h ++@@ -16,6 +16,7 @@ void ath79_register_wmac(u8 *cal_data, u ++ void ath79_register_wmac_simple(void); ++ void ath79_wmac_disable_2ghz(void); ++ void ath79_wmac_disable_5ghz(void); +++void ath79_wmac_set_tx_gain_buffalo(void); ++ ++ bool ar93xx_wmac_read_mac_address(u8 *dest); ++ +diff --git a/target/linux/ar71xx/patches-4.14/613-MIPS-ath79-add-ath79_wmac_setup_ext_lna_gpio-helper.patch b/target/linux/ar71xx/patches-4.14/613-MIPS-ath79-add-ath79_wmac_setup_ext_lna_gpio-helper.patch +new file mode 100644 +index 0000000000..5c1205d59f +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/613-MIPS-ath79-add-ath79_wmac_setup_ext_lna_gpio-helper.patch +@@ -0,0 +1,76 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -18,9 +18,11 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include ++ #include +++#include "common.h" ++ #include "dev-wmac.h" ++ ++ static u8 ath79_wmac_mac[ETH_ALEN]; ++@@ -324,6 +326,51 @@ void __init ath79_wmac_set_tx_gain_buffa ++ ath79_wmac_data.tx_gain_buffalo = true; ++ } ++ +++static int ath79_request_ext_lna_gpio(unsigned chain, int gpio) +++{ +++ char *label; +++ int err; +++ +++ label = kasprintf(GFP_KERNEL, "external LNA%u", chain); +++ if (!label) +++ return -ENOMEM; +++ +++ err = gpio_request_one(gpio, GPIOF_DIR_OUT | GPIOF_INIT_LOW, label); +++ if (err) { +++ pr_err("unable to request GPIO%d for external LNA%u\n", +++ gpio, chain); +++ kfree(label); +++ } +++ +++ return err; +++} +++ +++static void ar934x_set_ext_lna_gpio(unsigned chain, int gpio) +++{ +++ unsigned int sel; +++ int err; +++ +++ if (WARN_ON(chain > 1)) +++ return; +++ +++ err = ath79_request_ext_lna_gpio(chain, gpio); +++ if (err) +++ return; +++ +++ if (chain == 0) +++ sel = AR934X_GPIO_OUT_EXT_LNA0; +++ else +++ sel = AR934X_GPIO_OUT_EXT_LNA1; +++ +++ ath79_gpio_output_select(gpio, sel); +++} +++ +++void __init ath79_wmac_set_ext_lna_gpio(unsigned chain, int gpio) +++{ +++ if (soc_is_ar934x()) +++ ar934x_set_ext_lna_gpio(chain, gpio); +++} +++ ++ void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) ++ { ++ if (soc_is_ar913x()) ++--- a/arch/mips/ath79/dev-wmac.h +++++ b/arch/mips/ath79/dev-wmac.h ++@@ -17,6 +17,7 @@ void ath79_register_wmac_simple(void); ++ void ath79_wmac_disable_2ghz(void); ++ void ath79_wmac_disable_5ghz(void); ++ void ath79_wmac_set_tx_gain_buffalo(void); +++void ath79_wmac_set_ext_lna_gpio(unsigned chain, int gpio); ++ ++ bool ar93xx_wmac_read_mac_address(u8 *dest); ++ +diff --git a/target/linux/ar71xx/patches-4.14/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch b/target/linux/ar71xx/patches-4.14/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch +new file mode 100644 +index 0000000000..722d127ec5 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch +@@ -0,0 +1,696 @@ ++From 5300a7cd7ed2f88488ddba62947b9c6bb9663777 Mon Sep 17 00:00:00 2001 ++Message-Id: <5300a7cd7ed2f88488ddba62947b9c6bb9663777.1396122227.git.mschiffer@universe-factory.net> ++From: Matthias Schiffer ++Date: Sat, 29 Mar 2014 20:26:08 +0100 ++Subject: [PATCH 1/2] MIPS: ath79: add support for QCA953x SoC ++ ++Note that the clock calculation looks very similar to the QCA955x, but the ++meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed. ++--- ++ arch/mips/ath79/Kconfig | 6 +- ++ arch/mips/ath79/clock.c | 78 ++++++++++++++++++++++++++ ++ arch/mips/ath79/common.c | 4 ++ ++ arch/mips/ath79/dev-common.c | 1 + ++ arch/mips/ath79/dev-wmac.c | 20 +++++++ ++ arch/mips/ath79/early_printk.c | 1 + ++ arch/mips/ath79/gpio.c | 4 +- ++ arch/mips/ath79/irq.c | 4 ++ ++ arch/mips/ath79/setup.c | 8 ++- ++ arch/mips/include/asm/mach-ath79/ar71xx_regs.h | 48 ++++++++++++++++ ++ arch/mips/include/asm/mach-ath79/ath79.h | 11 ++++ ++ 11 files changed, 182 insertions(+), 3 deletions(-) ++ ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -105,6 +105,10 @@ config SOC_AR934X ++ select PCI_AR724X if PCI ++ def_bool n ++ +++config SOC_QCA953X +++ select USB_ARCH_HAS_EHCI +++ def_bool n +++ ++ config SOC_QCA955X ++ select HW_HAS_PCI ++ select PCI_AR724X if PCI ++@@ -144,7 +148,7 @@ config ATH79_DEV_USB ++ def_bool n ++ ++ config ATH79_DEV_WMAC ++- depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA955X) +++ depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA953X || SOC_QCA955X) ++ def_bool n ++ ++ config ATH79_NVRAM ++--- a/arch/mips/ath79/clock.c +++++ b/arch/mips/ath79/clock.c ++@@ -357,6 +357,87 @@ static void __init ar934x_clocks_init(vo ++ iounmap(dpll_base); ++ } ++ +++static void __init qca953x_clocks_init(void) +++{ +++ unsigned long ref_rate; +++ unsigned long cpu_rate; +++ unsigned long ddr_rate; +++ unsigned long ahb_rate; +++ u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; +++ u32 cpu_pll, ddr_pll; +++ +++ /* QCA953X only supports 25MHz ref_clk */ +++ ref_rate = 25 * 1000 * 1000; +++ +++ pll = ath79_pll_rr(QCA953X_PLL_CPU_CONFIG_REG); +++ out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & +++ QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK; +++ ref_div = (pll >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) & +++ QCA953X_PLL_CPU_CONFIG_REFDIV_MASK; +++ nint = (pll >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT) & +++ QCA953X_PLL_CPU_CONFIG_NINT_MASK; +++ frac = (pll >> QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT) & +++ QCA953X_PLL_CPU_CONFIG_NFRAC_MASK; +++ +++ cpu_pll = nint * ref_rate / ref_div; +++ cpu_pll += frac * (ref_rate >> 6) / ref_div; +++ cpu_pll /= (1 << out_div); +++ +++ pll = ath79_pll_rr(QCA953X_PLL_DDR_CONFIG_REG); +++ out_div = (pll >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & +++ QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK; +++ ref_div = (pll >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) & +++ QCA953X_PLL_DDR_CONFIG_REFDIV_MASK; +++ nint = (pll >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT) & +++ QCA953X_PLL_DDR_CONFIG_NINT_MASK; +++ frac = (pll >> QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT) & +++ QCA953X_PLL_DDR_CONFIG_NFRAC_MASK; +++ +++ ddr_pll = nint * ref_rate / ref_div; +++ ddr_pll += frac * (ref_rate >> 6) / (ref_div << 4); +++ ddr_pll /= (1 << out_div); +++ +++ clk_ctrl = ath79_pll_rr(QCA953X_PLL_CLK_CTRL_REG); +++ +++ postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & +++ QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; +++ +++ if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS) +++ cpu_rate = ref_rate; +++ else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) +++ cpu_rate = cpu_pll / (postdiv + 1); +++ else +++ cpu_rate = ddr_pll / (postdiv + 1); +++ +++ postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & +++ QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; +++ +++ if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS) +++ ddr_rate = ref_rate; +++ else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) +++ ddr_rate = ddr_pll / (postdiv + 1); +++ else +++ ddr_rate = cpu_pll / (postdiv + 1); +++ +++ postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & +++ QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; +++ +++ if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS) +++ ahb_rate = ref_rate; +++ else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) +++ ahb_rate = ddr_pll / (postdiv + 1); +++ else +++ ahb_rate = cpu_pll / (postdiv + 1); +++ +++ ath79_add_sys_clkdev("ref", ref_rate); +++ ath79_add_sys_clkdev("cpu", cpu_rate); +++ ath79_add_sys_clkdev("ddr", ddr_rate); +++ ath79_add_sys_clkdev("ahb", ahb_rate); +++ +++ clk_add_alias("wdt", NULL, "ref", NULL); +++ clk_add_alias("uart", NULL, "ref", NULL); +++} +++ ++ static void __init qca955x_clocks_init(void) ++ { ++ unsigned long ref_rate; ++@@ -452,6 +533,8 @@ void __init ath79_clocks_init(void) ++ ar933x_clocks_init(); ++ else if (soc_is_ar934x()) ++ ar934x_clocks_init(); +++ else if (soc_is_qca953x()) +++ qca953x_clocks_init(); ++ else if (soc_is_qca955x()) ++ qca955x_clocks_init(); ++ else ++--- a/arch/mips/ath79/common.c +++++ b/arch/mips/ath79/common.c ++@@ -103,6 +103,8 @@ void ath79_device_reset_set(u32 mask) ++ reg = AR933X_RESET_REG_RESET_MODULE; ++ else if (soc_is_ar934x()) ++ reg = AR934X_RESET_REG_RESET_MODULE; +++ else if (soc_is_qca953x()) +++ reg = QCA953X_RESET_REG_RESET_MODULE; ++ else if (soc_is_qca955x()) ++ reg = QCA955X_RESET_REG_RESET_MODULE; ++ else ++@@ -131,6 +133,8 @@ void ath79_device_reset_clear(u32 mask) ++ reg = AR933X_RESET_REG_RESET_MODULE; ++ else if (soc_is_ar934x()) ++ reg = AR934X_RESET_REG_RESET_MODULE; +++ else if (soc_is_qca953x()) +++ reg = QCA953X_RESET_REG_RESET_MODULE; ++ else if (soc_is_qca955x()) ++ reg = QCA955X_RESET_REG_RESET_MODULE; ++ else ++--- a/arch/mips/ath79/dev-common.c +++++ b/arch/mips/ath79/dev-common.c ++@@ -94,6 +94,7 @@ void __init ath79_register_uart(void) ++ soc_is_ar724x() || ++ soc_is_ar913x() || ++ soc_is_ar934x() || +++ soc_is_qca953x() || ++ soc_is_qca955x()) { ++ ath79_uart_data[0].uartclk = uart_clk_rate; ++ platform_device_register(&ath79_uart_device); ++@@ -157,6 +158,9 @@ void __init ath79_gpio_init(void) ++ } else if (soc_is_ar934x()) { ++ ath79_gpio_pdata.ngpios = AR934X_GPIO_COUNT; ++ ath79_gpio_pdata.oe_inverted = 1; +++ } else if (soc_is_qca953x()) { +++ ath79_gpio_pdata.ngpios = QCA953X_GPIO_COUNT; +++ ath79_gpio_pdata.oe_inverted = 1; ++ } else if (soc_is_qca955x()) { ++ ath79_gpio_pdata.ngpios = QCA955X_GPIO_COUNT; ++ ath79_gpio_pdata.oe_inverted = 1; ++--- a/arch/mips/ath79/dev-usb.c +++++ b/arch/mips/ath79/dev-usb.c ++@@ -236,6 +236,30 @@ static void __init ar934x_usb_setup(void ++ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); ++ } ++ +++static void __init qca953x_usb_setup(void) +++{ +++ u32 bootstrap; +++ +++ bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP); +++ +++ ath79_device_reset_set(QCA953X_RESET_USBSUS_OVERRIDE); +++ udelay(1000); +++ +++ ath79_device_reset_clear(QCA953X_RESET_USB_PHY); +++ udelay(1000); +++ +++ ath79_device_reset_clear(QCA953X_RESET_USB_PHY_ANALOG); +++ udelay(1000); +++ +++ ath79_device_reset_clear(QCA953X_RESET_USB_HOST); +++ udelay(1000); +++ +++ ath79_usb_register("ehci-platform", -1, +++ QCA953X_EHCI_BASE, QCA953X_EHCI_SIZE, +++ ATH79_CPU_IRQ(3), +++ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +++} +++ ++ static void qca955x_usb_reset_notifier(struct platform_device *pdev) ++ { ++ u32 base; ++@@ -286,6 +310,8 @@ void __init ath79_register_usb(void) ++ ar933x_usb_setup(); ++ else if (soc_is_ar934x()) ++ ar934x_usb_setup(); +++ else if (soc_is_qca953x()) +++ qca953x_usb_setup(); ++ else if (soc_is_qca955x()) ++ qca955x_usb_setup(); ++ else ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -100,7 +100,7 @@ static int ar933x_wmac_reset(void) ++ return -ETIMEDOUT; ++ } ++ ++-static int ar933x_r1_get_wmac_revision(void) +++static int ar93xx_get_soc_revision(void) ++ { ++ return ath79_soc_rev; ++ } ++@@ -125,7 +125,7 @@ static void __init ar933x_wmac_setup(voi ++ ath79_wmac_data.is_clk_25mhz = true; ++ ++ if (ath79_soc_rev == 1) ++- ath79_wmac_data.get_mac_revision = ar933x_r1_get_wmac_revision; +++ ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; ++ ++ ath79_wmac_data.external_reset = ar933x_wmac_reset; ++ } ++@@ -150,6 +150,21 @@ static void ar934x_wmac_setup(void) ++ ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; ++ } ++ +++static void qca953x_wmac_setup(void) +++{ +++ ath79_wmac_device.name = "qca953x_wmac"; +++ +++ ath79_wmac_resources[0].start = QCA953X_WMAC_BASE; +++ ath79_wmac_resources[0].end = QCA953X_WMAC_BASE + QCA953X_WMAC_SIZE - 1; +++ ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); +++ ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1); +++ +++ /* QCA953X only supports 25MHz ref_clk */ +++ ath79_wmac_data.is_clk_25mhz = true; +++ +++ ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; +++} +++ ++ static void qca955x_wmac_setup(void) ++ { ++ u32 t; ++@@ -379,6 +394,8 @@ void __init ath79_register_wmac(u8 *cal_ ++ ar933x_wmac_setup(); ++ else if (soc_is_ar934x()) ++ ar934x_wmac_setup(); +++ else if (soc_is_qca953x()) +++ qca953x_wmac_setup(); ++ else if (soc_is_qca955x()) ++ qca955x_wmac_setup(); ++ else ++--- a/arch/mips/ath79/early_printk.c +++++ b/arch/mips/ath79/early_printk.c ++@@ -116,6 +116,8 @@ static void prom_putchar_init(void) ++ case REV_ID_MAJOR_AR9341: ++ case REV_ID_MAJOR_AR9342: ++ case REV_ID_MAJOR_AR9344: +++ case REV_ID_MAJOR_QCA9533: +++ case REV_ID_MAJOR_QCA9533_V2: ++ case REV_ID_MAJOR_QCA9556: ++ case REV_ID_MAJOR_QCA9558: ++ _prom_putchar = prom_putchar_ar71xx; ++--- a/arch/mips/ath79/gpio.c +++++ b/arch/mips/ath79/gpio.c ++@@ -31,7 +31,7 @@ static void __iomem *ath79_gpio_get_func ++ soc_is_ar913x() || ++ soc_is_ar933x()) ++ reg = AR71XX_GPIO_REG_FUNC; ++- else if (soc_is_ar934x()) +++ else if (soc_is_ar934x() || soc_is_qca953x()) ++ reg = AR934X_GPIO_REG_FUNC; ++ else ++ BUG(); ++@@ -64,7 +64,7 @@ void __init ath79_gpio_output_select(uns ++ unsigned int reg; ++ u32 t, s; ++ ++- BUG_ON(!soc_is_ar934x()); +++ BUG_ON(!soc_is_ar934x() && !soc_is_qca953x()); ++ ++ if (gpio >= AR934X_GPIO_COUNT) ++ return; ++--- a/arch/mips/ath79/irq.c +++++ b/arch/mips/ath79/irq.c ++@@ -62,6 +62,34 @@ static void ar934x_ip2_irq_init(void) ++ irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch); ++ } ++ +++static void qca953x_ip2_irq_dispatch(struct irq_desc *desc) +++{ +++ u32 status; +++ +++ status = ath79_reset_rr(QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS); +++ +++ if (status & QCA953X_PCIE_WMAC_INT_PCIE_ALL) { +++ ath79_ddr_wb_flush(3); +++ generic_handle_irq(ATH79_IP2_IRQ(0)); +++ } else if (status & QCA953X_PCIE_WMAC_INT_WMAC_ALL) { +++ ath79_ddr_wb_flush(4); +++ generic_handle_irq(ATH79_IP2_IRQ(1)); +++ } else { +++ spurious_interrupt(); +++ } +++} +++ +++static void qca953x_irq_init(void) +++{ +++ int i; +++ +++ for (i = ATH79_IP2_IRQ_BASE; +++ i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) +++ irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq); +++ +++ irq_set_chained_handler(ATH79_CPU_IRQ(2), qca953x_ip2_irq_dispatch); +++} +++ ++ static void qca955x_ip2_irq_dispatch(struct irq_desc *desc) ++ { ++ u32 status; ++@@ -149,7 +177,7 @@ void __init arch_init_irq(void) ++ soc_is_ar913x() || soc_is_ar933x()) { ++ irq_wb_chan2 = 3; ++ irq_wb_chan3 = 2; ++- } else if (soc_is_ar934x()) { +++ } else if (soc_is_ar934x() || soc_is_qca953x()) { ++ irq_wb_chan3 = 2; ++ } ++ ++@@ -160,6 +188,7 @@ void __init arch_init_irq(void) ++ else if (soc_is_ar724x() || ++ soc_is_ar933x() || ++ soc_is_ar934x() || +++ soc_is_qca953x() || ++ soc_is_qca955x()) ++ misc_is_ar71xx = false; ++ else ++@@ -170,6 +199,8 @@ void __init arch_init_irq(void) ++ ++ if (soc_is_ar934x()) ++ ar934x_ip2_irq_init(); +++ else if (soc_is_qca953x()) +++ qca953x_irq_init(); ++ else if (soc_is_qca955x()) ++ qca955x_irq_init(); ++ } ++--- a/arch/mips/ath79/setup.c +++++ b/arch/mips/ath79/setup.c ++@@ -60,6 +60,7 @@ static void __init ath79_detect_sys_type ++ u32 major; ++ u32 minor; ++ u32 rev = 0; +++ u32 ver = 1; ++ ++ id = ath79_reset_rr(AR71XX_RESET_REG_REV_ID); ++ major = id & REV_ID_MAJOR_MASK; ++@@ -152,6 +153,17 @@ static void __init ath79_detect_sys_type ++ rev = id & AR934X_REV_ID_REVISION_MASK; ++ break; ++ +++ case REV_ID_MAJOR_QCA9533_V2: +++ ver = 2; +++ ath79_soc_rev = 2; +++ /* drop through */ +++ +++ case REV_ID_MAJOR_QCA9533: +++ ath79_soc = ATH79_SOC_QCA9533; +++ chip = "9533"; +++ rev = id & QCA953X_REV_ID_REVISION_MASK; +++ break; +++ ++ case REV_ID_MAJOR_QCA9556: ++ ath79_soc = ATH79_SOC_QCA9556; ++ chip = "9556"; ++@@ -168,11 +180,12 @@ static void __init ath79_detect_sys_type ++ panic("ath79: unknown SoC, id:0x%08x", id); ++ } ++ ++- ath79_soc_rev = rev; +++ if (ver == 1) +++ ath79_soc_rev = rev; ++ ++- if (soc_is_qca955x()) ++- sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s rev %u", ++- chip, rev); +++ if (soc_is_qca953x() || soc_is_qca955x()) +++ sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s ver %u rev %u", +++ chip, ver, rev); ++ else ++ sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); ++ pr_info("SoC: %s\n", ath79_sys_type); ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -105,6 +105,21 @@ ++ #define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) ++ #define AR934X_SRIF_SIZE 0x1000 ++ +++#define QCA953X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +++#define QCA953X_GMAC_SIZE 0x14 +++#define QCA953X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) +++#define QCA953X_WMAC_SIZE 0x20000 +++#define QCA953X_EHCI_BASE 0x1b000000 +++#define QCA953X_EHCI_SIZE 0x200 +++#define QCA953X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) +++#define QCA953X_SRIF_SIZE 0x1000 +++ +++#define QCA953X_PCI_CFG_BASE0 0x14000000 +++#define QCA953X_PCI_CTRL_BASE0 (AR71XX_APB_BASE + 0x000f0000) +++#define QCA953X_PCI_CRP_BASE0 (AR71XX_APB_BASE + 0x000c0000) +++#define QCA953X_PCI_MEM_BASE0 0x10000000 +++#define QCA953X_PCI_MEM_SIZE 0x02000000 +++ ++ #define QCA955X_PCI_MEM_BASE0 0x10000000 ++ #define QCA955X_PCI_MEM_BASE1 0x12000000 ++ #define QCA955X_PCI_MEM_SIZE 0x02000000 ++@@ -180,6 +195,12 @@ ++ #define AR934X_OTP_INTF3_ADDRESS 0x3100c ++ #define AR934X_OTP_PGENB_SETUP_HOLD_TIME_ADDRESS 0x31034 ++ +++#define QCA953X_DDR_REG_FLUSH_GE0 0x9c +++#define QCA953X_DDR_REG_FLUSH_GE1 0xa0 +++#define QCA953X_DDR_REG_FLUSH_USB 0xa4 +++#define QCA953X_DDR_REG_FLUSH_PCIE 0xa8 +++#define QCA953X_DDR_REG_FLUSH_WMAC 0xac +++ ++ /* ++ * PLL block ++ */ ++@@ -289,6 +310,44 @@ ++ ++ #define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL BIT(6) ++ +++#define QCA953X_PLL_CPU_CONFIG_REG 0x00 +++#define QCA953X_PLL_DDR_CONFIG_REG 0x04 +++#define QCA953X_PLL_CLK_CTRL_REG 0x08 +++#define QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 +++#define QCA953X_PLL_ETH_XMII_CONTROL_REG 0x2c +++#define QCA953X_PLL_ETH_SGMII_CONTROL_REG 0x48 +++ +++#define QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 +++#define QCA953X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f +++#define QCA953X_PLL_CPU_CONFIG_NINT_SHIFT 6 +++#define QCA953X_PLL_CPU_CONFIG_NINT_MASK 0x3f +++#define QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +++#define QCA953X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +++#define QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +++#define QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 +++ +++#define QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 +++#define QCA953X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff +++#define QCA953X_PLL_DDR_CONFIG_NINT_SHIFT 10 +++#define QCA953X_PLL_DDR_CONFIG_NINT_MASK 0x3f +++#define QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +++#define QCA953X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +++#define QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +++#define QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 +++ +++#define QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +++#define QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +++#define QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +++#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +++#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +++#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +++#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +++#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +++#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +++#define QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) +++#define QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) +++#define QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) +++ ++ #define QCA955X_PLL_CPU_CONFIG_REG 0x00 ++ #define QCA955X_PLL_DDR_CONFIG_REG 0x04 ++ #define QCA955X_PLL_CLK_CTRL_REG 0x08 ++@@ -365,6 +424,10 @@ ++ #define AR934X_RESET_REG_BOOTSTRAP 0xb0 ++ #define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac ++ +++#define QCA953X_RESET_REG_RESET_MODULE 0x1c +++#define QCA953X_RESET_REG_BOOTSTRAP 0xb0 +++#define QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac +++ ++ #define QCA955X_RESET_REG_RESET_MODULE 0x1c ++ #define QCA955X_RESET_REG_BOOTSTRAP 0xb0 ++ #define QCA955X_RESET_REG_EXT_INT_STATUS 0xac ++@@ -460,6 +523,27 @@ ++ #define AR934X_RESET_MBOX BIT(1) ++ #define AR934X_RESET_I2S BIT(0) ++ +++#define QCA953X_RESET_USB_EXT_PWR BIT(29) +++#define QCA953X_RESET_EXTERNAL BIT(28) +++#define QCA953X_RESET_RTC BIT(27) +++#define QCA953X_RESET_FULL_CHIP BIT(24) +++#define QCA953X_RESET_GE1_MDIO BIT(23) +++#define QCA953X_RESET_GE0_MDIO BIT(22) +++#define QCA953X_RESET_CPU_NMI BIT(21) +++#define QCA953X_RESET_CPU_COLD BIT(20) +++#define QCA953X_RESET_DDR BIT(16) +++#define QCA953X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +++#define QCA953X_RESET_GE1_MAC BIT(13) +++#define QCA953X_RESET_ETH_SWITCH_ANALOG BIT(12) +++#define QCA953X_RESET_USB_PHY_ANALOG BIT(11) +++#define QCA953X_RESET_GE0_MAC BIT(9) +++#define QCA953X_RESET_ETH_SWITCH BIT(8) +++#define QCA953X_RESET_PCIE_PHY BIT(7) +++#define QCA953X_RESET_PCIE BIT(6) +++#define QCA953X_RESET_USB_HOST BIT(5) +++#define QCA953X_RESET_USB_PHY BIT(4) +++#define QCA953X_RESET_USBSUS_OVERRIDE BIT(3) +++ ++ #define QCA955X_RESET_HOST BIT(31) ++ #define QCA955X_RESET_SLIC BIT(30) ++ #define QCA955X_RESET_HDMA BIT(29) ++@@ -513,6 +597,13 @@ ++ #define AR934X_BOOTSTRAP_SDRAM_DISABLED BIT(1) ++ #define AR934X_BOOTSTRAP_DDR1 BIT(0) ++ +++#define QCA953X_BOOTSTRAP_SW_OPTION2 BIT(12) +++#define QCA953X_BOOTSTRAP_SW_OPTION1 BIT(11) +++#define QCA953X_BOOTSTRAP_EJTAG_MODE BIT(5) +++#define QCA953X_BOOTSTRAP_REF_CLK BIT(4) +++#define QCA953X_BOOTSTRAP_SDRAM_DISABLED BIT(1) +++#define QCA953X_BOOTSTRAP_DDR1 BIT(0) +++ ++ #define QCA955X_BOOTSTRAP_REF_CLK_40 BIT(4) ++ ++ #define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) ++@@ -533,6 +624,24 @@ ++ AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \ ++ AR934X_PCIE_WMAC_INT_PCIE_RC3) ++ +++#define QCA953X_PCIE_WMAC_INT_WMAC_MISC BIT(0) +++#define QCA953X_PCIE_WMAC_INT_WMAC_TX BIT(1) +++#define QCA953X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) +++#define QCA953X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) +++#define QCA953X_PCIE_WMAC_INT_PCIE_RC BIT(4) +++#define QCA953X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) +++#define QCA953X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) +++#define QCA953X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) +++#define QCA953X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) +++#define QCA953X_PCIE_WMAC_INT_WMAC_ALL \ +++ (QCA953X_PCIE_WMAC_INT_WMAC_MISC | QCA953X_PCIE_WMAC_INT_WMAC_TX | \ +++ QCA953X_PCIE_WMAC_INT_WMAC_RXLP | QCA953X_PCIE_WMAC_INT_WMAC_RXHP) +++ +++#define QCA953X_PCIE_WMAC_INT_PCIE_ALL \ +++ (QCA953X_PCIE_WMAC_INT_PCIE_RC | QCA953X_PCIE_WMAC_INT_PCIE_RC0 | \ +++ QCA953X_PCIE_WMAC_INT_PCIE_RC1 | QCA953X_PCIE_WMAC_INT_PCIE_RC2 | \ +++ QCA953X_PCIE_WMAC_INT_PCIE_RC3) +++ ++ #define QCA955X_EXT_INT_WMAC_MISC BIT(0) ++ #define QCA955X_EXT_INT_WMAC_TX BIT(1) ++ #define QCA955X_EXT_INT_WMAC_RXLP BIT(2) ++@@ -575,6 +684,8 @@ ++ #define REV_ID_MAJOR_AR9341 0x0120 ++ #define REV_ID_MAJOR_AR9342 0x1120 ++ #define REV_ID_MAJOR_AR9344 0x2120 +++#define REV_ID_MAJOR_QCA9533 0x0140 +++#define REV_ID_MAJOR_QCA9533_V2 0x0160 ++ #define REV_ID_MAJOR_QCA9556 0x0130 ++ #define REV_ID_MAJOR_QCA9558 0x1130 ++ ++@@ -597,6 +708,8 @@ ++ ++ #define AR934X_REV_ID_REVISION_MASK 0xf ++ +++#define QCA953X_REV_ID_REVISION_MASK 0xf +++ ++ #define QCA955X_REV_ID_REVISION_MASK 0xf ++ ++ /* ++@@ -644,6 +757,25 @@ ++ #define AR934X_GPIO_REG_OUT_FUNC5 0x40 ++ #define AR934X_GPIO_REG_FUNC 0x6c ++ +++#define QCA953X_GPIO_REG_OUT_FUNC0 0x2c +++#define QCA953X_GPIO_REG_OUT_FUNC1 0x30 +++#define QCA953X_GPIO_REG_OUT_FUNC2 0x34 +++#define QCA953X_GPIO_REG_OUT_FUNC3 0x38 +++#define QCA953X_GPIO_REG_OUT_FUNC4 0x3c +++#define QCA953X_GPIO_REG_IN_ENABLE0 0x44 +++#define QCA953X_GPIO_REG_FUNC 0x6c +++ +++#define QCA953X_GPIO_OUT_MUX_SPI_CS1 10 +++#define QCA953X_GPIO_OUT_MUX_SPI_CS2 11 +++#define QCA953X_GPIO_OUT_MUX_SPI_CS0 9 +++#define QCA953X_GPIO_OUT_MUX_SPI_CLK 8 +++#define QCA953X_GPIO_OUT_MUX_SPI_MOSI 12 +++#define QCA953X_GPIO_OUT_MUX_LED_LINK1 41 +++#define QCA953X_GPIO_OUT_MUX_LED_LINK2 42 +++#define QCA953X_GPIO_OUT_MUX_LED_LINK3 43 +++#define QCA953X_GPIO_OUT_MUX_LED_LINK4 44 +++#define QCA953X_GPIO_OUT_MUX_LED_LINK5 45 +++ ++ #define QCA955X_GPIO_REG_OUT_FUNC0 0x2c ++ #define QCA955X_GPIO_REG_OUT_FUNC1 0x30 ++ #define QCA955X_GPIO_REG_OUT_FUNC2 0x34 ++@@ -658,6 +790,7 @@ ++ #define AR913X_GPIO_COUNT 22 ++ #define AR933X_GPIO_COUNT 30 ++ #define AR934X_GPIO_COUNT 23 +++#define QCA953X_GPIO_COUNT 18 ++ #define QCA955X_GPIO_COUNT 24 ++ ++ /* ++@@ -681,6 +814,24 @@ ++ #define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 ++ #define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 ++ +++#define QCA953X_SRIF_CPU_DPLL1_REG 0x1c0 +++#define QCA953X_SRIF_CPU_DPLL2_REG 0x1c4 +++#define QCA953X_SRIF_CPU_DPLL3_REG 0x1c8 +++ +++#define QCA953X_SRIF_DDR_DPLL1_REG 0x240 +++#define QCA953X_SRIF_DDR_DPLL2_REG 0x244 +++#define QCA953X_SRIF_DDR_DPLL3_REG 0x248 +++ +++#define QCA953X_SRIF_DPLL1_REFDIV_SHIFT 27 +++#define QCA953X_SRIF_DPLL1_REFDIV_MASK 0x1f +++#define QCA953X_SRIF_DPLL1_NINT_SHIFT 18 +++#define QCA953X_SRIF_DPLL1_NINT_MASK 0x1ff +++#define QCA953X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff +++ +++#define QCA953X_SRIF_DPLL2_LOCAL_PLL BIT(30) +++#define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT 13 +++#define QCA953X_SRIF_DPLL2_OUTDIV_MASK 0x7 +++ ++ #define AR71XX_GPIO_FUNC_STEREO_EN BIT(17) ++ #define AR71XX_GPIO_FUNC_SLIC_EN BIT(16) ++ #define AR71XX_GPIO_FUNC_SPI_CS2_EN BIT(13) ++@@ -887,6 +1038,16 @@ ++ #define AR934X_ETH_CFG_RDV_DELAY_SHIFT 16 ++ ++ /* +++ * QCA953X GMAC Interface +++ */ +++#define QCA953X_GMAC_REG_ETH_CFG 0x00 +++ +++#define QCA953X_ETH_CFG_SW_ONLY_MODE BIT(6) +++#define QCA953X_ETH_CFG_SW_PHY_SWAP BIT(7) +++#define QCA953X_ETH_CFG_SW_APB_ACCESS BIT(9) +++#define QCA953X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) +++ +++/* ++ * QCA955X GMAC Interface ++ */ ++ ++--- a/arch/mips/include/asm/mach-ath79/ath79.h +++++ b/arch/mips/include/asm/mach-ath79/ath79.h ++@@ -32,6 +32,7 @@ enum ath79_soc_type { ++ ATH79_SOC_AR9341, ++ ATH79_SOC_AR9342, ++ ATH79_SOC_AR9344, +++ ATH79_SOC_QCA9533, ++ ATH79_SOC_QCA9556, ++ ATH79_SOC_QCA9558, ++ }; ++@@ -100,6 +101,16 @@ static inline int soc_is_ar934x(void) ++ return soc_is_ar9341() || soc_is_ar9342() || soc_is_ar9344(); ++ } ++ +++static inline int soc_is_qca9533(void) +++{ +++ return ath79_soc == ATH79_SOC_QCA9533; +++} +++ +++static inline int soc_is_qca953x(void) +++{ +++ return soc_is_qca9533(); +++} +++ ++ static inline int soc_is_qca9556(void) ++ { ++ return ath79_soc == ATH79_SOC_QCA9556; +diff --git a/target/linux/ar71xx/patches-4.14/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-4.14/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch +new file mode 100644 +index 0000000000..670f7bef0a +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch +@@ -0,0 +1,717 @@ ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -114,6 +114,12 @@ config SOC_QCA955X ++ select PCI_AR724X if PCI ++ def_bool n ++ +++config SOC_QCA956X +++ select USB_ARCH_HAS_EHCI +++ select HW_HAS_PCI +++ select PCI_AR724X if PCI +++ def_bool n +++ ++ config ATH79_DEV_M25P80 ++ select ATH79_DEV_SPI ++ def_bool n ++@@ -148,7 +154,7 @@ config ATH79_DEV_USB ++ def_bool n ++ ++ config ATH79_DEV_WMAC ++- depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA953X || SOC_QCA955X) +++ depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA953X || SOC_QCA955X || SOC_QCA956X) ++ def_bool n ++ ++ config ATH79_NVRAM ++--- a/arch/mips/ath79/clock.c +++++ b/arch/mips/ath79/clock.c ++@@ -523,6 +523,100 @@ static void __init qca955x_clocks_init(v ++ clk_add_alias("uart", NULL, "ref", NULL); ++ } ++ +++static void __init qca956x_clocks_init(void) +++{ +++ unsigned long ref_rate; +++ unsigned long cpu_rate; +++ unsigned long ddr_rate; +++ unsigned long ahb_rate; +++ u32 pll, out_div, ref_div, nint, hfrac, lfrac, clk_ctrl, postdiv; +++ u32 cpu_pll, ddr_pll; +++ u32 bootstrap; +++ +++ bootstrap = ath79_reset_rr(QCA956X_RESET_REG_BOOTSTRAP); +++ if (bootstrap & QCA956X_BOOTSTRAP_REF_CLK_40) +++ ref_rate = 40 * 1000 * 1000; +++ else +++ ref_rate = 25 * 1000 * 1000; +++ +++ pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG_REG); +++ out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & +++ QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK; +++ ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) & +++ QCA956X_PLL_CPU_CONFIG_REFDIV_MASK; +++ +++ pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG1_REG); +++ nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) & +++ QCA956X_PLL_CPU_CONFIG1_NINT_MASK; +++ hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) & +++ QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK; +++ lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) & +++ QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK; +++ +++ cpu_pll = nint * ref_rate / ref_div; +++ cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); +++ cpu_pll += (hfrac >> 13) * ref_rate / ref_div; +++ cpu_pll /= (1 << out_div); +++ +++ pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG_REG); +++ out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & +++ QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK; +++ ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) & +++ QCA956X_PLL_DDR_CONFIG_REFDIV_MASK; +++ pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG1_REG); +++ nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) & +++ QCA956X_PLL_DDR_CONFIG1_NINT_MASK; +++ hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) & +++ QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK; +++ lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) & +++ QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK; +++ +++ ddr_pll = nint * ref_rate / ref_div; +++ ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); +++ ddr_pll += (hfrac >> 13) * ref_rate / ref_div; +++ ddr_pll /= (1 << out_div); +++ +++ clk_ctrl = ath79_pll_rr(QCA956X_PLL_CLK_CTRL_REG); +++ +++ postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & +++ QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; +++ +++ if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS) +++ cpu_rate = ref_rate; +++ else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL) +++ cpu_rate = ddr_pll / (postdiv + 1); +++ else +++ cpu_rate = cpu_pll / (postdiv + 1); +++ +++ postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & +++ QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; +++ +++ if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS) +++ ddr_rate = ref_rate; +++ else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL) +++ ddr_rate = cpu_pll / (postdiv + 1); +++ else +++ ddr_rate = ddr_pll / (postdiv + 1); +++ +++ postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & +++ QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; +++ +++ if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS) +++ ahb_rate = ref_rate; +++ else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) +++ ahb_rate = ddr_pll / (postdiv + 1); +++ else +++ ahb_rate = cpu_pll / (postdiv + 1); +++ +++ ath79_add_sys_clkdev("ref", ref_rate); +++ ath79_add_sys_clkdev("cpu", cpu_rate); +++ ath79_add_sys_clkdev("ddr", ddr_rate); +++ ath79_add_sys_clkdev("ahb", ahb_rate); +++ +++ clk_add_alias("wdt", NULL, "ref", NULL); +++ clk_add_alias("uart", NULL, "ref", NULL); +++} +++ ++ void __init ath79_clocks_init(void) ++ { ++ if (soc_is_ar71xx()) ++@@ -537,6 +631,8 @@ void __init ath79_clocks_init(void) ++ qca953x_clocks_init(); ++ else if (soc_is_qca955x()) ++ qca955x_clocks_init(); +++ else if (soc_is_qca956x() || soc_is_tp9343()) +++ qca956x_clocks_init(); ++ else ++ BUG(); ++ } ++--- a/arch/mips/ath79/common.c +++++ b/arch/mips/ath79/common.c ++@@ -107,6 +107,8 @@ void ath79_device_reset_set(u32 mask) ++ reg = QCA953X_RESET_REG_RESET_MODULE; ++ else if (soc_is_qca955x()) ++ reg = QCA955X_RESET_REG_RESET_MODULE; +++ else if (soc_is_qca956x() || soc_is_tp9343()) +++ reg = QCA956X_RESET_REG_RESET_MODULE; ++ else ++ panic("Reset register not defined for this SOC"); ++ ++@@ -137,6 +139,8 @@ void ath79_device_reset_clear(u32 mask) ++ reg = QCA953X_RESET_REG_RESET_MODULE; ++ else if (soc_is_qca955x()) ++ reg = QCA955X_RESET_REG_RESET_MODULE; +++ else if (soc_is_qca956x() || soc_is_tp9343()) +++ reg = QCA956X_RESET_REG_RESET_MODULE; ++ else ++ panic("Reset register not defined for this SOC"); ++ ++@@ -163,6 +167,8 @@ u32 ath79_device_reset_get(u32 mask) ++ reg = AR933X_RESET_REG_RESET_MODULE; ++ else if (soc_is_ar934x()) ++ reg = AR934X_RESET_REG_RESET_MODULE; +++ else if (soc_is_qca956x() || soc_is_tp9343()) +++ reg = QCA956X_RESET_REG_RESET_MODULE; ++ else ++ BUG(); ++ ++--- a/arch/mips/ath79/dev-common.c +++++ b/arch/mips/ath79/dev-common.c ++@@ -95,7 +95,9 @@ void __init ath79_register_uart(void) ++ soc_is_ar913x() || ++ soc_is_ar934x() || ++ soc_is_qca953x() || ++- soc_is_qca955x()) { +++ soc_is_qca955x() || +++ soc_is_qca956x() || +++ soc_is_tp9343()) { ++ ath79_uart_data[0].uartclk = uart_clk_rate; ++ platform_device_register(&ath79_uart_device); ++ } else if (soc_is_ar933x()) { ++@@ -164,6 +166,9 @@ void __init ath79_gpio_init(void) ++ } else if (soc_is_qca955x()) { ++ ath79_gpio_pdata.ngpios = QCA955X_GPIO_COUNT; ++ ath79_gpio_pdata.oe_inverted = 1; +++ } else if (soc_is_qca956x() || soc_is_tp9343()) { +++ ath79_gpio_pdata.ngpios = QCA956X_GPIO_COUNT; +++ ath79_gpio_pdata.oe_inverted = 1; ++ } else { ++ BUG(); ++ } ++--- a/arch/mips/ath79/dev-usb.c +++++ b/arch/mips/ath79/dev-usb.c ++@@ -296,6 +296,19 @@ static void __init qca955x_usb_setup(voi ++ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); ++ } ++ +++static void __init qca956x_usb_setup(void) +++{ +++ ath79_usb_register("ehci-platform", 0, +++ QCA956X_EHCI0_BASE, QCA956X_EHCI_SIZE, +++ ATH79_IP3_IRQ(0), +++ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +++ +++ ath79_usb_register("ehci-platform", 1, +++ QCA956X_EHCI1_BASE, QCA956X_EHCI_SIZE, +++ ATH79_IP3_IRQ(1), +++ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +++} +++ ++ void __init ath79_register_usb(void) ++ { ++ if (soc_is_ar71xx()) ++@@ -314,6 +327,8 @@ void __init ath79_register_usb(void) ++ qca953x_usb_setup(); ++ else if (soc_is_qca955x()) ++ qca955x_usb_setup(); +++ else if (soc_is_qca956x()) +++ qca956x_usb_setup(); ++ else ++ BUG(); ++ } ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -195,6 +195,26 @@ static void qca955x_wmac_setup(void) ++ #define AR93XX_OTP_READ_DATA \ ++ (soc_is_ar934x() ? AR934X_OTP_READ_DATA : AR9300_OTP_READ_DATA) ++ +++static void qca956x_wmac_setup(void) +++{ +++ u32 t; +++ +++ ath79_wmac_device.name = "qca956x_wmac"; +++ +++ ath79_wmac_resources[0].start = QCA956X_WMAC_BASE; +++ ath79_wmac_resources[0].end = QCA956X_WMAC_BASE + QCA956X_WMAC_SIZE - 1; +++ ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); +++ ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1); +++ +++ t = ath79_reset_rr(QCA956X_RESET_REG_BOOTSTRAP); +++ if (t & QCA956X_BOOTSTRAP_REF_CLK_40) +++ ath79_wmac_data.is_clk_25mhz = false; +++ else +++ ath79_wmac_data.is_clk_25mhz = true; +++ +++ ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; +++} +++ ++ static bool __init ++ ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data) ++ { ++@@ -398,6 +418,8 @@ void __init ath79_register_wmac(u8 *cal_ ++ qca953x_wmac_setup(); ++ else if (soc_is_qca955x()) ++ qca955x_wmac_setup(); +++ else if (soc_is_qca956x() || soc_is_tp9343()) +++ qca956x_wmac_setup(); ++ else ++ BUG(); ++ ++--- a/arch/mips/ath79/early_printk.c +++++ b/arch/mips/ath79/early_printk.c ++@@ -120,6 +120,8 @@ static void prom_putchar_init(void) ++ case REV_ID_MAJOR_QCA9533_V2: ++ case REV_ID_MAJOR_QCA9556: ++ case REV_ID_MAJOR_QCA9558: +++ case REV_ID_MAJOR_TP9343: +++ case REV_ID_MAJOR_QCA956X: ++ _prom_putchar = prom_putchar_ar71xx; ++ break; ++ ++--- a/arch/mips/ath79/gpio.c +++++ b/arch/mips/ath79/gpio.c ++@@ -31,7 +31,10 @@ static void __iomem *ath79_gpio_get_func ++ soc_is_ar913x() || ++ soc_is_ar933x()) ++ reg = AR71XX_GPIO_REG_FUNC; ++- else if (soc_is_ar934x() || soc_is_qca953x()) +++ else if (soc_is_ar934x() || +++ soc_is_qca953x() || +++ soc_is_qca956x() || +++ soc_is_tp9343()) ++ reg = AR934X_GPIO_REG_FUNC; ++ else ++ BUG(); ++@@ -64,7 +67,7 @@ void __init ath79_gpio_output_select(uns ++ unsigned int reg; ++ u32 t, s; ++ ++- BUG_ON(!soc_is_ar934x() && !soc_is_qca953x()); +++ BUG_ON(!soc_is_ar934x() && !soc_is_qca953x() && !soc_is_qca956x()); ++ ++ if (gpio >= AR934X_GPIO_COUNT) ++ return; ++--- a/arch/mips/ath79/irq.c +++++ b/arch/mips/ath79/irq.c ++@@ -162,6 +162,87 @@ static void qca955x_irq_init(void) ++ irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); ++ } ++ +++static void qca956x_ip2_irq_dispatch(struct irq_desc *desc) +++{ +++ u32 status; +++ +++ status = ath79_reset_rr(QCA956X_RESET_REG_EXT_INT_STATUS); +++ status &= QCA956X_EXT_INT_PCIE_RC1_ALL | QCA956X_EXT_INT_WMAC_ALL; +++ +++ if (status == 0) { +++ spurious_interrupt(); +++ return; +++ } +++ +++ if (status & QCA956X_EXT_INT_PCIE_RC1_ALL) { +++ /* TODO: flush DDR? */ +++ generic_handle_irq(ATH79_IP2_IRQ(0)); +++ } +++ +++ if (status & QCA956X_EXT_INT_WMAC_ALL) { +++ /* TODO: flsuh DDR? */ +++ generic_handle_irq(ATH79_IP2_IRQ(1)); +++ } +++} +++ +++static void qca956x_ip3_irq_dispatch(struct irq_desc *desc) +++{ +++ u32 status; +++ +++ status = ath79_reset_rr(QCA956X_RESET_REG_EXT_INT_STATUS); +++ status &= QCA956X_EXT_INT_PCIE_RC2_ALL | +++ QCA956X_EXT_INT_USB1 | QCA956X_EXT_INT_USB2; +++ +++ if (status == 0) { +++ spurious_interrupt(); +++ return; +++ } +++ +++ if (status & QCA956X_EXT_INT_USB1) { +++ /* TODO: flush DDR? */ +++ generic_handle_irq(ATH79_IP3_IRQ(0)); +++ } +++ +++ if (status & QCA956X_EXT_INT_USB2) { +++ /* TODO: flush DDR? */ +++ generic_handle_irq(ATH79_IP3_IRQ(1)); +++ } +++ +++ if (status & QCA956X_EXT_INT_PCIE_RC2_ALL) { +++ /* TODO: flush DDR? */ +++ generic_handle_irq(ATH79_IP3_IRQ(2)); +++ } +++} +++ +++static void qca956x_enable_timer_cb(void) { +++ u32 misc; +++ +++ misc = ath79_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE); +++ misc |= MISC_INT_MIPS_SI_TIMERINT_MASK; +++ ath79_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE, misc); +++} +++ +++static void qca956x_irq_init(void) +++{ +++ int i; +++ +++ for (i = ATH79_IP2_IRQ_BASE; +++ i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) +++ irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq); +++ +++ irq_set_chained_handler(ATH79_CPU_IRQ(2), qca956x_ip2_irq_dispatch); +++ +++ for (i = ATH79_IP3_IRQ_BASE; +++ i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++) +++ irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq); +++ +++ irq_set_chained_handler(ATH79_CPU_IRQ(3), qca956x_ip3_irq_dispatch); +++ +++ /* QCA956x timer init workaround has to be applied right before setting +++ * up the clock. Else, there will be no jiffies */ +++ late_time_init = &qca956x_enable_timer_cb; +++} +++ ++ void __init arch_init_irq(void) ++ { ++ unsigned irq_wb_chan2 = -1; ++@@ -189,7 +270,9 @@ void __init arch_init_irq(void) ++ soc_is_ar933x() || ++ soc_is_ar934x() || ++ soc_is_qca953x() || ++- soc_is_qca955x()) +++ soc_is_qca955x() || +++ soc_is_qca956x() || +++ soc_is_tp9343()) ++ misc_is_ar71xx = false; ++ else ++ BUG(); ++@@ -203,4 +286,6 @@ void __init arch_init_irq(void) ++ qca953x_irq_init(); ++ else if (soc_is_qca955x()) ++ qca955x_irq_init(); +++ else if (soc_is_qca956x() || soc_is_tp9343()) +++ qca956x_irq_init(); ++ } ++--- a/arch/mips/ath79/pci.c +++++ b/arch/mips/ath79/pci.c ++@@ -68,6 +68,21 @@ static const struct ath79_pci_irq qca955 ++ }, ++ }; ++ +++static const struct ath79_pci_irq qca956x_pci_irq_map[] = { +++ { +++ .bus = 0, +++ .slot = 0, +++ .pin = 1, +++ .irq = ATH79_PCI_IRQ(0), +++ }, +++ { +++ .bus = 1, +++ .slot = 0, +++ .pin = 1, +++ .irq = ATH79_PCI_IRQ(1), +++ }, +++}; +++ ++ int pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) ++ { ++ int irq = -1; ++@@ -86,6 +101,9 @@ int pcibios_map_irq(const struct pci_dev ++ } else if (soc_is_qca955x()) { ++ ath79_pci_irq_map = qca955x_pci_irq_map; ++ ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map); +++ } else if (soc_is_qca956x()) { +++ ath79_pci_irq_map = qca956x_pci_irq_map; +++ ath79_pci_nr_irqs = ARRAY_SIZE(qca956x_pci_irq_map); ++ } else { ++ pr_crit("pci %s: invalid irq map\n", ++ pci_name((struct pci_dev *) dev)); ++@@ -303,6 +321,15 @@ int __init ath79_register_pci(void) ++ QCA955X_PCI_MEM_SIZE, ++ 1, ++ ATH79_IP3_IRQ(2)); +++ } else if (soc_is_qca956x()) { +++ pdev = ath79_register_pci_ar724x(0, +++ QCA956X_PCI_CFG_BASE1, +++ QCA956X_PCI_CTRL_BASE1, +++ QCA956X_PCI_CRP_BASE1, +++ QCA956X_PCI_MEM_BASE1, +++ QCA956X_PCI_MEM_SIZE, +++ 1, +++ ATH79_IP3_IRQ(2)); ++ } else { ++ /* No PCI support */ ++ return -ENODEV; ++--- a/arch/mips/ath79/setup.c +++++ b/arch/mips/ath79/setup.c ++@@ -176,6 +176,18 @@ static void __init ath79_detect_sys_type ++ rev = id & QCA955X_REV_ID_REVISION_MASK; ++ break; ++ +++ case REV_ID_MAJOR_QCA956X: +++ ath79_soc = ATH79_SOC_QCA956X; +++ chip = "956X"; +++ rev = id & QCA956X_REV_ID_REVISION_MASK; +++ break; +++ +++ case REV_ID_MAJOR_TP9343: +++ ath79_soc = ATH79_SOC_TP9343; +++ chip = "9343"; +++ rev = id & QCA956X_REV_ID_REVISION_MASK; +++ break; +++ ++ default: ++ panic("ath79: unknown SoC, id:0x%08x", id); ++ } ++@@ -183,9 +195,12 @@ static void __init ath79_detect_sys_type ++ if (ver == 1) ++ ath79_soc_rev = rev; ++ ++- if (soc_is_qca953x() || soc_is_qca955x()) +++ if (soc_is_qca953x() || soc_is_qca955x() || soc_is_qca956x()) ++ sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s ver %u rev %u", ++ chip, ver, rev); +++ else if (soc_is_tp9343()) +++ sprintf(ath79_sys_type, "Qualcomm Atheros TP%s rev %u", +++ chip, rev); ++ else ++ sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); ++ pr_info("SoC: %s\n", ath79_sys_type); ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -143,6 +143,23 @@ ++ #define QCA955X_NFC_BASE 0x1b800200 ++ #define QCA955X_NFC_SIZE 0xb8 ++ +++#define QCA956X_PCI_MEM_BASE1 0x12000000 +++#define QCA956X_PCI_MEM_SIZE 0x02000000 +++#define QCA956X_PCI_CFG_BASE1 0x16000000 +++#define QCA956X_PCI_CFG_SIZE 0x1000 +++#define QCA956X_PCI_CRP_BASE1 (AR71XX_APB_BASE + 0x00250000) +++#define QCA956X_PCI_CRP_SIZE 0x1000 +++#define QCA956X_PCI_CTRL_BASE1 (AR71XX_APB_BASE + 0x00280000) +++#define QCA956X_PCI_CTRL_SIZE 0x100 +++ +++#define QCA956X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) +++#define QCA956X_WMAC_SIZE 0x20000 +++#define QCA956X_EHCI0_BASE 0x1b000000 +++#define QCA956X_EHCI1_BASE 0x1b400000 +++#define QCA956X_EHCI_SIZE 0x200 +++#define QCA956X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +++#define QCA956X_GMAC_SIZE 0x64 +++ ++ #define AR9300_OTP_BASE 0x14000 ++ #define AR9300_OTP_STATUS 0x15f18 ++ #define AR9300_OTP_STATUS_TYPE 0x7 ++@@ -152,6 +169,13 @@ ++ #define AR9300_OTP_READ_DATA 0x15f1c ++ ++ /* +++ * Hidden Registers +++ */ +++#define QCA956X_DAM_RESET_OFFSET 0xb90001bc +++#define QCA956X_DAM_RESET_SIZE 0x4 +++#define QCA956X_INLINE_CHKSUM_ENG BIT(27) +++ +++/* ++ * DDR_CTRL block ++ */ ++ #define AR71XX_DDR_REG_PCI_WIN0 0x7c ++@@ -385,6 +409,49 @@ ++ #define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) ++ #define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) ++ +++#define QCA956X_PLL_CPU_CONFIG_REG 0x00 +++#define QCA956X_PLL_CPU_CONFIG1_REG 0x04 +++#define QCA956X_PLL_DDR_CONFIG_REG 0x08 +++#define QCA956X_PLL_DDR_CONFIG1_REG 0x0c +++#define QCA956X_PLL_CLK_CTRL_REG 0x10 +++ +++#define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +++#define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +++#define QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +++#define QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 +++ +++#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT 0 +++#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK 0x1f +++#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT 5 +++#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK 0x1fff +++#define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT 18 +++#define QCA956X_PLL_CPU_CONFIG1_NINT_MASK 0x1ff +++ +++#define QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +++#define QCA956X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +++#define QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +++#define QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 +++ +++#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT 0 +++#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK 0x1f +++#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT 5 +++#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK 0x1fff +++#define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT 18 +++#define QCA956X_PLL_DDR_CONFIG1_NINT_MASK 0x1ff +++ +++#define QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +++#define QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +++#define QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +++#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +++#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +++#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +++#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +++#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +++#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +++#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL BIT(20) +++#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL BIT(21) +++#define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) +++ ++ /* ++ * USB_CONFIG block ++ */ ++@@ -432,6 +499,11 @@ ++ #define QCA955X_RESET_REG_BOOTSTRAP 0xb0 ++ #define QCA955X_RESET_REG_EXT_INT_STATUS 0xac ++ +++#define QCA956X_RESET_REG_RESET_MODULE 0x1c +++#define QCA956X_RESET_REG_BOOTSTRAP 0xb0 +++#define QCA956X_RESET_REG_EXT_INT_STATUS 0xac +++ +++#define MISC_INT_MIPS_SI_TIMERINT_MASK BIT(28) ++ #define MISC_INT_ETHSW BIT(12) ++ #define MISC_INT_TIMER4 BIT(10) ++ #define MISC_INT_TIMER3 BIT(9) ++@@ -606,6 +678,8 @@ ++ ++ #define QCA955X_BOOTSTRAP_REF_CLK_40 BIT(4) ++ +++#define QCA956X_BOOTSTRAP_REF_CLK_40 BIT(2) +++ ++ #define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) ++ #define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1) ++ #define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) ++@@ -673,6 +747,37 @@ ++ QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \ ++ QCA955X_EXT_INT_PCIE_RC2_INT3) ++ +++#define QCA956X_EXT_INT_WMAC_MISC BIT(0) +++#define QCA956X_EXT_INT_WMAC_TX BIT(1) +++#define QCA956X_EXT_INT_WMAC_RXLP BIT(2) +++#define QCA956X_EXT_INT_WMAC_RXHP BIT(3) +++#define QCA956X_EXT_INT_PCIE_RC1 BIT(4) +++#define QCA956X_EXT_INT_PCIE_RC1_INT0 BIT(5) +++#define QCA956X_EXT_INT_PCIE_RC1_INT1 BIT(6) +++#define QCA956X_EXT_INT_PCIE_RC1_INT2 BIT(7) +++#define QCA956X_EXT_INT_PCIE_RC1_INT3 BIT(8) +++#define QCA956X_EXT_INT_PCIE_RC2 BIT(12) +++#define QCA956X_EXT_INT_PCIE_RC2_INT0 BIT(13) +++#define QCA956X_EXT_INT_PCIE_RC2_INT1 BIT(14) +++#define QCA956X_EXT_INT_PCIE_RC2_INT2 BIT(15) +++#define QCA956X_EXT_INT_PCIE_RC2_INT3 BIT(16) +++#define QCA956X_EXT_INT_USB1 BIT(24) +++#define QCA956X_EXT_INT_USB2 BIT(28) +++ +++#define QCA956X_EXT_INT_WMAC_ALL \ +++ (QCA956X_EXT_INT_WMAC_MISC | QCA956X_EXT_INT_WMAC_TX | \ +++ QCA956X_EXT_INT_WMAC_RXLP | QCA956X_EXT_INT_WMAC_RXHP) +++ +++#define QCA956X_EXT_INT_PCIE_RC1_ALL \ +++ (QCA956X_EXT_INT_PCIE_RC1 | QCA956X_EXT_INT_PCIE_RC1_INT0 | \ +++ QCA956X_EXT_INT_PCIE_RC1_INT1 | QCA956X_EXT_INT_PCIE_RC1_INT2 | \ +++ QCA956X_EXT_INT_PCIE_RC1_INT3) +++ +++#define QCA956X_EXT_INT_PCIE_RC2_ALL \ +++ (QCA956X_EXT_INT_PCIE_RC2 | QCA956X_EXT_INT_PCIE_RC2_INT0 | \ +++ QCA956X_EXT_INT_PCIE_RC2_INT1 | QCA956X_EXT_INT_PCIE_RC2_INT2 | \ +++ QCA956X_EXT_INT_PCIE_RC2_INT3) +++ ++ #define REV_ID_MAJOR_MASK 0xfff0 ++ #define REV_ID_MAJOR_AR71XX 0x00a0 ++ #define REV_ID_MAJOR_AR913X 0x00b0 ++@@ -688,6 +793,8 @@ ++ #define REV_ID_MAJOR_QCA9533_V2 0x0160 ++ #define REV_ID_MAJOR_QCA9556 0x0130 ++ #define REV_ID_MAJOR_QCA9558 0x1130 +++#define REV_ID_MAJOR_TP9343 0x0150 +++#define REV_ID_MAJOR_QCA956X 0x1150 ++ ++ #define AR71XX_REV_ID_MINOR_MASK 0x3 ++ #define AR71XX_REV_ID_MINOR_AR7130 0x0 ++@@ -712,6 +819,8 @@ ++ ++ #define QCA955X_REV_ID_REVISION_MASK 0xf ++ +++#define QCA956X_REV_ID_REVISION_MASK 0xf +++ ++ /* ++ * SPI block ++ */ ++@@ -784,6 +893,19 @@ ++ #define QCA955X_GPIO_REG_OUT_FUNC5 0x40 ++ #define QCA955X_GPIO_REG_FUNC 0x6c ++ +++#define QCA956X_GPIO_REG_OUT_FUNC0 0x2c +++#define QCA956X_GPIO_REG_OUT_FUNC1 0x30 +++#define QCA956X_GPIO_REG_OUT_FUNC2 0x34 +++#define QCA956X_GPIO_REG_OUT_FUNC3 0x38 +++#define QCA956X_GPIO_REG_OUT_FUNC4 0x3c +++#define QCA956X_GPIO_REG_OUT_FUNC5 0x40 +++#define QCA956X_GPIO_REG_IN_ENABLE0 0x44 +++#define QCA956X_GPIO_REG_IN_ENABLE3 0x50 +++#define QCA956X_GPIO_REG_FUNC 0x6c +++ +++#define QCA956X_GPIO_OUT_MUX_GE0_MDO 32 +++#define QCA956X_GPIO_OUT_MUX_GE0_MDC 33 +++ ++ #define AR71XX_GPIO_COUNT 16 ++ #define AR7240_GPIO_COUNT 18 ++ #define AR7241_GPIO_COUNT 20 ++@@ -792,6 +914,7 @@ ++ #define AR934X_GPIO_COUNT 23 ++ #define QCA953X_GPIO_COUNT 18 ++ #define QCA955X_GPIO_COUNT 24 +++#define QCA956X_GPIO_COUNT 23 ++ ++ /* ++ * SRIF block ++--- a/arch/mips/include/asm/mach-ath79/ath79.h +++++ b/arch/mips/include/asm/mach-ath79/ath79.h ++@@ -35,6 +35,8 @@ enum ath79_soc_type { ++ ATH79_SOC_QCA9533, ++ ATH79_SOC_QCA9556, ++ ATH79_SOC_QCA9558, +++ ATH79_SOC_TP9343, +++ ATH79_SOC_QCA956X, ++ }; ++ ++ extern enum ath79_soc_type ath79_soc; ++@@ -126,6 +128,26 @@ static inline int soc_is_qca955x(void) ++ return soc_is_qca9556() || soc_is_qca9558(); ++ } ++ +++static inline int soc_is_tp9343(void) +++{ +++ return ath79_soc == ATH79_SOC_TP9343; +++} +++ +++static inline int soc_is_qca9561(void) +++{ +++ return ath79_soc == ATH79_SOC_QCA956X; +++} +++ +++static inline int soc_is_qca9563(void) +++{ +++ return ath79_soc == ATH79_SOC_QCA956X; +++} +++ +++static inline int soc_is_qca956x(void) +++{ +++ return soc_is_qca9561() || soc_is_qca9563(); +++} +++ ++ void ath79_ddr_wb_flush(unsigned int reg); ++ void ath79_ddr_set_pci_windows(void); ++ +diff --git a/target/linux/ar71xx/patches-4.14/622-MIPS-ath79-add-more-register-defines-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-4.14/622-MIPS-ath79-add-more-register-defines-for-QCA956x-SoC.patch +new file mode 100644 +index 0000000000..cab2f6f9cb +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/622-MIPS-ath79-add-more-register-defines-for-QCA956x-SoC.patch +@@ -0,0 +1,38 @@ ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -157,6 +157,10 @@ ++ #define QCA956X_EHCI0_BASE 0x1b000000 ++ #define QCA956X_EHCI1_BASE 0x1b400000 ++ #define QCA956X_EHCI_SIZE 0x200 +++#define QCA956X_GMAC_SGMII_BASE (AR71XX_APB_BASE + 0x00070000) +++#define QCA956X_GMAC_SGMII_SIZE 0x64 +++#define QCA956X_PLL_BASE (AR71XX_APB_BASE + 0x00050000) +++#define QCA956X_PLL_SIZE 0x50 ++ #define QCA956X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) ++ #define QCA956X_GMAC_SIZE 0x64 ++ ++@@ -414,6 +418,7 @@ ++ #define QCA956X_PLL_DDR_CONFIG_REG 0x08 ++ #define QCA956X_PLL_DDR_CONFIG1_REG 0x0c ++ #define QCA956X_PLL_CLK_CTRL_REG 0x10 +++#define QCA956X_PLL_ETH_XMII_CONTROL_REG 0x30 ++ ++ #define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 ++ #define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f ++@@ -1196,4 +1201,16 @@ ++ #define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3 ++ #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20 ++ +++/* +++ * QCA956X GMAC Interface +++ */ +++ +++#define QCA956X_GMAC_REG_ETH_CFG 0x00 +++ +++#define QCA956X_ETH_CFG_SW_ONLY_MODE BIT(7) +++#define QCA956X_ETH_CFG_SW_PHY_SWAP BIT(8) +++#define QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP BIT(9) +++#define QCA956X_ETH_CFG_SW_APB_ACCESS BIT(10) +++#define QCA956X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) +++ ++ #endif /* __ASM_MACH_AR71XX_REGS_H */ +diff --git a/target/linux/ar71xx/patches-4.14/630-MIPS-ath79-fix-chained-irq-disable.patch b/target/linux/ar71xx/patches-4.14/630-MIPS-ath79-fix-chained-irq-disable.patch +new file mode 100644 +index 0000000000..a74eb4f43e +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/630-MIPS-ath79-fix-chained-irq-disable.patch +@@ -0,0 +1,106 @@ ++--- a/arch/mips/ath79/irq.c +++++ b/arch/mips/ath79/irq.c ++@@ -27,6 +27,9 @@ ++ #include "machtypes.h" ++ ++ +++static struct irq_chip ip2_chip; +++static struct irq_chip ip3_chip; +++ ++ static void ar934x_ip2_irq_dispatch(struct irq_desc *desc) ++ { ++ u32 status; ++@@ -56,8 +59,7 @@ static void ar934x_ip2_irq_init(void) ++ ++ for (i = ATH79_IP2_IRQ_BASE; ++ i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) ++- irq_set_chip_and_handler(i, &dummy_irq_chip, ++- handle_level_irq); +++ irq_set_chip_and_handler(i, &ip2_chip, handle_level_irq); ++ ++ irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch); ++ } ++@@ -85,7 +87,7 @@ static void qca953x_irq_init(void) ++ ++ for (i = ATH79_IP2_IRQ_BASE; ++ i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) ++- irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq); +++ irq_set_chip_and_handler(i, &ip2_chip, handle_level_irq); ++ ++ irq_set_chained_handler(ATH79_CPU_IRQ(2), qca953x_ip2_irq_dispatch); ++ } ++@@ -149,15 +151,13 @@ static void qca955x_irq_init(void) ++ ++ for (i = ATH79_IP2_IRQ_BASE; ++ i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) ++- irq_set_chip_and_handler(i, &dummy_irq_chip, ++- handle_level_irq); +++ irq_set_chip_and_handler(i, &ip2_chip, handle_level_irq); ++ ++ irq_set_chained_handler(ATH79_CPU_IRQ(2), qca955x_ip2_irq_dispatch); ++ ++ for (i = ATH79_IP3_IRQ_BASE; ++ i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++) ++- irq_set_chip_and_handler(i, &dummy_irq_chip, ++- handle_level_irq); +++ irq_set_chip_and_handler(i, &ip3_chip, handle_level_irq); ++ ++ irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); ++ } ++@@ -228,13 +228,13 @@ static void qca956x_irq_init(void) ++ ++ for (i = ATH79_IP2_IRQ_BASE; ++ i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) ++- irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq); +++ irq_set_chip_and_handler(i, &ip2_chip, handle_level_irq); ++ ++ irq_set_chained_handler(ATH79_CPU_IRQ(2), qca956x_ip2_irq_dispatch); ++ ++ for (i = ATH79_IP3_IRQ_BASE; ++ i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++) ++- irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq); +++ irq_set_chip_and_handler(i, &ip3_chip, handle_level_irq); ++ ++ irq_set_chained_handler(ATH79_CPU_IRQ(3), qca956x_ip3_irq_dispatch); ++ ++@@ -243,12 +243,40 @@ static void qca956x_irq_init(void) ++ late_time_init = &qca956x_enable_timer_cb; ++ } ++ +++static void ath79_ip2_disable(struct irq_data *data) +++{ +++ disable_irq(ATH79_CPU_IRQ(2)); +++} +++ +++static void ath79_ip2_enable(struct irq_data *data) +++{ +++ enable_irq(ATH79_CPU_IRQ(2)); +++} +++ +++static void ath79_ip3_disable(struct irq_data *data) +++{ +++ disable_irq(ATH79_CPU_IRQ(3)); +++} +++ +++static void ath79_ip3_enable(struct irq_data *data) +++{ +++ enable_irq(ATH79_CPU_IRQ(3)); +++} +++ ++ void __init arch_init_irq(void) ++ { ++ unsigned irq_wb_chan2 = -1; ++ unsigned irq_wb_chan3 = -1; ++ bool misc_is_ar71xx; ++ +++ ip2_chip = dummy_irq_chip; +++ ip2_chip.irq_disable = ath79_ip2_disable; +++ ip2_chip.irq_enable = ath79_ip2_enable; +++ +++ ip3_chip = dummy_irq_chip; +++ ip3_chip.irq_disable = ath79_ip3_disable; +++ ip3_chip.irq_enable = ath79_ip3_enable; +++ ++ if (mips_machtype == ATH79_MACH_GENERIC_OF) { ++ irqchip_init(); ++ return; +diff --git a/target/linux/ar71xx/patches-4.14/631-MIPS-ath79-wmac-enable-set-led-pin.patch b/target/linux/ar71xx/patches-4.14/631-MIPS-ath79-wmac-enable-set-led-pin.patch +new file mode 100644 +index 0000000000..a312217711 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/631-MIPS-ath79-wmac-enable-set-led-pin.patch +@@ -0,0 +1,24 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -406,6 +406,11 @@ void __init ath79_wmac_set_ext_lna_gpio( ++ ar934x_set_ext_lna_gpio(chain, gpio); ++ } ++ +++void __init ath79_wmac_set_led_pin(int gpio) +++{ +++ ath79_wmac_data.led_pin = gpio; +++} +++ ++ void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) ++ { ++ if (soc_is_ar913x()) ++--- a/arch/mips/ath79/dev-wmac.h +++++ b/arch/mips/ath79/dev-wmac.h ++@@ -18,6 +18,7 @@ void ath79_wmac_disable_2ghz(void); ++ void ath79_wmac_disable_5ghz(void); ++ void ath79_wmac_set_tx_gain_buffalo(void); ++ void ath79_wmac_set_ext_lna_gpio(unsigned chain, int gpio); +++void ath79_wmac_set_led_pin(int gpio); ++ ++ bool ar93xx_wmac_read_mac_address(u8 *dest); ++ +diff --git a/target/linux/ar71xx/patches-4.14/632-MIPS-ath79-gpio-enable-set-direction.patch b/target/linux/ar71xx/patches-4.14/632-MIPS-ath79-gpio-enable-set-direction.patch +new file mode 100644 +index 0000000000..4cf36325e1 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/632-MIPS-ath79-gpio-enable-set-direction.patch +@@ -0,0 +1,32 @@ ++--- a/arch/mips/ath79/common.h +++++ b/arch/mips/ath79/common.h ++@@ -28,6 +28,7 @@ void ath79_gpio_function_enable(u32 mask ++ void ath79_gpio_function_disable(u32 mask); ++ void ath79_gpio_function_setup(u32 set, u32 clear); ++ void ath79_gpio_output_select(unsigned gpio, u8 val); +++int ath79_gpio_direction_select(unsigned gpio, bool oe); ++ void ath79_gpio_init(void); ++ ++ #endif /* __ATH79_COMMON_H */ ++--- a/arch/mips/ath79/gpio.c +++++ b/arch/mips/ath79/gpio.c ++@@ -83,3 +83,19 @@ void __init ath79_gpio_output_select(uns ++ /* flush write */ ++ (void) __raw_readl(base + reg); ++ } +++ +++int ath79_gpio_direction_select(unsigned gpio, bool oe) +++{ +++ void __iomem *base = ath79_gpio_base; +++ bool ieq_1 = (soc_is_ar934x() || +++ soc_is_qca953x()); +++ +++ if ((ieq_1 && oe) || (!ieq_1 && !oe)) +++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << gpio), +++ base + AR71XX_GPIO_REG_OE); +++ else +++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << gpio), +++ base + AR71XX_GPIO_REG_OE); +++ +++ return 0; +++} +diff --git a/target/linux/ar71xx/patches-4.14/640-MIPS-ath79-add-QCA955x-wmac-reset.patch b/target/linux/ar71xx/patches-4.14/640-MIPS-ath79-add-QCA955x-wmac-reset.patch +new file mode 100644 +index 0000000000..bb315a1e65 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/640-MIPS-ath79-add-QCA955x-wmac-reset.patch +@@ -0,0 +1,82 @@ ++--- a/arch/mips/ath79/common.c +++++ b/arch/mips/ath79/common.c ++@@ -38,7 +38,7 @@ unsigned int ath79_soc_rev; ++ void __iomem *ath79_pll_base; ++ void __iomem *ath79_reset_base; ++ EXPORT_SYMBOL_GPL(ath79_reset_base); ++-static void __iomem *ath79_ddr_base; +++void __iomem *ath79_ddr_base; ++ static void __iomem *ath79_ddr_wb_flush_base; ++ static void __iomem *ath79_ddr_pci_win_base; ++ ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -32,7 +32,7 @@ ++ #define AR71XX_SPI_SIZE 0x01000000 ++ ++ #define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000) ++-#define AR71XX_DDR_CTRL_SIZE 0x100 +++#define AR71XX_DDR_CTRL_SIZE 0x200 ++ #define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000) ++ #define AR71XX_UART_SIZE 0x100 ++ #define AR71XX_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) ++@@ -229,6 +229,9 @@ ++ #define QCA953X_DDR_REG_FLUSH_PCIE 0xa8 ++ #define QCA953X_DDR_REG_FLUSH_WMAC 0xac ++ +++#define QCA955X_DDR_CTL_CONFIG 0x108 +++#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23) +++ ++ /* ++ * PLL block ++ */ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -165,6 +165,27 @@ static void qca953x_wmac_setup(void) ++ ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; ++ } ++ +++static int ar955x_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; +++} +++ ++ static void qca955x_wmac_setup(void) ++ { ++ u32 t; ++@@ -181,6 +202,8 @@ static void qca955x_wmac_setup(void) ++ ath79_wmac_data.is_clk_25mhz = false; ++ else ++ ath79_wmac_data.is_clk_25mhz = true; +++ +++ ath79_wmac_data.external_reset = ar955x_wmac_reset; ++ } ++ ++ #define AR93XX_WMAC_SIZE \ ++--- a/arch/mips/ath79/common.h +++++ b/arch/mips/ath79/common.h ++@@ -19,6 +19,8 @@ ++ #define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024) ++ #define ATH79_MEM_SIZE_MAX (256 * 1024 * 1024) ++ +++extern void __iomem *ath79_ddr_base; +++ ++ void ath79_clocks_init(void); ++ unsigned long ath79_get_sys_clk_rate(const char *id); ++ +diff --git a/target/linux/ar71xx/patches-4.14/700-MIPS-ath79-add-openwrt-Kconfig.patch b/target/linux/ar71xx/patches-4.14/700-MIPS-ath79-add-openwrt-Kconfig.patch +new file mode 100644 +index 0000000000..093def8d11 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/700-MIPS-ath79-add-openwrt-Kconfig.patch +@@ -0,0 +1,11 @@ ++--- a/arch/mips/ath79/Kconfig +++++ b/arch/mips/ath79/Kconfig ++@@ -83,6 +83,8 @@ config ATH79_MACH_UBNT_XM ++ Say 'Y' here if you want your kernel to support the ++ Ubiquiti Networks XM (rev 1.0) board. ++ +++source "arch/mips/ath79/Kconfig.openwrt" +++ ++ endmenu ++ ++ config SOC_AR71XX +diff --git a/target/linux/ar71xx/patches-4.14/701-MIPS-ath79-add-routerboard-detection.patch b/target/linux/ar71xx/patches-4.14/701-MIPS-ath79-add-routerboard-detection.patch +new file mode 100644 +index 0000000000..ae9e7772b5 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/701-MIPS-ath79-add-routerboard-detection.patch +@@ -0,0 +1,35 @@ ++--- a/arch/mips/ath79/prom.c +++++ b/arch/mips/ath79/prom.c ++@@ -136,6 +136,32 @@ void __init prom_init(void) ++ initrd_end = initrd_start + fw_getenvl("initrd_size"); ++ } ++ #endif +++ +++ if (strstr(arcs_cmdline, "board=750Gr3") || +++ strstr(arcs_cmdline, "board=750i") || +++ strstr(arcs_cmdline, "board=750-hb") || +++ strstr(arcs_cmdline, "board=411") || +++ strstr(arcs_cmdline, "board=433") || +++ strstr(arcs_cmdline, "board=435") || +++ strstr(arcs_cmdline, "board=450") || +++ strstr(arcs_cmdline, "board=493") || +++ strstr(arcs_cmdline, "board=951G") || +++ strstr(arcs_cmdline, "board=H951L") || +++ strstr(arcs_cmdline, "board=952-hb") || +++ strstr(arcs_cmdline, "board=953gs") || +++ strstr(arcs_cmdline, "board=962") || +++ strstr(arcs_cmdline, "board=lhg") || +++ strstr(arcs_cmdline, "board=map-hb") || +++ strstr(arcs_cmdline, "board=map2-hb") || +++ strstr(arcs_cmdline, "board=wap-hb") || +++ strstr(arcs_cmdline, "board=wap-lte") || +++ strstr(arcs_cmdline, "board=wapg-sc") || +++ strstr(arcs_cmdline, "board=2011L") || +++ strstr(arcs_cmdline, "board=2011r") || +++ strstr(arcs_cmdline, "board=711Gr100") || +++ strstr(arcs_cmdline, "board=911L") || +++ strstr(arcs_cmdline, "board=922gs")) +++ ath79_prom_append_cmdline("console", "ttyS0,115200"); ++ } ++ ++ void __init prom_free_prom_memory(void) +diff --git a/target/linux/ar71xx/patches-4.14/702-MIPS-ath79-fixup-routerboot-board-parameter.patch b/target/linux/ar71xx/patches-4.14/702-MIPS-ath79-fixup-routerboot-board-parameter.patch +new file mode 100644 +index 0000000000..b8715bba9e +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/702-MIPS-ath79-fixup-routerboot-board-parameter.patch +@@ -0,0 +1,43 @@ ++From: Gabor Juhos ++Date: Sat, 2 Dec 2017 19:15:29 +0100 ++Subject: [PATCH] MIPS: ath79: fix board detection with newer RouterBOOT versions ++ ++Recent RouterBOOT version (at least version 3.41 on RB911G-5HPacD) ++use "Board=" kernel parameter instead of "board=" to pass the board ++name to the kernel. Due to this change the board detection code is ++not working on the devices shipped with the new RouterBOOT version. ++Because the kernel is unable to identify these boards they become ++unusable despite that they are supported by the current code. ++ ++Update the prom_init code to convert the 'Board' kernel parameter to ++'board'. After this change, the board detection works also with the ++new RouterBOOT versions. ++ ++Signed-off-by: Gabor Juhos ++--- ++--- a/arch/mips/ath79/prom.c +++++ b/arch/mips/ath79/prom.c ++@@ -104,6 +104,7 @@ static int __init ath79_prom_init_myload ++ void __init prom_init(void) ++ { ++ const char *env; +++ char *c; ++ ++ if (ath79_prom_init_myloader()) ++ return; ++@@ -137,6 +138,15 @@ void __init prom_init(void) ++ } ++ #endif ++ +++ /* +++ * RouterBOOT uses "Board" kernel parameter instead of "board" since +++ * version 3.41 (or so). Replace the first character of the parameter +++ * to keep board detection working. +++ */ +++ c = strstr(arcs_cmdline, "Board="); +++ if (c) +++ c[0] = 'b'; +++ ++ if (strstr(arcs_cmdline, "board=750Gr3") || ++ strstr(arcs_cmdline, "board=750i") || ++ strstr(arcs_cmdline, "board=750-hb") || +diff --git a/target/linux/ar71xx/patches-4.14/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch b/target/linux/ar71xx/patches-4.14/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch +new file mode 100644 +index 0000000000..a65f7d993f +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch +@@ -0,0 +1,38 @@ ++--- a/arch/mips/ath79/gpio.c +++++ b/arch/mips/ath79/gpio.c ++@@ -33,6 +33,7 @@ static void __iomem *ath79_gpio_get_func ++ reg = AR71XX_GPIO_REG_FUNC; ++ else if (soc_is_ar934x() || ++ soc_is_qca953x() || +++ soc_is_qca955x() || ++ soc_is_qca956x() || ++ soc_is_tp9343()) ++ reg = AR934X_GPIO_REG_FUNC; ++@@ -64,15 +65,21 @@ void ath79_gpio_function_disable(u32 mas ++ void __init ath79_gpio_output_select(unsigned gpio, u8 val) ++ { ++ void __iomem *base = ath79_gpio_base; ++- unsigned int reg; +++ unsigned int reg, reg_base; ++ u32 t, s; ++ ++- BUG_ON(!soc_is_ar934x() && !soc_is_qca953x() && !soc_is_qca956x()); ++- ++- if (gpio >= AR934X_GPIO_COUNT) ++- return; +++ if (soc_is_ar934x()) +++ reg_base = AR934X_GPIO_REG_OUT_FUNC0; +++ else if (soc_is_qca953x()) +++ reg_base = QCA953X_GPIO_REG_OUT_FUNC0; +++ else if (soc_is_qca955x()) +++ reg_base = QCA955X_GPIO_REG_OUT_FUNC0; +++ else if (soc_is_qca956x()) +++ reg_base = QCA956X_GPIO_REG_OUT_FUNC0; +++ else +++ BUG(); ++ ++- reg = AR934X_GPIO_REG_OUT_FUNC0 + 4 * (gpio / 4); +++ reg = reg_base + 4 * (gpio / 4); ++ s = 8 * (gpio % 4); ++ ++ t = __raw_readl(base + reg); +diff --git a/target/linux/ar71xx/patches-4.14/740-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch b/target/linux/ar71xx/patches-4.14/740-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch +new file mode 100644 +index 0000000000..659f74451c +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/740-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch +@@ -0,0 +1,44 @@ ++--- a/arch/mips/ath79/pci.c +++++ b/arch/mips/ath79/pci.c ++@@ -53,6 +53,15 @@ static const struct ath79_pci_irq ar724x ++ } ++ }; ++ +++static const struct ath79_pci_irq qca953x_pci_irq_map[] = { +++ { +++ .bus = 0, +++ .slot = 0, +++ .pin = 1, +++ .irq = ATH79_PCI_IRQ(0), +++ }, +++}; +++ ++ static const struct ath79_pci_irq qca955x_pci_irq_map[] = { ++ { ++ .bus = 0, ++@@ -98,6 +107,9 @@ int pcibios_map_irq(const struct pci_dev ++ soc_is_ar9344()) { ++ ath79_pci_irq_map = ar724x_pci_irq_map; ++ ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map); +++ } else if (soc_is_qca953x()) { +++ ath79_pci_irq_map = qca953x_pci_irq_map; +++ ath79_pci_nr_irqs = ARRAY_SIZE(qca953x_pci_irq_map); ++ } else if (soc_is_qca955x()) { ++ ath79_pci_irq_map = qca955x_pci_irq_map; ++ ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map); ++@@ -303,6 +315,15 @@ int __init ath79_register_pci(void) ++ AR724X_PCI_MEM_SIZE, ++ 0, ++ ATH79_IP2_IRQ(0)); +++ } else if (soc_is_qca9533()) { +++ pdev = ath79_register_pci_ar724x(0, +++ QCA953X_PCI_CFG_BASE0, +++ QCA953X_PCI_CTRL_BASE0, +++ QCA953X_PCI_CRP_BASE0, +++ QCA953X_PCI_MEM_BASE0, +++ QCA953X_PCI_MEM_SIZE, +++ 0, +++ ATH79_IP2_IRQ(0)); ++ } else if (soc_is_qca9558()) { ++ pdev = ath79_register_pci_ar724x(0, ++ QCA955X_PCI_CFG_BASE0, +diff --git a/target/linux/ar71xx/patches-4.14/741-MIPS-ath79-add-PCI-for-QCA9556-SoC.patch b/target/linux/ar71xx/patches-4.14/741-MIPS-ath79-add-PCI-for-QCA9556-SoC.patch +new file mode 100644 +index 0000000000..5ca0784253 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/741-MIPS-ath79-add-PCI-for-QCA9556-SoC.patch +@@ -0,0 +1,12 @@ ++--- a/arch/mips/ath79/pci.c +++++ b/arch/mips/ath79/pci.c ++@@ -324,7 +324,8 @@ int __init ath79_register_pci(void) ++ QCA953X_PCI_MEM_SIZE, ++ 0, ++ ATH79_IP2_IRQ(0)); ++- } else if (soc_is_qca9558()) { +++ } else if (soc_is_qca9558() || +++ soc_is_qca9556()) { ++ pdev = ath79_register_pci_ar724x(0, ++ QCA955X_PCI_CFG_BASE0, ++ QCA955X_PCI_CTRL_BASE0, +diff --git a/target/linux/ar71xx/patches-4.14/818-MIPS-ath79-add-nu801-led-driver.patch b/target/linux/ar71xx/patches-4.14/818-MIPS-ath79-add-nu801-led-driver.patch +new file mode 100644 +index 0000000000..349c43d9fb +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/818-MIPS-ath79-add-nu801-led-driver.patch +@@ -0,0 +1,26 @@ ++--- a/drivers/leds/Kconfig +++++ b/drivers/leds/Kconfig ++@@ -632,6 +632,13 @@ config LEDS_IS31FL32XX ++ ++ comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)" ++ +++config LEDS_NU801 +++ tristate "LED driver for NU801 RGB LED" +++ depends on LEDS_CLASS && (ATH79_MACH_MR18 || ATH79_MACH_Z1) +++ help +++ This option enables support for NU801 RGB LED driver chips +++ accessed via GPIO. +++ ++ config LEDS_BLINKM ++ tristate "LED support for the BlinkM I2C RGB LED" ++ depends on LEDS_CLASS ++--- a/drivers/leds/Makefile +++++ b/drivers/leds/Makefile ++@@ -58,6 +58,7 @@ obj-$(CONFIG_LEDS_LT3593) += leds-lt359 ++ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o ++ obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o ++ obj-$(CONFIG_LEDS_RB750) += leds-rb750.o +++obj-$(CONFIG_LEDS_NU801) += leds-nu801.o ++ obj-$(CONFIG_LEDS_NS2) += leds-ns2.o ++ obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o ++ obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o +diff --git a/target/linux/ar71xx/patches-4.14/820-MIPS-ath79-add_gpio_function2_setup.patch b/target/linux/ar71xx/patches-4.14/820-MIPS-ath79-add_gpio_function2_setup.patch +new file mode 100644 +index 0000000000..afa7b69b43 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/820-MIPS-ath79-add_gpio_function2_setup.patch +@@ -0,0 +1,67 @@ ++Add access to the function2 gpio register. This probably has to be ++converted into a pimux driver later on. This is needed for some setup ++functions on the Arduino Yun. ++ ++--- a/arch/mips/ath79/common.h +++++ b/arch/mips/ath79/common.h ++@@ -29,6 +29,7 @@ void ath79_ddr_ctrl_init(void); ++ void ath79_gpio_function_enable(u32 mask); ++ void ath79_gpio_function_disable(u32 mask); ++ void ath79_gpio_function_setup(u32 set, u32 clear); +++void ath79_gpio_function2_setup(u32 set, u32 clear); ++ void ath79_gpio_output_select(unsigned gpio, u8 val); ++ int ath79_gpio_direction_select(unsigned gpio, bool oe); ++ void ath79_gpio_init(void); ++--- a/arch/mips/ath79/gpio.c +++++ b/arch/mips/ath79/gpio.c ++@@ -43,6 +43,31 @@ static void __iomem *ath79_gpio_get_func ++ return ath79_gpio_base + reg; ++ } ++ +++static void __iomem *ath79_gpio_get_function2_reg(void) +++{ +++ u32 reg = 0; +++ +++ if (soc_is_ar71xx() || +++ soc_is_ar724x() || +++ soc_is_ar913x() || +++ soc_is_ar933x()) +++ reg = AR71XX_GPIO_REG_FUNC_2; +++ else +++ BUG(); +++ +++ return ath79_gpio_base + reg; +++} +++ +++ +++void ath79_gpio_function2_setup(u32 set, u32 clear) +++{ +++ void __iomem *reg = ath79_gpio_get_function2_reg(); +++ +++ __raw_writel((__raw_readl(reg) & ~clear) | set, reg); +++ /* flush write */ +++ __raw_readl(reg); +++} +++ ++ void ath79_gpio_function_setup(u32 set, u32 clear) ++ { ++ void __iomem *reg = ath79_gpio_get_function_reg(); ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -865,6 +865,7 @@ ++ #define AR71XX_GPIO_REG_INT_PENDING 0x20 ++ #define AR71XX_GPIO_REG_INT_ENABLE 0x24 ++ #define AR71XX_GPIO_REG_FUNC 0x28 +++#define AR71XX_GPIO_REG_FUNC_2 0x30 ++ ++ #define AR934X_GPIO_REG_OUT_FUNC0 0x2c ++ #define AR934X_GPIO_REG_OUT_FUNC1 0x30 ++@@ -989,6 +990,8 @@ ++ #define AR724X_GPIO_FUNC_UART_EN BIT(1) ++ #define AR724X_GPIO_FUNC_JTAG_DISABLE BIT(0) ++ +++#define AR933X_GPIO_FUNC2_JUMPSTART_DISABLE BIT(9) +++ ++ #define AR913X_GPIO_FUNC_WMAC_LED_EN BIT(22) ++ #define AR913X_GPIO_FUNC_EXP_PORT_CS_EN BIT(21) ++ #define AR913X_GPIO_FUNC_I2S_REFCLKEN BIT(20) +diff --git a/target/linux/ar71xx/patches-4.14/821-serial-core-add-support-for-boot-console-with-arbitr.patch b/target/linux/ar71xx/patches-4.14/821-serial-core-add-support-for-boot-console-with-arbitr.patch +new file mode 100644 +index 0000000000..23b6d73959 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/821-serial-core-add-support-for-boot-console-with-arbitr.patch +@@ -0,0 +1,54 @@ ++From 4d3c17975c7814884a721fe693b3adf5c426d759 Mon Sep 17 00:00:00 2001 ++From: Hauke Mehrtens ++Date: Tue, 10 Nov 2015 22:18:39 +0100 ++Subject: [RFC] serial: core: add support for boot console with arbitrary ++ baud rates ++ ++The Arduino Yun uses a baud rate of 250000 by default. The serial is ++going over the Atmel ATmega and is used to connect to this chip. ++Without this patch Linux wants to switch the console to 9600 Baud. ++ ++With this patch Linux will use the configured baud rate and not a ++default one specified in uart_register_driver(). ++ ++Signed-off-by: Hauke Mehrtens ++[rebased to 4.14, slightly reworded commit message] ++Signed-off-by: Sungbo Eo ++--- ++ drivers/tty/serial/serial_core.c | 6 +++++- ++ include/linux/console.h | 1 + ++ 2 files changed, 6 insertions(+), 1 deletions(-) ++ ++--- a/drivers/tty/serial/serial_core.c +++++ b/drivers/tty/serial/serial_core.c ++@@ -232,6 +232,8 @@ static int uart_port_startup(struct tty_ ++ if (retval == 0) { ++ if (uart_console(uport) && uport->cons->cflag) { ++ tty->termios.c_cflag = uport->cons->cflag; +++ tty->termios.c_ospeed = uport->cons->baud; +++ tty->termios.c_ispeed = uport->cons->baud; ++ uport->cons->cflag = 0; ++ } ++ /* ++@@ -2072,8 +2074,10 @@ uart_set_options(struct uart_port *port, ++ * Allow the setting of the UART parameters with a NULL console ++ * too: ++ */ ++- if (co) +++ if (co) { ++ co->cflag = termios.c_cflag; +++ co->baud = baud; +++ } ++ ++ return 0; ++ } ++--- a/include/linux/console.h +++++ b/include/linux/console.h ++@@ -145,6 +145,7 @@ struct console { ++ short flags; ++ short index; ++ int cflag; +++ int baud; ++ void *data; ++ struct console *next; ++ }; +diff --git a/target/linux/ar71xx/patches-4.14/900-mdio_bitbang_ignore_ta_value.patch b/target/linux/ar71xx/patches-4.14/900-mdio_bitbang_ignore_ta_value.patch +new file mode 100644 +index 0000000000..8f8f349a66 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/900-mdio_bitbang_ignore_ta_value.patch +@@ -0,0 +1,32 @@ ++--- a/drivers/net/phy/mdio-bitbang.c +++++ b/drivers/net/phy/mdio-bitbang.c ++@@ -155,7 +155,7 @@ static int mdiobb_cmd_addr(struct mdiobb ++ static int mdiobb_read(struct mii_bus *bus, int phy, int reg) ++ { ++ struct mdiobb_ctrl *ctrl = bus->priv; ++- int ret, i; +++ int ret; ++ ++ if (reg & MII_ADDR_C45) { ++ reg = mdiobb_cmd_addr(ctrl, phy, reg); ++@@ -165,19 +165,7 @@ static int mdiobb_read(struct mii_bus *b ++ ++ ctrl->ops->set_mdio_dir(ctrl, 0); ++ ++- /* check the turnaround bit: the PHY should be driving it to zero, if this ++- * PHY is listed in phy_ignore_ta_mask as having broken TA, skip that ++- */ ++- if (mdiobb_get_bit(ctrl) != 0 && ++- !(bus->phy_ignore_ta_mask & (1 << phy))) { ++- /* PHY didn't drive TA low -- flush any bits it ++- * may be trying to send. ++- */ ++- for (i = 0; i < 32; i++) ++- mdiobb_get_bit(ctrl); ++- ++- return 0xffff; ++- } +++ mdiobb_get_bit(ctrl); ++ ++ ret = mdiobb_get_num(ctrl, 16); ++ mdiobb_get_bit(ctrl); +diff --git a/target/linux/ar71xx/patches-4.14/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch b/target/linux/ar71xx/patches-4.14/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch +new file mode 100644 +index 0000000000..a830346a31 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch +@@ -0,0 +1,61 @@ ++From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001 ++From: Jonas Gorski ++Date: Tue, 16 Jun 2015 13:15:08 +0200 ++Subject: [PATCH] phy/mdio-bitbang: prevent rescheduling during command ++ ++It seems some phys have some maximum timings for accessing the MDIO line, ++resulting in bit errors under cpu stress. Prevent this from happening by ++disabling interrupts when sending commands. ++ ++Signed-off-by: Jonas Gorski ++--- ++ drivers/net/phy/mdio-bitbang.c | 9 +++++++++ ++ 1 file changed, 9 insertions(+) ++ ++--- a/drivers/net/phy/mdio-bitbang.c +++++ b/drivers/net/phy/mdio-bitbang.c ++@@ -17,6 +17,7 @@ ++ * kind, whether express or implied. ++ */ ++ +++#include ++ #include ++ #include ++ #include ++@@ -156,7 +157,9 @@ static int mdiobb_read(struct mii_bus *b ++ { ++ struct mdiobb_ctrl *ctrl = bus->priv; ++ int ret; +++ unsigned long flags; ++ +++ local_irq_save(flags); ++ if (reg & MII_ADDR_C45) { ++ reg = mdiobb_cmd_addr(ctrl, phy, reg); ++ mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); ++@@ -169,13 +172,17 @@ static int mdiobb_read(struct mii_bus *b ++ ++ ret = mdiobb_get_num(ctrl, 16); ++ mdiobb_get_bit(ctrl); +++ local_irq_restore(flags); +++ ++ return ret; ++ } ++ ++ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) ++ { ++ struct mdiobb_ctrl *ctrl = bus->priv; +++ unsigned long flags; ++ +++ local_irq_save(flags); ++ if (reg & MII_ADDR_C45) { ++ reg = mdiobb_cmd_addr(ctrl, phy, reg); ++ mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); ++@@ -190,6 +197,8 @@ static int mdiobb_write(struct mii_bus * ++ ++ ctrl->ops->set_mdio_dir(ctrl, 0); ++ mdiobb_get_bit(ctrl); +++ local_irq_restore(flags); +++ ++ return 0; ++ } ++ +diff --git a/target/linux/ar71xx/patches-4.14/902-at803x-add-reset-gpio-pdata.patch b/target/linux/ar71xx/patches-4.14/902-at803x-add-reset-gpio-pdata.patch +new file mode 100644 +index 0000000000..e4e51963bb +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/902-at803x-add-reset-gpio-pdata.patch +@@ -0,0 +1,68 @@ ++Add support for configuring AT803x GPIO reset via platform data. ++This is necessary, because ath79 is not converted to device tree yet. ++ ++Signed-off-by: Felix Fietkau ++ ++--- a/include/linux/platform_data/phy-at803x.h +++++ b/include/linux/platform_data/phy-at803x.h ++@@ -6,6 +6,8 @@ struct at803x_platform_data { ++ int enable_rgmii_tx_delay:1; ++ int enable_rgmii_rx_delay:1; ++ int fixup_rgmii_tx_delay:1; +++ int has_reset_gpio:1; +++ int reset_gpio; ++ }; ++ ++ #endif /* _PHY_AT803X_PDATA_H */ ++--- a/drivers/net/phy/at803x.c +++++ b/drivers/net/phy/at803x.c ++@@ -259,6 +259,7 @@ static int at803x_resume(struct phy_devi ++ ++ static int at803x_probe(struct phy_device *phydev) ++ { +++ struct at803x_platform_data *pdata; ++ struct device *dev = &phydev->mdio.dev; ++ struct at803x_priv *priv; ++ struct gpio_desc *gpiod_reset; ++@@ -271,6 +272,12 @@ static int at803x_probe(struct phy_devic ++ phydev->drv->phy_id != ATH8032_PHY_ID) ++ goto does_not_require_reset_workaround; ++ +++ pdata = dev_get_platdata(dev); +++ if (pdata && pdata->has_reset_gpio) { +++ devm_gpio_request(dev, pdata->reset_gpio, "reset"); +++ gpio_direction_output(pdata->reset_gpio, 1); +++ } +++ ++ gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); ++ if (IS_ERR(gpiod_reset)) ++ return PTR_ERR(gpiod_reset); ++@@ -402,15 +409,23 @@ static void at803x_link_change_notify(st ++ * cannot recover from by software. ++ */ ++ if (phydev->state == PHY_NOLINK) { ++- if (priv->gpiod_reset && !priv->phy_reset) { +++ if ((priv->gpiod_reset || (pdata && pdata->has_reset_gpio)) && +++ !priv->phy_reset) { ++ struct at803x_context context; ++ ++ at803x_context_save(phydev, &context); ++ ++- gpiod_set_value(priv->gpiod_reset, 1); ++- msleep(1); ++- gpiod_set_value(priv->gpiod_reset, 0); ++- msleep(1); +++ if (pdata && pdata->has_reset_gpio) { +++ gpio_set_value_cansleep(pdata->reset_gpio, 0); +++ msleep(1); +++ gpio_set_value_cansleep(pdata->reset_gpio, 1); +++ msleep(1); +++ } else { +++ gpiod_set_value(priv->gpiod_reset, 1); +++ msleep(1); +++ gpiod_set_value(priv->gpiod_reset, 0); +++ msleep(1); +++ } ++ ++ at803x_context_restore(phydev, &context); ++ +diff --git a/target/linux/ar71xx/patches-4.14/903-at803x-add-sgmii-aneg-override-pdata.patch b/target/linux/ar71xx/patches-4.14/903-at803x-add-sgmii-aneg-override-pdata.patch +new file mode 100644 +index 0000000000..600f8ff6de +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/903-at803x-add-sgmii-aneg-override-pdata.patch +@@ -0,0 +1,38 @@ ++--- a/drivers/net/phy/at803x.c +++++ b/drivers/net/phy/at803x.c ++@@ -458,12 +458,15 @@ static void at803x_link_change_notify(st ++ ++ static int at803x_aneg_done(struct phy_device *phydev) ++ { +++ struct at803x_platform_data *pdata; ++ int ccr; ++ ++ int aneg_done = genphy_aneg_done(phydev); ++ if (aneg_done != BMSR_ANEGCOMPLETE) ++ return aneg_done; ++ +++ pdata = dev_get_platdata(&phydev->mdio.dev); +++ ++ /* ++ * in SGMII mode, if copper side autoneg is successful, ++ * also check SGMII side autoneg result ++@@ -478,7 +481,8 @@ static int at803x_aneg_done(struct phy_d ++ /* check if the SGMII link is OK. */ ++ if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) { ++ pr_warn("803x_aneg_done: SGMII link is not ok\n"); ++- aneg_done = 0; +++ if (!pdata || !pdata->override_sgmii_aneg) +++ aneg_done = 0; ++ } ++ /* switch back to copper page */ ++ phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL); ++--- a/include/linux/platform_data/phy-at803x.h +++++ b/include/linux/platform_data/phy-at803x.h ++@@ -7,6 +7,7 @@ struct at803x_platform_data { ++ int enable_rgmii_rx_delay:1; ++ int fixup_rgmii_tx_delay:1; ++ int has_reset_gpio:1; +++ int override_sgmii_aneg:1; ++ int reset_gpio; ++ }; ++ +diff --git a/target/linux/ar71xx/patches-4.14/910-unaligned_access_hacks.patch b/target/linux/ar71xx/patches-4.14/910-unaligned_access_hacks.patch +new file mode 100644 +index 0000000000..6938f96551 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/910-unaligned_access_hacks.patch +@@ -0,0 +1,942 @@ ++--- a/arch/mips/include/asm/checksum.h +++++ b/arch/mips/include/asm/checksum.h ++@@ -134,26 +134,30 @@ static inline __sum16 ip_fast_csum(const ++ const unsigned int *stop = word + ihl; ++ unsigned int csum; ++ int carry; +++ unsigned int w; ++ ++- csum = word[0]; ++- csum += word[1]; ++- carry = (csum < word[1]); +++ csum = net_hdr_word(word++); +++ +++ w = net_hdr_word(word++); +++ csum += w; +++ carry = (csum < w); ++ csum += carry; ++ ++- csum += word[2]; ++- carry = (csum < word[2]); +++ w = net_hdr_word(word++); +++ csum += w; +++ carry = (csum < w); ++ csum += carry; ++ ++- csum += word[3]; ++- carry = (csum < word[3]); +++ w = net_hdr_word(word++); +++ csum += w; +++ carry = (csum < w); ++ csum += carry; ++ ++- word += 4; ++ do { ++- csum += *word; ++- carry = (csum < *word); +++ w = net_hdr_word(word++); +++ csum += w; +++ carry = (csum < w); ++ csum += carry; ++- word++; ++ } while (word != stop); ++ ++ return csum_fold(csum); ++@@ -214,73 +218,6 @@ static inline __sum16 ip_compute_csum(co ++ return csum_fold(csum_partial(buff, len, 0)); ++ } ++ ++-#define _HAVE_ARCH_IPV6_CSUM ++-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, ++- const struct in6_addr *daddr, ++- __u32 len, __u8 proto, ++- __wsum sum) ++-{ ++- __wsum tmp; ++- ++- __asm__( ++- " .set push # csum_ipv6_magic\n" ++- " .set noreorder \n" ++- " .set noat \n" ++- " addu %0, %5 # proto (long in network byte order)\n" ++- " sltu $1, %0, %5 \n" ++- " addu %0, $1 \n" ++- ++- " addu %0, %6 # csum\n" ++- " sltu $1, %0, %6 \n" ++- " lw %1, 0(%2) # four words source address\n" ++- " addu %0, $1 \n" ++- " addu %0, %1 \n" ++- " sltu $1, %0, %1 \n" ++- ++- " lw %1, 4(%2) \n" ++- " addu %0, $1 \n" ++- " addu %0, %1 \n" ++- " sltu $1, %0, %1 \n" ++- ++- " lw %1, 8(%2) \n" ++- " addu %0, $1 \n" ++- " addu %0, %1 \n" ++- " sltu $1, %0, %1 \n" ++- ++- " lw %1, 12(%2) \n" ++- " addu %0, $1 \n" ++- " addu %0, %1 \n" ++- " sltu $1, %0, %1 \n" ++- ++- " lw %1, 0(%3) \n" ++- " addu %0, $1 \n" ++- " addu %0, %1 \n" ++- " sltu $1, %0, %1 \n" ++- ++- " lw %1, 4(%3) \n" ++- " addu %0, $1 \n" ++- " addu %0, %1 \n" ++- " sltu $1, %0, %1 \n" ++- ++- " lw %1, 8(%3) \n" ++- " addu %0, $1 \n" ++- " addu %0, %1 \n" ++- " sltu $1, %0, %1 \n" ++- ++- " lw %1, 12(%3) \n" ++- " addu %0, $1 \n" ++- " addu %0, %1 \n" ++- " sltu $1, %0, %1 \n" ++- ++- " addu %0, $1 # Add final carry\n" ++- " .set pop" ++- : "=&r" (sum), "=&r" (tmp) ++- : "r" (saddr), "r" (daddr), ++- "0" (htonl(len)), "r" (htonl(proto)), "r" (sum)); ++- ++- return csum_fold(sum); ++-} ++- ++ #include ++ #endif /* CONFIG_GENERIC_CSUM */ ++ ++--- a/include/uapi/linux/ip.h +++++ b/include/uapi/linux/ip.h ++@@ -103,7 +103,7 @@ struct iphdr { ++ __be32 saddr; ++ __be32 daddr; ++ /*The options start here. */ ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ ++ struct ip_auth_hdr { ++--- a/include/uapi/linux/ipv6.h +++++ b/include/uapi/linux/ipv6.h ++@@ -104,7 +104,7 @@ struct ipv6_destopt_hao { ++ __u8 type; ++ __u8 length; ++ struct in6_addr addr; ++-} __attribute__((packed)); +++} __attribute__((packed, aligned(2))); ++ ++ /* ++ * IPv6 fixed header ++@@ -131,7 +131,7 @@ struct ipv6hdr { ++ ++ struct in6_addr saddr; ++ struct in6_addr daddr; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ ++ /* index values for the variables in ipv6_devconf */ ++--- a/include/uapi/linux/tcp.h +++++ b/include/uapi/linux/tcp.h ++@@ -55,7 +55,7 @@ struct tcphdr { ++ __be16 window; ++ __sum16 check; ++ __be16 urg_ptr; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ /* ++ * The union cast uses a gcc extension to avoid aliasing problems ++@@ -65,7 +65,7 @@ struct tcphdr { ++ union tcp_word_hdr { ++ struct tcphdr hdr; ++ __be32 words[5]; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) ++ ++--- a/include/uapi/linux/udp.h +++++ b/include/uapi/linux/udp.h ++@@ -25,7 +25,7 @@ struct udphdr { ++ __be16 dest; ++ __be16 len; ++ __sum16 check; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ /* UDP socket options */ ++ #define UDP_CORK 1 /* Never send partially complete segments */ ++--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c ++@@ -48,8 +48,8 @@ static bool ipv4_pkt_to_tuple(const stru ++ if (ap == NULL) ++ return false; ++ ++- tuple->src.u3.ip = ap[0]; ++- tuple->dst.u3.ip = ap[1]; +++ tuple->src.u3.ip = net_hdr_word(ap++); +++ tuple->dst.u3.ip = net_hdr_word(ap); ++ ++ return true; ++ } ++--- a/include/uapi/linux/icmp.h +++++ b/include/uapi/linux/icmp.h ++@@ -82,7 +82,7 @@ struct icmphdr { ++ } frag; ++ __u8 reserved[4]; ++ } un; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ ++ /* ++--- a/include/uapi/linux/in6.h +++++ b/include/uapi/linux/in6.h ++@@ -43,7 +43,7 @@ struct in6_addr { ++ #define s6_addr16 in6_u.u6_addr16 ++ #define s6_addr32 in6_u.u6_addr32 ++ #endif ++-}; +++} __attribute__((packed, aligned(2))); ++ #endif /* __UAPI_DEF_IN6_ADDR */ ++ ++ #if __UAPI_DEF_SOCKADDR_IN6 ++--- a/net/ipv6/tcp_ipv6.c +++++ b/net/ipv6/tcp_ipv6.c ++@@ -39,6 +39,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -819,10 +820,10 @@ static void tcp_v6_send_response(const s ++ topt = (__be32 *)(t1 + 1); ++ ++ if (tsecr) { ++- *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | ++- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); ++- *topt++ = htonl(tsval); ++- *topt++ = htonl(tsecr); +++ put_unaligned_be32((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | +++ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP, topt++); +++ put_unaligned_be32(tsval, topt++); +++ put_unaligned_be32(tsecr, topt++); ++ } ++ ++ #ifdef CONFIG_TCP_MD5SIG ++--- a/include/linux/ipv6.h +++++ b/include/linux/ipv6.h ++@@ -6,6 +6,7 @@ ++ ++ #define ipv6_optlen(p) (((p)->hdrlen+1) << 3) ++ #define ipv6_authlen(p) (((p)->hdrlen+2) << 2) +++ ++ /* ++ * This structure contains configuration options per IPv6 link. ++ */ ++--- a/net/ipv6/datagram.c +++++ b/net/ipv6/datagram.c ++@@ -486,7 +486,7 @@ int ipv6_recv_error(struct sock *sk, str ++ ipv6_iface_scope_id(&sin->sin6_addr, ++ IP6CB(skb)->iif); ++ } else { ++- ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset), +++ ipv6_addr_set_v4mapped(net_hdr_word(nh + serr->addr_offset), ++ &sin->sin6_addr); ++ sin->sin6_scope_id = 0; ++ } ++@@ -835,12 +835,12 @@ int ip6_datagram_send_ctl(struct net *ne ++ } ++ ++ if (fl6->flowlabel&IPV6_FLOWINFO_MASK) { ++- if ((fl6->flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { +++ if ((fl6->flowlabel^net_hdr_word(CMSG_DATA(cmsg)))&~IPV6_FLOWINFO_MASK) { ++ err = -EINVAL; ++ goto exit_f; ++ } ++ } ++- fl6->flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg); +++ fl6->flowlabel = IPV6_FLOWINFO_MASK & net_hdr_word(CMSG_DATA(cmsg)); ++ break; ++ ++ case IPV6_2292HOPOPTS: ++--- a/net/ipv6/ip6_gre.c +++++ b/net/ipv6/ip6_gre.c ++@@ -400,7 +400,7 @@ static void ip6gre_err(struct sk_buff *s ++ return; ++ ipv6h = (const struct ipv6hdr *)skb->data; ++ greh = (const struct gre_base_hdr *)(skb->data + offset); ++- key = key_off ? *(__be32 *)(skb->data + key_off) : 0; +++ key = key_off ? net_hdr_word((__be32 *)(skb->data + key_off)) : 0; ++ ++ t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, ++ key, greh->protocol); ++--- a/net/ipv6/exthdrs.c +++++ b/net/ipv6/exthdrs.c ++@@ -733,7 +733,7 @@ static bool ipv6_hop_jumbo(struct sk_buf ++ goto drop; ++ } ++ ++- pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); +++ pkt_len = ntohl(net_hdr_word(nh + optoff + 2)); ++ if (pkt_len <= IPV6_MAXPLEN) { ++ __IP6_INC_STATS(net, ipv6_skb_idev(skb), ++ IPSTATS_MIB_INHDRERRORS); ++--- a/include/linux/types.h +++++ b/include/linux/types.h ++@@ -229,5 +229,11 @@ struct callback_head { ++ typedef void (*rcu_callback_t)(struct rcu_head *head); ++ typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func); ++ +++struct net_hdr_word { +++ u32 words[1]; +++} __attribute__((packed, aligned(2))); +++ +++#define net_hdr_word(_p) (((struct net_hdr_word *) (_p))->words[0]) +++ ++ #endif /* __ASSEMBLY__ */ ++ #endif /* _LINUX_TYPES_H */ ++--- a/net/ipv4/af_inet.c +++++ b/net/ipv4/af_inet.c ++@@ -1352,8 +1352,8 @@ struct sk_buff **inet_gro_receive(struct ++ if (unlikely(ip_fast_csum((u8 *)iph, 5))) ++ goto out_unlock; ++ ++- id = ntohl(*(__be32 *)&iph->id); ++- flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF)); +++ id = ntohl(net_hdr_word(&iph->id)); +++ flush = (u16)((ntohl(net_hdr_word(iph)) ^ skb_gro_len(skb)) | (id & ~IP_DF)); ++ id >>= 16; ++ ++ for (p = *head; p; p = p->next) { ++--- a/net/ipv4/route.c +++++ b/net/ipv4/route.c ++@@ -464,7 +464,7 @@ static struct neighbour *ipv4_neigh_look ++ else if (skb) ++ pkey = &ip_hdr(skb)->daddr; ++ ++- n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey); +++ n = __ipv4_neigh_lookup(dev, net_hdr_word(pkey)); ++ if (n) ++ return n; ++ return neigh_create(&arp_tbl, pkey, dev); ++--- a/net/ipv4/tcp_output.c +++++ b/net/ipv4/tcp_output.c ++@@ -454,48 +454,53 @@ static void tcp_options_write(__be32 *pt ++ u16 options = opts->options; /* mungable copy */ ++ ++ if (unlikely(OPTION_MD5 & options)) { ++- *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | ++- (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); +++ net_hdr_word(ptr++) = +++ htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | +++ (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); ++ /* overload cookie hash location */ ++ opts->hash_location = (__u8 *)ptr; ++ ptr += 4; ++ } ++ ++ if (unlikely(opts->mss)) { ++- *ptr++ = htonl((TCPOPT_MSS << 24) | ++- (TCPOLEN_MSS << 16) | ++- opts->mss); +++ net_hdr_word(ptr++) = +++ htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | +++ opts->mss); ++ } ++ ++ if (likely(OPTION_TS & options)) { ++ if (unlikely(OPTION_SACK_ADVERTISE & options)) { ++- *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | ++- (TCPOLEN_SACK_PERM << 16) | ++- (TCPOPT_TIMESTAMP << 8) | ++- TCPOLEN_TIMESTAMP); +++ net_hdr_word(ptr++) = +++ htonl((TCPOPT_SACK_PERM << 24) | +++ (TCPOLEN_SACK_PERM << 16) | +++ (TCPOPT_TIMESTAMP << 8) | +++ TCPOLEN_TIMESTAMP); ++ options &= ~OPTION_SACK_ADVERTISE; ++ } else { ++- *ptr++ = htonl((TCPOPT_NOP << 24) | ++- (TCPOPT_NOP << 16) | ++- (TCPOPT_TIMESTAMP << 8) | ++- TCPOLEN_TIMESTAMP); +++ net_hdr_word(ptr++) = +++ htonl((TCPOPT_NOP << 24) | +++ (TCPOPT_NOP << 16) | +++ (TCPOPT_TIMESTAMP << 8) | +++ TCPOLEN_TIMESTAMP); ++ } ++- *ptr++ = htonl(opts->tsval); ++- *ptr++ = htonl(opts->tsecr); +++ net_hdr_word(ptr++) = htonl(opts->tsval); +++ net_hdr_word(ptr++) = htonl(opts->tsecr); ++ } ++ ++ if (unlikely(OPTION_SACK_ADVERTISE & options)) { ++- *ptr++ = htonl((TCPOPT_NOP << 24) | ++- (TCPOPT_NOP << 16) | ++- (TCPOPT_SACK_PERM << 8) | ++- TCPOLEN_SACK_PERM); +++ net_hdr_word(ptr++) = +++ htonl((TCPOPT_NOP << 24) | +++ (TCPOPT_NOP << 16) | +++ (TCPOPT_SACK_PERM << 8) | +++ TCPOLEN_SACK_PERM); ++ } ++ ++ if (unlikely(OPTION_WSCALE & options)) { ++- *ptr++ = htonl((TCPOPT_NOP << 24) | ++- (TCPOPT_WINDOW << 16) | ++- (TCPOLEN_WINDOW << 8) | ++- opts->ws); +++ net_hdr_word(ptr++) = +++ htonl((TCPOPT_NOP << 24) | +++ (TCPOPT_WINDOW << 16) | +++ (TCPOLEN_WINDOW << 8) | +++ opts->ws); ++ } ++ ++ if (unlikely(opts->num_sack_blocks)) { ++@@ -503,16 +508,17 @@ static void tcp_options_write(__be32 *pt ++ tp->duplicate_sack : tp->selective_acks; ++ int this_sack; ++ ++- *ptr++ = htonl((TCPOPT_NOP << 24) | ++- (TCPOPT_NOP << 16) | ++- (TCPOPT_SACK << 8) | ++- (TCPOLEN_SACK_BASE + (opts->num_sack_blocks * +++ net_hdr_word(ptr++) = +++ htonl((TCPOPT_NOP << 24) | +++ (TCPOPT_NOP << 16) | +++ (TCPOPT_SACK << 8) | +++ (TCPOLEN_SACK_BASE + (opts->num_sack_blocks * ++ TCPOLEN_SACK_PERBLOCK))); ++ ++ for (this_sack = 0; this_sack < opts->num_sack_blocks; ++ ++this_sack) { ++- *ptr++ = htonl(sp[this_sack].start_seq); ++- *ptr++ = htonl(sp[this_sack].end_seq); +++ net_hdr_word(ptr++) = htonl(sp[this_sack].start_seq); +++ net_hdr_word(ptr++) = htonl(sp[this_sack].end_seq); ++ } ++ ++ tp->rx_opt.dsack = 0; ++@@ -525,13 +531,14 @@ static void tcp_options_write(__be32 *pt ++ ++ if (foc->exp) { ++ len = TCPOLEN_EXP_FASTOPEN_BASE + foc->len; ++- *ptr = htonl((TCPOPT_EXP << 24) | (len << 16) | +++ net_hdr_word(ptr) = +++ htonl((TCPOPT_EXP << 24) | (len << 16) | ++ TCPOPT_FASTOPEN_MAGIC); ++ p += TCPOLEN_EXP_FASTOPEN_BASE; ++ } else { ++ len = TCPOLEN_FASTOPEN_BASE + foc->len; ++- *p++ = TCPOPT_FASTOPEN; ++- *p++ = len; +++ net_hdr_word(p++) = TCPOPT_FASTOPEN; +++ net_hdr_word(p++) = len; ++ } ++ ++ memcpy(p, foc->val, foc->len); ++--- a/net/ipv4/igmp.c +++++ b/net/ipv4/igmp.c ++@@ -548,7 +548,7 @@ static struct sk_buff *add_grec(struct s ++ if (!skb) ++ return NULL; ++ psrc = skb_put(skb, sizeof(__be32)); ++- *psrc = psf->sf_inaddr; +++ net_hdr_word(psrc) = psf->sf_inaddr; ++ scount++; stotal++; ++ if ((type == IGMPV3_ALLOW_NEW_SOURCES || ++ type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) { ++--- a/include/uapi/linux/igmp.h +++++ b/include/uapi/linux/igmp.h ++@@ -33,7 +33,7 @@ struct igmphdr { ++ __u8 code; /* For newer IGMP */ ++ __sum16 csum; ++ __be32 group; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ /* V3 group record types [grec_type] */ ++ #define IGMPV3_MODE_IS_INCLUDE 1 ++@@ -49,7 +49,7 @@ struct igmpv3_grec { ++ __be16 grec_nsrcs; ++ __be32 grec_mca; ++ __be32 grec_src[0]; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ struct igmpv3_report { ++ __u8 type; ++@@ -58,7 +58,7 @@ struct igmpv3_report { ++ __be16 resv2; ++ __be16 ngrec; ++ struct igmpv3_grec grec[0]; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ struct igmpv3_query { ++ __u8 type; ++@@ -79,7 +79,7 @@ struct igmpv3_query { ++ __u8 qqic; ++ __be16 nsrcs; ++ __be32 srcs[0]; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ #define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */ ++ #define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */ ++--- a/net/core/flow_dissector.c +++++ b/net/core/flow_dissector.c ++@@ -109,7 +109,7 @@ __be32 __skb_flow_get_ports(const struct ++ ports = __skb_header_pointer(skb, thoff + poff, ++ sizeof(_ports), data, hlen, &_ports); ++ if (ports) ++- return *ports; +++ return (__be32)net_hdr_word(ports); ++ } ++ ++ return 0; ++--- a/include/uapi/linux/icmpv6.h +++++ b/include/uapi/linux/icmpv6.h ++@@ -77,7 +77,7 @@ struct icmp6hdr { ++ #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other ++ #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime ++ #define icmp6_router_pref icmp6_dataun.u_nd_ra.router_pref ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ ++ #define ICMPV6_ROUTER_PREF_LOW 0x3 ++--- a/include/net/ndisc.h +++++ b/include/net/ndisc.h ++@@ -89,7 +89,7 @@ struct ra_msg { ++ struct icmp6hdr icmph; ++ __be32 reachable_time; ++ __be32 retrans_timer; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ struct rd_msg { ++ struct icmp6hdr icmph; ++@@ -368,10 +368,10 @@ static inline u32 ndisc_hashfn(const voi ++ { ++ const u32 *p32 = pkey; ++ ++- return (((p32[0] ^ hash32_ptr(dev)) * hash_rnd[0]) + ++- (p32[1] * hash_rnd[1]) + ++- (p32[2] * hash_rnd[2]) + ++- (p32[3] * hash_rnd[3])); +++ return (((net_hdr_word(&p32[0]) ^ hash32_ptr(dev)) * hash_rnd[0]) + +++ (net_hdr_word(&p32[1]) * hash_rnd[1]) + +++ (net_hdr_word(&p32[2]) * hash_rnd[2]) + +++ (net_hdr_word(&p32[3]) * hash_rnd[3])); ++ } ++ ++ static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey) ++--- a/net/sched/cls_u32.c +++++ b/net/sched/cls_u32.c ++@@ -165,7 +165,7 @@ next_knode: ++ data = skb_header_pointer(skb, toff, 4, &hdata); ++ if (!data) ++ goto out; ++- if ((*data ^ key->val) & key->mask) { +++ if ((net_hdr_word(data) ^ key->val) & key->mask) { ++ n = rcu_dereference_bh(n->next); ++ goto next_knode; ++ } ++@@ -218,8 +218,8 @@ check_terminal: ++ &hdata); ++ if (!data) ++ goto out; ++- sel = ht->divisor & u32_hash_fold(*data, &n->sel, ++- n->fshift); +++ sel = ht->divisor & u32_hash_fold(net_hdr_word(data), +++ &n->sel, n->fshift); ++ } ++ if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT))) ++ goto next_ht; ++--- a/net/ipv6/ip6_offload.c +++++ b/net/ipv6/ip6_offload.c ++@@ -221,7 +221,7 @@ static struct sk_buff **ipv6_gro_receive ++ continue; ++ ++ iph2 = (struct ipv6hdr *)(p->data + off); ++- first_word = *(__be32 *)iph ^ *(__be32 *)iph2; +++ first_word = net_hdr_word(iph) ^ net_hdr_word(iph2); ++ ++ /* All fields must match except length and Traffic Class. ++ * XXX skbs on the gro_list have all been parsed and pulled ++--- a/include/net/addrconf.h +++++ b/include/net/addrconf.h ++@@ -47,7 +47,7 @@ struct prefix_info { ++ __be32 reserved2; ++ ++ struct in6_addr prefix; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ #include ++ #include ++--- a/include/net/inet_ecn.h +++++ b/include/net/inet_ecn.h ++@@ -125,9 +125,9 @@ static inline int IP6_ECN_set_ce(struct ++ if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) ++ return 0; ++ ++- from = *(__be32 *)iph; +++ from = net_hdr_word(iph); ++ to = from | htonl(INET_ECN_CE << 20); ++- *(__be32 *)iph = to; +++ net_hdr_word(iph) = to; ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from), ++ (__force __wsum)to); ++@@ -136,7 +136,7 @@ static inline int IP6_ECN_set_ce(struct ++ ++ static inline void IP6_ECN_clear(struct ipv6hdr *iph) ++ { ++- *(__be32*)iph &= ~htonl(INET_ECN_MASK << 20); +++ net_hdr_word(iph) &= ~htonl(INET_ECN_MASK << 20); ++ } ++ ++ static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner) ++--- a/include/net/ipv6.h +++++ b/include/net/ipv6.h ++@@ -108,7 +108,7 @@ struct frag_hdr { ++ __u8 reserved; ++ __be16 frag_off; ++ __be32 identification; ++-}; +++} __attribute__((packed, aligned(2))); ++ ++ #define IP6_MF 0x0001 ++ #define IP6_OFFSET 0xFFF8 ++@@ -437,8 +437,8 @@ static inline void __ipv6_addr_set_half( ++ } ++ #endif ++ #endif ++- addr[0] = wh; ++- addr[1] = wl; +++ net_hdr_word(&addr[0]) = wh; +++ net_hdr_word(&addr[1]) = wl; ++ } ++ ++ static inline void ipv6_addr_set(struct in6_addr *addr, ++@@ -497,6 +497,8 @@ static inline bool ipv6_prefix_equal(con ++ const __be32 *a1 = addr1->s6_addr32; ++ const __be32 *a2 = addr2->s6_addr32; ++ unsigned int pdw, pbi; +++ /* Used for last <32-bit fraction of prefix */ +++ u32 pbia1, pbia2; ++ ++ /* check complete u32 in prefix */ ++ pdw = prefixlen >> 5; ++@@ -505,7 +507,9 @@ static inline bool ipv6_prefix_equal(con ++ ++ /* check incomplete u32 in prefix */ ++ pbi = prefixlen & 0x1f; ++- if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi)))) +++ pbia1 = net_hdr_word(&a1[pdw]); +++ pbia2 = net_hdr_word(&a2[pdw]); +++ if (pbi && ((pbia1 ^ pbia2) & htonl((0xffffffff) << (32 - pbi)))) ++ return false; ++ ++ return true; ++@@ -605,13 +609,13 @@ static inline void ipv6_addr_set_v4mappe ++ */ ++ static inline int __ipv6_addr_diff32(const void *token1, const void *token2, int addrlen) ++ { ++- const __be32 *a1 = token1, *a2 = token2; +++ const struct in6_addr *a1 = token1, *a2 = token2; ++ int i; ++ ++ addrlen >>= 2; ++ ++ for (i = 0; i < addrlen; i++) { ++- __be32 xb = a1[i] ^ a2[i]; +++ __be32 xb = a1->s6_addr32[i] ^ a2->s6_addr32[i]; ++ if (xb) ++ return i * 32 + 31 - __fls(ntohl(xb)); ++ } ++@@ -780,17 +784,18 @@ static inline int ip6_default_np_autolab ++ static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass, ++ __be32 flowlabel) ++ { ++- *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel; +++ net_hdr_word((__be32 *)hdr) = +++ htonl(0x60000000 | (tclass << 20)) | flowlabel; ++ } ++ ++ static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr) ++ { ++- return *(__be32 *)hdr & IPV6_FLOWINFO_MASK; +++ return net_hdr_word((__be32 *)hdr) & IPV6_FLOWINFO_MASK; ++ } ++ ++ static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr) ++ { ++- return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK; +++ return net_hdr_word((__be32 *)hdr) & IPV6_FLOWLABEL_MASK; ++ } ++ ++ static inline u8 ip6_tclass(__be32 flowinfo) ++--- a/include/net/secure_seq.h +++++ b/include/net/secure_seq.h ++@@ -3,6 +3,7 @@ ++ #define _NET_SECURE_SEQ ++ ++ #include +++#include ++ ++ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); ++ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, ++--- a/include/uapi/linux/in.h +++++ b/include/uapi/linux/in.h ++@@ -84,7 +84,7 @@ enum { ++ /* Internet address. */ ++ struct in_addr { ++ __be32 s_addr; ++-}; +++} __attribute__((packed, aligned(2))); ++ #endif ++ ++ #define IP_TOS 1 ++--- a/net/ipv6/ip6_fib.c +++++ b/net/ipv6/ip6_fib.c ++@@ -137,7 +137,7 @@ static __be32 addr_bit_set(const void *t ++ * See include/asm-generic/bitops/le.h. ++ */ ++ return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) & ++- addr[fn_bit >> 5]; +++ net_hdr_word(&addr[fn_bit >> 5]); ++ } ++ ++ static struct fib6_node *node_alloc(void) ++--- a/net/netfilter/nf_conntrack_proto_tcp.c +++++ b/net/netfilter/nf_conntrack_proto_tcp.c ++@@ -447,7 +447,7 @@ static void tcp_sack(const struct sk_buf ++ ++ /* Fast path for timestamp-only option */ ++ if (length == TCPOLEN_TSTAMP_ALIGNED ++- && *(__be32 *)ptr == htonl((TCPOPT_NOP << 24) +++ && net_hdr_word(ptr) == htonl((TCPOPT_NOP << 24) ++ | (TCPOPT_NOP << 16) ++ | (TCPOPT_TIMESTAMP << 8) ++ | TCPOLEN_TIMESTAMP)) ++--- a/net/xfrm/xfrm_input.c +++++ b/net/xfrm/xfrm_input.c ++@@ -193,8 +193,8 @@ int xfrm_parse_spi(struct sk_buff *skb, ++ if (!pskb_may_pull(skb, hlen)) ++ return -EINVAL; ++ ++- *spi = *(__be32 *)(skb_transport_header(skb) + offset); ++- *seq = *(__be32 *)(skb_transport_header(skb) + offset_seq); +++ *spi = net_hdr_word(skb_transport_header(skb) + offset); +++ *seq = net_hdr_word(skb_transport_header(skb) + offset_seq); ++ return 0; ++ } ++ EXPORT_SYMBOL(xfrm_parse_spi); ++--- a/net/ipv4/tcp_input.c +++++ b/net/ipv4/tcp_input.c ++@@ -3879,14 +3879,16 @@ static bool tcp_parse_aligned_timestamp( ++ { ++ const __be32 *ptr = (const __be32 *)(th + 1); ++ ++- if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) ++- | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { +++ if (net_hdr_word(ptr) == +++ htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | +++ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { ++ tp->rx_opt.saw_tstamp = 1; ++ ++ptr; ++- tp->rx_opt.rcv_tsval = ntohl(*ptr); +++ tp->rx_opt.rcv_tsval = get_unaligned_be32(ptr); ++ ++ptr; ++- if (*ptr) ++- tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset; +++ if (net_hdr_word(ptr)) +++ tp->rx_opt.rcv_tsecr = get_unaligned_be32(ptr) - +++ tp->tsoffset; ++ else ++ tp->rx_opt.rcv_tsecr = 0; ++ return true; ++--- a/include/uapi/linux/if_pppox.h +++++ b/include/uapi/linux/if_pppox.h ++@@ -51,6 +51,7 @@ struct pppoe_addr { ++ */ ++ struct pptp_addr { ++ __u16 call_id; +++ __u16 pad; ++ struct in_addr sin_addr; ++ }; ++ ++--- a/net/ipv6/netfilter/nf_log_ipv6.c +++++ b/net/ipv6/netfilter/nf_log_ipv6.c ++@@ -66,9 +66,9 @@ static void dump_ipv6_packet(struct nf_l ++ /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ ++ nf_log_buf_add(m, "LEN=%zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", ++ ntohs(ih->payload_len) + sizeof(struct ipv6hdr), ++- (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, +++ (ntohl(net_hdr_word(ih)) & 0x0ff00000) >> 20, ++ ih->hop_limit, ++- (ntohl(*(__be32 *)ih) & 0x000fffff)); +++ (ntohl(net_hdr_word(ih)) & 0x000fffff)); ++ ++ fragment = 0; ++ ptr = ip6hoff + sizeof(struct ipv6hdr); ++--- a/include/net/neighbour.h +++++ b/include/net/neighbour.h ++@@ -265,8 +265,10 @@ static inline bool neigh_key_eq128(const ++ const u32 *n32 = (const u32 *)n->primary_key; ++ const u32 *p32 = pkey; ++ ++- return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) | ++- (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0; +++ return ((n32[0] ^ net_hdr_word(&p32[0])) | +++ (n32[1] ^ net_hdr_word(&p32[1])) | +++ (n32[2] ^ net_hdr_word(&p32[2])) | +++ (n32[3] ^ net_hdr_word(&p32[3]))) == 0; ++ } ++ ++ static inline struct neighbour *___neigh_lookup_noref( ++--- a/include/uapi/linux/netfilter_arp/arp_tables.h +++++ b/include/uapi/linux/netfilter_arp/arp_tables.h ++@@ -70,7 +70,7 @@ struct arpt_arp { ++ __u8 flags; ++ /* Inverse flags */ ++ __u16 invflags; ++-}; +++} __attribute__((aligned(4))); ++ ++ /* Values for "flag" field in struct arpt_ip (general arp structure). ++ * No flags defined yet. ++--- a/net/core/utils.c +++++ b/net/core/utils.c ++@@ -441,8 +441,14 @@ void inet_proto_csum_replace16(__sum16 * ++ bool pseudohdr) ++ { ++ __be32 diff[] = { ++- ~from[0], ~from[1], ~from[2], ~from[3], ++- to[0], to[1], to[2], to[3], +++ ~net_hdr_word(&from[0]), +++ ~net_hdr_word(&from[1]), +++ ~net_hdr_word(&from[2]), +++ ~net_hdr_word(&from[3]), +++ net_hdr_word(&to[0]), +++ net_hdr_word(&to[1]), +++ net_hdr_word(&to[2]), +++ net_hdr_word(&to[3]), ++ }; ++ if (skb->ip_summed != CHECKSUM_PARTIAL) { ++ *sum = csum_fold(csum_partial(diff, sizeof(diff), ++--- a/drivers/net/vxlan.c +++++ b/drivers/net/vxlan.c ++@@ -1872,15 +1872,15 @@ static int vxlan_build_skb(struct sk_buf ++ return err; ++ ++ vxh = __skb_push(skb, sizeof(*vxh)); ++- vxh->vx_flags = VXLAN_HF_VNI; ++- vxh->vx_vni = vxlan_vni_field(vni); +++ net_hdr_word(&vxh->vx_flags) = VXLAN_HF_VNI; +++ net_hdr_word(&vxh->vx_vni) = vxlan_vni_field(vni); ++ ++ if (type & SKB_GSO_TUNNEL_REMCSUM) { ++ unsigned int start; ++ ++ start = skb_checksum_start_offset(skb) - sizeof(struct vxlanhdr); ++- vxh->vx_vni |= vxlan_compute_rco(start, skb->csum_offset); ++- vxh->vx_flags |= VXLAN_HF_RCO; +++ net_hdr_word(&vxh->vx_vni) |= vxlan_compute_rco(start, skb->csum_offset); +++ net_hdr_word(&vxh->vx_flags) |= VXLAN_HF_RCO; ++ ++ if (!skb_is_gso(skb)) { ++ skb->ip_summed = CHECKSUM_NONE; ++--- a/include/linux/etherdevice.h +++++ b/include/linux/etherdevice.h ++@@ -480,7 +480,7 @@ static inline bool is_etherdev_addr(cons ++ * @b: Pointer to Ethernet header ++ * ++ * Compare two Ethernet headers, returns 0 if equal. ++- * This assumes that the network header (i.e., IP header) is 4-byte +++ * This assumes that the network header (i.e., IP header) is 2-byte ++ * aligned OR the platform can handle unaligned access. This is the ++ * case for all packets coming into netif_receive_skb or similar ++ * entry points. ++@@ -503,11 +503,12 @@ static inline unsigned long compare_ethe ++ fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); ++ return fold; ++ #else ++- u32 *a32 = (u32 *)((u8 *)a + 2); ++- u32 *b32 = (u32 *)((u8 *)b + 2); +++ const u16 *a16 = a; +++ const u16 *b16 = b; ++ ++- return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | ++- (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); +++ return (a16[0] ^ b16[0]) | (a16[1] ^ b16[1]) | (a16[2] ^ b16[2]) | +++ (a16[3] ^ b16[3]) | (a16[4] ^ b16[4]) | (a16[5] ^ b16[5]) | +++ (a16[6] ^ b16[6]); ++ #endif ++ } ++ ++--- a/net/ipv4/tcp_offload.c +++++ b/net/ipv4/tcp_offload.c ++@@ -226,7 +226,7 @@ struct sk_buff **tcp_gro_receive(struct ++ ++ th2 = tcp_hdr(p); ++ ++- if (*(u32 *)&th->source ^ *(u32 *)&th2->source) { +++ if (net_hdr_word(&th->source) ^ net_hdr_word(&th2->source)) { ++ NAPI_GRO_CB(p)->same_flow = 0; ++ continue; ++ } ++@@ -244,8 +244,8 @@ found: ++ ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); ++ flush |= (__force int)(th->ack_seq ^ th2->ack_seq); ++ for (i = sizeof(*th); i < thlen; i += 4) ++- flush |= *(u32 *)((u8 *)th + i) ^ ++- *(u32 *)((u8 *)th2 + i); +++ flush |= net_hdr_word((u8 *)th + i) ^ +++ net_hdr_word((u8 *)th2 + i); ++ ++ /* When we receive our second frame we can made a decision on if we ++ * continue this flow as an atomic flow with a fixed ID or if we use ++--- a/net/ipv6/netfilter/ip6table_mangle.c +++++ b/net/ipv6/netfilter/ip6table_mangle.c ++@@ -50,7 +50,7 @@ ip6t_mangle_out(struct sk_buff *skb, con ++ hop_limit = ipv6_hdr(skb)->hop_limit; ++ ++ /* flowlabel and prio (includes version, which shouldn't change either */ ++- flowlabel = *((u_int32_t *)ipv6_hdr(skb)); +++ flowlabel = net_hdr_word(ipv6_hdr(skb)); ++ ++ ret = ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle); ++ ++@@ -59,7 +59,7 @@ ip6t_mangle_out(struct sk_buff *skb, con ++ !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || ++ skb->mark != mark || ++ ipv6_hdr(skb)->hop_limit != hop_limit || ++- flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { +++ flowlabel != net_hdr_word(ipv6_hdr(skb)))) { ++ err = ip6_route_me_harder(state->net, skb); ++ if (err < 0) ++ ret = NF_DROP_ERR(err); +diff --git a/target/linux/ar71xx/patches-4.14/920-usb-chipidea-AR933x-platform-support.patch b/target/linux/ar71xx/patches-4.14/920-usb-chipidea-AR933x-platform-support.patch +new file mode 100644 +index 0000000000..b0e69af9c1 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/920-usb-chipidea-AR933x-platform-support.patch +@@ -0,0 +1,124 @@ ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -659,6 +659,7 @@ ++ ++ #define AR933X_BOOTSTRAP_MDIO_GPIO_EN BIT(18) ++ #define AR933X_BOOTSTRAP_EEPBUSY BIT(4) +++#define AR933X_BOOTSTRAP_USB_MODE_HOST BIT(3) ++ #define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0) ++ ++ #define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23) ++@@ -688,6 +689,8 @@ ++ ++ #define QCA956X_BOOTSTRAP_REF_CLK_40 BIT(2) ++ +++#define AR933X_USB_CONFIG_HOST_ONLY BIT(8) +++ ++ #define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) ++ #define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1) ++ #define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) ++--- a/arch/mips/ath79/dev-usb.c +++++ b/arch/mips/ath79/dev-usb.c ++@@ -19,6 +19,9 @@ ++ #include ++ #include ++ #include +++#include +++#include +++#include ++ ++ #include ++ #include ++@@ -170,6 +173,44 @@ static void __init ar913x_usb_setup(void ++ &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); ++ } ++ +++static void __init ar9xxx_ci_usb_setup(int bus_id, int irq) +++{ +++ struct ci_hdrc_platform_data ci_pdata; +++ bool host_mode = true; +++ +++ if (soc_is_ar933x()) +++ host_mode = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP) & +++ AR933X_BOOTSTRAP_USB_MODE_HOST; +++ else +++ host_mode = !(ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP) & +++ AR934X_BOOTSTRAP_USB_MODE_DEVICE); +++ +++ if (host_mode) { +++ ath79_usb_register("ehci-platform", bus_id, +++ AR934X_EHCI_BASE, AR934X_EHCI_SIZE, +++ irq, &ath79_ehci_pdata_v2, +++ sizeof(ath79_ehci_pdata_v2)); +++ +++ return; +++ } +++ +++ memset(&ci_pdata, 0, sizeof(ci_pdata)); +++ ci_pdata.name = "ci_hdrc_ar9xxx"; +++ ci_pdata.capoffset = DEF_CAPOFFSET; +++ ci_pdata.dr_mode = USB_DR_MODE_PERIPHERAL; +++ ci_pdata.flags = CI_HDRC_DUAL_ROLE_NOT_OTG | CI_HDRC_DP_ALWAYS_PULLUP; +++ ci_pdata.vbus_extcon.edev = ERR_PTR(-ENODEV); +++ ci_pdata.id_extcon.edev = ERR_PTR(-ENODEV); +++ ci_pdata.itc_setting = 1; +++ +++ platform_device_register_simple("usb_phy_generic", +++ PLATFORM_DEVID_AUTO, NULL, 0); +++ +++ ath79_usb_register("ci_hdrc", -1, +++ AR934X_EHCI_BASE, AR934X_EHCI_SIZE, +++ irq, &ci_pdata, sizeof(ci_pdata)); +++} +++ ++ static void __init ar933x_usb_setup(void) ++ { ++ ath79_device_reset_set(AR933X_RESET_USBSUS_OVERRIDE); ++@@ -181,10 +222,7 @@ static void __init ar933x_usb_setup(void ++ ath79_device_reset_clear(AR933X_RESET_USB_PHY); ++ mdelay(10); ++ ++- ath79_usb_register("ehci-platform", -1, ++- AR933X_EHCI_BASE, AR933X_EHCI_SIZE, ++- ATH79_CPU_IRQ(3), ++- &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +++ ar9xxx_ci_usb_setup(-1, ATH79_CPU_IRQ(3)); ++ } ++ ++ static void enable_tx_tx_idp_violation_fix(unsigned base) ++@@ -230,10 +268,7 @@ static void __init ar934x_usb_setup(void ++ if (ath79_soc_rev >= 3) ++ ath79_ehci_pdata_v2.reset_notifier = ar934x_usb_reset_notifier; ++ ++- ath79_usb_register("ehci-platform", -1, ++- AR934X_EHCI_BASE, AR934X_EHCI_SIZE, ++- ATH79_CPU_IRQ(3), ++- &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +++ ar9xxx_ci_usb_setup(-1, ATH79_CPU_IRQ(3)); ++ } ++ ++ static void __init qca953x_usb_setup(void) ++@@ -254,10 +289,7 @@ static void __init qca953x_usb_setup(voi ++ ath79_device_reset_clear(QCA953X_RESET_USB_HOST); ++ udelay(1000); ++ ++- ath79_usb_register("ehci-platform", -1, ++- QCA953X_EHCI_BASE, QCA953X_EHCI_SIZE, ++- ATH79_CPU_IRQ(3), ++- &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +++ ar9xxx_ci_usb_setup(-1, ATH79_CPU_IRQ(3)); ++ } ++ ++ static void qca955x_usb_reset_notifier(struct platform_device *pdev) ++@@ -285,10 +317,7 @@ static void __init qca955x_usb_setup(voi ++ { ++ ath79_ehci_pdata_v2.reset_notifier = qca955x_usb_reset_notifier; ++ ++- ath79_usb_register("ehci-platform", 0, ++- QCA955X_EHCI0_BASE, QCA955X_EHCI_SIZE, ++- ATH79_IP3_IRQ(0), ++- &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +++ ar9xxx_ci_usb_setup(0, ATH79_IP3_IRQ(0)); ++ ++ ath79_usb_register("ehci-platform", 1, ++ QCA955X_EHCI1_BASE, QCA955X_EHCI_SIZE, +diff --git a/target/linux/ar71xx/patches-4.14/921-MIPS-ath79-add-even-more-register-defines-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-4.14/921-MIPS-ath79-add-even-more-register-defines-for-QCA956x-SoC.patch +new file mode 100644 +index 0000000000..a4608ea48d +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/921-MIPS-ath79-add-even-more-register-defines-for-QCA956x-SoC.patch +@@ -0,0 +1,194 @@ ++Add more registers for QCA955x and QCA956x. ++ ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -175,6 +175,35 @@ ++ /* ++ * Hidden Registers ++ */ +++#define QCA956X_MAC_CFG_BASE 0xb9000000 +++#define QCA956X_MAC_CFG_SIZE 0x64 +++ +++#define QCA956X_MAC_CFG1_REG 0x00 +++#define QCA956X_MAC_CFG1_SOFT_RST BIT(31) +++#define QCA956X_MAC_CFG1_RX_RST BIT(19) +++#define QCA956X_MAC_CFG1_TX_RST BIT(18) +++#define QCA956X_MAC_CFG1_LOOPBACK BIT(8) +++#define QCA956X_MAC_CFG1_RX_EN BIT(2) +++#define QCA956X_MAC_CFG1_TX_EN BIT(0) +++ +++#define QCA956X_MAC_CFG2_REG 0x04 +++#define QCA956X_MAC_CFG2_IF_1000 BIT(9) +++#define QCA956X_MAC_CFG2_IF_10_100 BIT(8) +++#define QCA956X_MAC_CFG2_HUGE_FRAME_EN BIT(5) +++#define QCA956X_MAC_CFG2_LEN_CHECK BIT(4) +++#define QCA956X_MAC_CFG2_PAD_CRC_EN BIT(2) +++#define QCA956X_MAC_CFG2_FDX BIT(0) +++ +++#define QCA956X_MAC_MII_MGMT_CFG_REG 0x20 +++#define QCA956X_MGMT_CFG_CLK_DIV_20 0x07 +++ +++#define QCA956X_MAC_FIFO_CFG0_REG 0x48 +++#define QCA956X_MAC_FIFO_CFG1_REG 0x4c +++#define QCA956X_MAC_FIFO_CFG2_REG 0x50 +++#define QCA956X_MAC_FIFO_CFG3_REG 0x54 +++#define QCA956X_MAC_FIFO_CFG4_REG 0x58 +++#define QCA956X_MAC_FIFO_CFG5_REG 0x5c +++ ++ #define QCA956X_DAM_RESET_OFFSET 0xb90001bc ++ #define QCA956X_DAM_RESET_SIZE 0x4 ++ #define QCA956X_INLINE_CHKSUM_ENG BIT(27) ++@@ -384,6 +413,7 @@ ++ #define QCA955X_PLL_CLK_CTRL_REG 0x08 ++ #define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28 ++ #define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48 +++#define QCA955X_PLL_ETH_SGMII_SERDES_REG 0x4c ++ ++ #define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 ++ #define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f ++@@ -416,12 +446,18 @@ ++ #define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) ++ #define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) ++ +++#define QCA955X_PLL_ETH_SGMII_SERDES_LOCK_DETECT BIT(2) +++#define QCA955X_PLL_ETH_SGMII_SERDES_PLL_REFCLK BIT(1) +++#define QCA955X_PLL_ETH_SGMII_SERDES_EN_PLL BIT(0) +++ ++ #define QCA956X_PLL_CPU_CONFIG_REG 0x00 ++ #define QCA956X_PLL_CPU_CONFIG1_REG 0x04 ++ #define QCA956X_PLL_DDR_CONFIG_REG 0x08 ++ #define QCA956X_PLL_DDR_CONFIG1_REG 0x0c ++ #define QCA956X_PLL_CLK_CTRL_REG 0x10 +++#define QCA956X_PLL_SWITCH_CLOCK_CONTROL_REG 0x28 ++ #define QCA956X_PLL_ETH_XMII_CONTROL_REG 0x30 +++#define QCA956X_PLL_ETH_SGMII_SERDES_REG 0x4c ++ ++ #define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 ++ #define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f ++@@ -460,6 +496,31 @@ ++ #define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL BIT(21) ++ #define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) ++ +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_I2C_CLK_SELB BIT(5) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL0_1 BIT(6) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_UART1_CLK_SEL BIT(7) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_USB_REFCLK_FREQ_SEL_SHIFT 8 +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_USB_REFCLK_FREQ_SEL_MASK 0xf +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_EN_PLL_TOP BIT(12) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL0_2 BIT(13) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL1_1 BIT(14) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL1_2 BIT(15) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_SWITCH_FUNC_TST_MODE BIT(16) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_EEE_ENABLE BIT(17) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_OEN_CLK125M_PLL BIT(18) +++#define QCA956X_PLL_SWITCH_CLOCK_SPARE_SWITCHCLK_SEL BIT(19) +++ +++#define QCA956X_PLL_ETH_XMII_TX_INVERT BIT(1) +++#define QCA956X_PLL_ETH_XMII_GIGE BIT(25) +++#define QCA956X_PLL_ETH_XMII_RX_DELAY_SHIFT 28 +++#define QCA956X_PLL_ETH_XMII_RX_DELAY_MASK 0x3 +++#define QCA956X_PLL_ETH_XMII_TX_DELAY_SHIFT 26 +++#define QCA956X_PLL_ETH_XMII_TX_DELAY_MASK 3 +++ +++#define QCA956X_PLL_ETH_SGMII_SERDES_LOCK_DETECT BIT(2) +++#define QCA956X_PLL_ETH_SGMII_SERDES_PLL_REFCLK BIT(1) +++#define QCA956X_PLL_ETH_SGMII_SERDES_EN_PLL BIT(0) +++ ++ /* ++ * USB_CONFIG block ++ */ ++@@ -657,6 +718,25 @@ ++ #define QCA955X_RESET_MBOX BIT(1) ++ #define QCA955X_RESET_I2S BIT(0) ++ +++#define QCA956X_RESET_EXTERNAL BIT(28) +++#define QCA956X_RESET_FULL_CHIP BIT(24) +++#define QCA956X_RESET_GE1_MDIO BIT(23) +++#define QCA956X_RESET_GE0_MDIO BIT(22) +++#define QCA956X_RESET_CPU_NMI BIT(21) +++#define QCA956X_RESET_CPU_COLD BIT(20) +++#define QCA956X_RESET_DMA BIT(19) +++#define QCA956X_RESET_DDR BIT(16) +++#define QCA956X_RESET_GE1_MAC BIT(13) +++#define QCA956X_RESET_SGMII_ANALOG BIT(12) +++#define QCA956X_RESET_USB_PHY_ANALOG BIT(11) +++#define QCA956X_RESET_GE0_MAC BIT(9) +++#define QCA956X_RESET_SGMII BIT(8) +++#define QCA956X_RESET_USB_HOST BIT(5) +++#define QCA956X_RESET_USB_PHY BIT(4) +++#define QCA956X_RESET_USBSUS_OVERRIDE BIT(3) +++#define QCA956X_RESET_SWITCH_ANALOG BIT(2) +++#define QCA956X_RESET_SWITCH BIT(0) +++ ++ #define AR933X_BOOTSTRAP_MDIO_GPIO_EN BIT(18) ++ #define AR933X_BOOTSTRAP_EEPBUSY BIT(4) ++ #define AR933X_BOOTSTRAP_USB_MODE_HOST BIT(3) ++@@ -1189,6 +1269,7 @@ ++ */ ++ ++ #define QCA955X_GMAC_REG_ETH_CFG 0x00 +++#define QCA955X_GMAC_REG_SGMII_SERDES 0x18 ++ ++ #define QCA955X_ETH_CFG_RGMII_EN BIT(0) ++ #define QCA955X_ETH_CFG_MII_GE0 BIT(1) ++@@ -1210,16 +1291,58 @@ ++ #define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3 ++ #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20 ++ +++#define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15) +++#define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23 +++#define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf ++ /* ++ * QCA956X GMAC Interface ++ */ ++ ++-#define QCA956X_GMAC_REG_ETH_CFG 0x00 +++#define QCA956X_GMAC_REG_ETH_CFG 0x00 +++#define QCA956X_GMAC_REG_SGMII_RESET 0x14 +++#define QCA956X_GMAC_REG_SGMII_SERDES 0x18 +++#define QCA956X_GMAC_REG_MR_AN_CONTROL 0x1c +++#define QCA956X_GMAC_REG_SGMII_CONFIG 0x34 +++#define QCA956X_GMAC_REG_SGMII_DEBUG 0x58 ++ +++#define QCA956X_ETH_CFG_RGMII_EN BIT(0) +++#define QCA956X_ETH_CFG_GE0_SGMII BIT(6) ++ #define QCA956X_ETH_CFG_SW_ONLY_MODE BIT(7) ++-#define QCA956X_ETH_CFG_SW_PHY_SWAP BIT(8) +++#define QCA956X_ETH_CFG_SW_PHY_SWAP BIT(8) ++ #define QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP BIT(9) ++ #define QCA956X_ETH_CFG_SW_APB_ACCESS BIT(10) ++ #define QCA956X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) +++#define QCA956X_ETH_CFG_RXD_DELAY_MASK 0x3 +++#define QCA956X_ETH_CFG_RXD_DELAY_SHIFT 14 +++#define QCA956X_ETH_CFG_RDV_DELAY_MASK 0x3 +++#define QCA956X_ETH_CFG_RDV_DELAY_SHIFT 16 +++ +++#define QCA956X_SGMII_RESET_RX_CLK_N_RESET 0x0 +++#define QCA956X_SGMII_RESET_RX_CLK_N BIT(0) +++#define QCA956X_SGMII_RESET_TX_CLK_N BIT(1) +++#define QCA956X_SGMII_RESET_RX_125M_N BIT(2) +++#define QCA956X_SGMII_RESET_TX_125M_N BIT(3) +++#define QCA956X_SGMII_RESET_HW_RX_125M_N BIT(4) +++ +++#define QCA956X_SGMII_SERDES_CDR_BW_MASK 0x3 +++#define QCA956X_SGMII_SERDES_CDR_BW_SHIFT 1 +++#define QCA956X_SGMII_SERDES_TX_DR_CTRL_MASK 0x7 +++#define QCA956X_SGMII_SERDES_TX_DR_CTRL_SHIFT 4 +++#define QCA956X_SGMII_SERDES_PLL_BW BIT(8) +++#define QCA956X_SGMII_SERDES_VCO_FAST BIT(9) +++#define QCA956X_SGMII_SERDES_VCO_SLOW BIT(10) +++#define QCA956X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15) +++#define QCA956X_SGMII_SERDES_EN_SIGNAL_DETECT BIT(16) +++#define QCA956X_SGMII_SERDES_FIBER_SDO BIT(17) +++#define QCA956X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23 +++#define QCA956X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf +++#define QCA956X_SGMII_SERDES_VCO_REG_SHIFT 27 +++#define QCA956X_SGMII_SERDES_VCO_REG_MASK 0xf +++ +++#define QCA956X_MR_AN_CONTROL_AN_ENABLE BIT(12) +++#define QCA956X_MR_AN_CONTROL_PHY_RESET BIT(15) +++ +++#define QCA956X_SGMII_CONFIG_MODE_CTRL_SHIFT 0 +++#define QCA956X_SGMII_CONFIG_MODE_CTRL_MASK 0x7 ++ ++ #endif /* __ASM_MACH_AR71XX_REGS_H */ +diff --git a/target/linux/ar71xx/patches-4.14/930-chipidea-pullup.patch b/target/linux/ar71xx/patches-4.14/930-chipidea-pullup.patch +new file mode 100644 +index 0000000000..2e9a878630 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/930-chipidea-pullup.patch +@@ -0,0 +1,72 @@ ++--- a/drivers/usb/chipidea/ci.h +++++ b/drivers/usb/chipidea/ci.h ++@@ -205,6 +205,7 @@ struct hw_bank { ++ * @in_lpm: if the core in low power mode ++ * @wakeup_int: if wakeup interrupt occur ++ * @rev: The revision number for controller +++ * @dp_always_pullup: keep dp always pullup at device mode ++ */ ++ struct ci_hdrc { ++ struct device *dev; ++@@ -259,6 +260,7 @@ struct ci_hdrc { ++ bool in_lpm; ++ bool wakeup_int; ++ enum ci_revision rev; +++ bool dp_always_pullup; ++ }; ++ ++ static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) ++--- a/drivers/usb/chipidea/core.c +++++ b/drivers/usb/chipidea/core.c ++@@ -818,7 +818,7 @@ static inline void ci_role_destroy(struc ++ { ++ ci_hdrc_gadget_destroy(ci); ++ ci_hdrc_host_destroy(ci); ++- if (ci->is_otg && ci->roles[CI_ROLE_GADGET]) +++ if (!ci->dp_always_pullup && ci->roles[CI_ROLE_GADGET]) ++ ci_hdrc_otg_destroy(ci); ++ } ++ ++@@ -923,6 +923,9 @@ static int ci_hdrc_probe(struct platform ++ CI_HDRC_SUPPORTS_RUNTIME_PM); ++ platform_set_drvdata(pdev, ci); ++ +++ ci->dp_always_pullup = !!(ci->platdata->flags & +++ CI_HDRC_DP_ALWAYS_PULLUP); +++ ++ ret = hw_device_init(ci, base); ++ if (ret < 0) { ++ dev_err(dev, "can't initialize hardware\n"); ++@@ -1011,7 +1014,7 @@ static int ci_hdrc_probe(struct platform ++ goto deinit_gadget; ++ } ++ ++- if (ci->is_otg && ci->roles[CI_ROLE_GADGET]) { +++ if (!ci->dp_always_pullup && ci->roles[CI_ROLE_GADGET]) { ++ ret = ci_hdrc_otg_init(ci); ++ if (ret) { ++ dev_err(dev, "init otg fails, ret = %d\n", ret); ++--- a/drivers/usb/chipidea/otg.c +++++ b/drivers/usb/chipidea/otg.c ++@@ -131,8 +131,10 @@ enum ci_role ci_otg_role(struct ci_hdrc ++ ++ void ci_handle_vbus_change(struct ci_hdrc *ci) ++ { ++- if (!ci->is_otg) +++ if (ci->dp_always_pullup) { +++ usb_gadget_vbus_connect(&ci->gadget); ++ return; +++ } ++ ++ if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active) ++ usb_gadget_vbus_connect(&ci->gadget); ++--- a/include/linux/usb/chipidea.h +++++ b/include/linux/usb/chipidea.h ++@@ -60,6 +60,7 @@ struct ci_hdrc_platform_data { ++ #define CI_HDRC_OVERRIDE_RX_BURST BIT(11) ++ #define CI_HDRC_OVERRIDE_PHY_CONTROL BIT(12) /* Glue layer manages phy */ ++ #define CI_HDRC_REQUIRES_ALIGNED_DMA BIT(13) +++#define CI_HDRC_DP_ALWAYS_PULLUP BIT(14) ++ enum usb_dr_mode dr_mode; ++ #define CI_HDRC_CONTROLLER_RESET_EVENT 0 ++ #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 +diff --git a/target/linux/ar71xx/patches-4.14/940-qca955x-add-more-registers.patch b/target/linux/ar71xx/patches-4.14/940-qca955x-add-more-registers.patch +new file mode 100644 +index 0000000000..ff72308465 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/940-qca955x-add-more-registers.patch +@@ -0,0 +1,42 @@ ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -134,7 +134,7 @@ ++ #define QCA955X_PCI_CTRL_SIZE 0x100 ++ ++ #define QCA955X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) ++-#define QCA955X_GMAC_SIZE 0x40 +++#define QCA955X_GMAC_SIZE 0x64 ++ #define QCA955X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) ++ #define QCA955X_WMAC_SIZE 0x20000 ++ #define QCA955X_EHCI0_BASE 0x1b000000 ++@@ -1269,7 +1269,11 @@ ++ */ ++ ++ #define QCA955X_GMAC_REG_ETH_CFG 0x00 +++#define QCA955X_GMAC_REG_SGMII_RESET 0x14 ++ #define QCA955X_GMAC_REG_SGMII_SERDES 0x18 +++#define QCA955X_GMAC_REG_MR_AN_CONTROL 0x1c +++#define QCA955X_GMAC_REG_MR_AN_STATUS 0x20 +++#define QCA955X_GMAC_REG_SGMII_DEBUG 0x58 ++ ++ #define QCA955X_ETH_CFG_RGMII_EN BIT(0) ++ #define QCA955X_ETH_CFG_MII_GE0 BIT(1) ++@@ -1291,6 +1295,18 @@ ++ #define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3 ++ #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20 ++ +++#define QCA955X_SGMII_RESET_RX_CLK_N_RESET 0x0 +++#define QCA955X_SGMII_RESET_RX_CLK_N BIT(0) +++#define QCA955X_SGMII_RESET_TX_CLK_N BIT(1) +++#define QCA955X_SGMII_RESET_RX_125M_N BIT(2) +++#define QCA955X_SGMII_RESET_TX_125M_N BIT(3) +++#define QCA955X_SGMII_RESET_HW_RX_125M_N BIT(4) +++ +++#define QCA955X_MR_AN_CONTROL_PHY_RESET BIT(15) +++#define QCA955X_MR_AN_CONTROL_AN_ENABLE BIT(12) +++ +++#define QCA955X_MR_AN_STATUS_AN_ABILITY BIT(3) +++ ++ #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15) ++ #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23 ++ #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf +diff --git a/target/linux/ar71xx/patches-4.14/950-add-boardinfo-platform-data.patch b/target/linux/ar71xx/patches-4.14/950-add-boardinfo-platform-data.patch +new file mode 100644 +index 0000000000..edeac838d9 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/950-add-boardinfo-platform-data.patch +@@ -0,0 +1,67 @@ ++--- a/drivers/net/phy/mdio-boardinfo.c +++++ b/drivers/net/phy/mdio-boardinfo.c ++@@ -15,8 +15,11 @@ ++ ++ #include "mdio-boardinfo.h" ++ ++-static LIST_HEAD(mdio_board_list); ++-static DEFINE_MUTEX(mdio_board_lock); +++LIST_HEAD(mdio_board_list); +++EXPORT_SYMBOL_GPL(mdio_board_list); +++ +++DEFINE_MUTEX(mdio_board_lock); +++EXPORT_SYMBOL_GPL(mdio_board_lock); ++ ++ /** ++ * mdiobus_setup_mdiodev_from_board_info - create and setup MDIO devices ++--- a/drivers/net/phy/mdio-boardinfo.h +++++ b/drivers/net/phy/mdio-boardinfo.h ++@@ -20,4 +20,7 @@ void mdiobus_setup_mdiodev_from_board_in ++ (struct mii_bus *bus, ++ struct mdio_board_info *bi)); ++ +++extern struct mutex mdio_board_lock; +++extern struct list_head mdio_board_list; +++ ++ #endif /* __MDIO_BOARD_INFO_H */ ++--- a/drivers/net/phy/mdio_bus.c +++++ b/drivers/net/phy/mdio_bus.c ++@@ -455,6 +455,17 @@ void mdiobus_free(struct mii_bus *bus) ++ } ++ EXPORT_SYMBOL(mdiobus_free); ++ +++static void mdiobus_setup_phydev_from_boardinfo(struct mii_bus *bus, +++ struct phy_device *phydev, +++ struct mdio_board_info *bi) +++{ +++ if (strcmp(bus->id, bi->bus_id) || +++ bi->mdio_addr != phydev->mdio.addr) +++ return; +++ +++ phydev->mdio.dev.platform_data = (void *) bi->platform_data; +++} +++ ++ /** ++ * mdiobus_scan - scan a bus for MDIO devices. ++ * @bus: mii_bus to scan ++@@ -470,6 +481,7 @@ EXPORT_SYMBOL(mdiobus_free); ++ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) ++ { ++ struct phy_device *phydev; +++ struct mdio_board_entry *be; ++ int err; ++ ++ phydev = get_phy_device(bus, addr, false); ++@@ -482,6 +494,12 @@ struct phy_device *mdiobus_scan(struct m ++ */ ++ of_mdiobus_link_mdiodev(bus, &phydev->mdio); ++ +++ mutex_lock(&mdio_board_lock); +++ list_for_each_entry(be, &mdio_board_list, list) +++ mdiobus_setup_phydev_from_boardinfo(bus, phydev, +++ &be->board_info); +++ mutex_unlock(&mdio_board_lock); +++ ++ err = phy_device_register(phydev); ++ if (err) { ++ phy_device_free(phydev); +diff --git a/target/linux/ar71xx/patches-4.14/952-qca955x-enable-ddr-wb-flush.patch b/target/linux/ar71xx/patches-4.14/952-qca955x-enable-ddr-wb-flush.patch +new file mode 100644 +index 0000000000..16d17b8a0e +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/952-qca955x-enable-ddr-wb-flush.patch +@@ -0,0 +1,49 @@ ++--- a/arch/mips/ath79/common.c +++++ b/arch/mips/ath79/common.c ++@@ -49,6 +49,8 @@ void ath79_ddr_ctrl_init(void) ++ if (soc_is_ar913x() || soc_is_ar724x() || soc_is_ar933x()) { ++ ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c; ++ ath79_ddr_pci_win_base = 0; +++ } else if (soc_is_qca953x() || soc_is_qca955x()) { +++ ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c; ++ } else { ++ ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c; ++ ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c; ++--- a/arch/mips/ath79/irq.c +++++ b/arch/mips/ath79/irq.c ++@@ -105,12 +105,12 @@ static void qca955x_ip2_irq_dispatch(str ++ } ++ ++ if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) { ++- /* TODO: flush DDR? */ +++ ath79_ddr_wb_flush(3); ++ generic_handle_irq(ATH79_IP2_IRQ(0)); ++ } ++ ++ if (status & QCA955X_EXT_INT_WMAC_ALL) { ++- /* TODO: flush DDR? */ +++ ath79_ddr_wb_flush(4); ++ generic_handle_irq(ATH79_IP2_IRQ(1)); ++ } ++ } ++@@ -130,17 +130,17 @@ static void qca955x_ip3_irq_dispatch(str ++ } ++ ++ if (status & QCA955X_EXT_INT_USB1) { ++- /* TODO: flush DDR? */ +++ ath79_ddr_wb_flush(2); ++ generic_handle_irq(ATH79_IP3_IRQ(0)); ++ } ++ ++ if (status & QCA955X_EXT_INT_USB2) { ++- /* TODO: flush DDR? */ +++ ath79_ddr_wb_flush(2); ++ generic_handle_irq(ATH79_IP3_IRQ(1)); ++ } ++ ++ if (status & QCA955X_EXT_INT_PCIE_RC2_ALL) { ++- /* TODO: flush DDR? */ +++ ath79_ddr_wb_flush(3); ++ generic_handle_irq(ATH79_IP3_IRQ(2)); ++ } ++ } +diff --git a/target/linux/ar71xx/patches-4.14/953-qca955x-pci-reset-fixes.patch b/target/linux/ar71xx/patches-4.14/953-qca955x-pci-reset-fixes.patch +new file mode 100644 +index 0000000000..0acca2a08f +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/953-qca955x-pci-reset-fixes.patch +@@ -0,0 +1,120 @@ ++--- a/arch/mips/ath79/common.c +++++ b/arch/mips/ath79/common.c ++@@ -153,6 +153,24 @@ void ath79_device_reset_clear(u32 mask) ++ } ++ EXPORT_SYMBOL_GPL(ath79_device_reset_clear); ++ +++void ath79_device_reset2_clear(u32 mask) +++{ +++ unsigned long flags; +++ u32 reg; +++ u32 t; +++ +++ if (soc_is_qca955x()) +++ reg = QCA955X_RESET_REG_RESET2_MODULE; +++ else +++ panic("Reset register not defined for this SOC"); +++ +++ spin_lock_irqsave(&ath79_device_reset_lock, flags); +++ t = ath79_reset_rr(reg); +++ ath79_reset_wr(reg, t & ~mask); +++ spin_unlock_irqrestore(&ath79_device_reset_lock, flags); +++} +++EXPORT_SYMBOL_GPL(ath79_device_reset2_clear); +++ ++ u32 ath79_device_reset_get(u32 mask) ++ { ++ unsigned long flags; ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -411,6 +411,7 @@ ++ #define QCA955X_PLL_CPU_CONFIG_REG 0x00 ++ #define QCA955X_PLL_DDR_CONFIG_REG 0x04 ++ #define QCA955X_PLL_CLK_CTRL_REG 0x08 +++#define QCA955X_PLL_PCIE_CONFIG_REG 0x0c ++ #define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28 ++ #define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48 ++ #define QCA955X_PLL_ETH_SGMII_SERDES_REG 0x4c ++@@ -565,6 +566,7 @@ ++ #define QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac ++ ++ #define QCA955X_RESET_REG_RESET_MODULE 0x1c +++#define QCA955X_RESET_REG_RESET2_MODULE 0xc4 ++ #define QCA955X_RESET_REG_BOOTSTRAP 0xb0 ++ #define QCA955X_RESET_REG_EXT_INT_STATUS 0xac ++ ++--- a/arch/mips/include/asm/mach-ath79/ath79.h +++++ b/arch/mips/include/asm/mach-ath79/ath79.h ++@@ -178,6 +178,7 @@ static inline u32 ath79_reset_rr(unsigne ++ ++ void ath79_device_reset_set(u32 mask); ++ void ath79_device_reset_clear(u32 mask); +++void ath79_device_reset2_clear(u32 mask); ++ u32 ath79_device_reset_get(u32 mask); ++ ++ void ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3); ++--- a/arch/mips/pci/pci-ar724x.c +++++ b/arch/mips/pci/pci-ar724x.c ++@@ -335,18 +335,37 @@ static void ar724x_pci_hw_init(struct ar ++ int wait = 0; ++ ++ /* deassert PCIe host controller and PCIe PHY reset */ ++- ath79_device_reset_clear(AR724X_RESET_PCIE); ++- ath79_device_reset_clear(AR724X_RESET_PCIE_PHY); +++ if (soc_is_qca955x()) { +++ ath79_device_reset_clear(QCA955X_RESET_PCIE); +++ mdelay(10); +++ ath79_device_reset_clear(QCA955X_RESET_PCIE_PHY); +++ mdelay(10); +++ ath79_device_reset2_clear(QCA955X_RESET_PCIE); +++ mdelay(10); +++ ath79_device_reset2_clear(QCA955X_RESET_PCIE_PHY); +++ mdelay(10); +++ } else { +++ ath79_device_reset_clear(AR724X_RESET_PCIE); +++ ath79_device_reset_clear(AR724X_RESET_PCIE_PHY); +++ } ++ ++ /* remove the reset of the PCIE PLL */ ++- ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); ++- ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; ++- ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); +++ if (!soc_is_qca955x()) { +++ ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); +++ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; +++ ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); +++ } ++ ++ /* deassert bypass for the PCIE PLL */ ++- ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); ++- ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; ++- ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); +++ if (soc_is_qca955x()) { +++ ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG); +++ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; +++ ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl); +++ } else { +++ ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); +++ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; +++ ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); +++ } ++ ++ /* set PCIE Application Control to ready */ ++ app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP); ++@@ -422,8 +441,14 @@ static int ar724x_pci_probe(struct platf ++ * Do the full PCIE Root Complex Initialization Sequence if the PCIe ++ * host controller is in reset. ++ */ ++- if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE) ++- ar724x_pci_hw_init(apc); +++ if (soc_is_qca955x()) { +++ if (ath79_reset_rr(QCA955X_RESET_REG_RESET_MODULE) & QCA955X_RESET_PCIE || +++ ath79_reset_rr(QCA955X_RESET_REG_RESET2_MODULE) & QCA955X_RESET_PCIE) +++ ar724x_pci_hw_init(apc); +++ } else { +++ if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE) +++ ar724x_pci_hw_init(apc); +++ } ++ ++ apc->link_up = ar724x_pci_check_link(apc); ++ if (!apc->link_up) +diff --git a/target/linux/ar71xx/patches-4.14/955-qca953x-fix-potential-missing-irq-dispatch.patch b/target/linux/ar71xx/patches-4.14/955-qca953x-fix-potential-missing-irq-dispatch.patch +new file mode 100644 +index 0000000000..5174029989 +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/955-qca953x-fix-potential-missing-irq-dispatch.patch +@@ -0,0 +1,27 @@ ++--- a/arch/mips/ath79/irq.c +++++ b/arch/mips/ath79/irq.c ++@@ -69,15 +69,21 @@ static void qca953x_ip2_irq_dispatch(str ++ u32 status; ++ ++ status = ath79_reset_rr(QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS); +++ status &= QCA953X_PCIE_WMAC_INT_PCIE_ALL | QCA953X_PCIE_WMAC_INT_WMAC_ALL; +++ +++ if (status == 0) { +++ spurious_interrupt(); +++ return; +++ } ++ ++ if (status & QCA953X_PCIE_WMAC_INT_PCIE_ALL) { ++ ath79_ddr_wb_flush(3); ++ generic_handle_irq(ATH79_IP2_IRQ(0)); ++- } else if (status & QCA953X_PCIE_WMAC_INT_WMAC_ALL) { +++ } +++ +++ if (status & QCA953X_PCIE_WMAC_INT_WMAC_ALL) { ++ ath79_ddr_wb_flush(4); ++ generic_handle_irq(ATH79_IP2_IRQ(1)); ++- } else { ++- spurious_interrupt(); ++ } ++ } ++ +diff --git a/target/linux/ar71xx/patches-4.14/999-backport-fixes.patch b/target/linux/ar71xx/patches-4.14/999-backport-fixes.patch +new file mode 100644 +index 0000000000..a78519ccaf +--- /dev/null ++++ b/target/linux/ar71xx/patches-4.14/999-backport-fixes.patch +@@ -0,0 +1,191 @@ ++Index: linux-4.14.193/drivers/mtd/mtdsplit/mtdsplit_squashfs.c ++=================================================================== ++--- linux-4.14.193.orig/drivers/mtd/mtdsplit/mtdsplit_squashfs.c +++++ linux-4.14.193/drivers/mtd/mtdsplit/mtdsplit_squashfs.c ++@@ -36,7 +36,7 @@ mtdsplit_parse_squashfs(struct mtd_info ++ if (err) ++ return err; ++ ++- parent_mtd = mtd_get_master(master); +++ parent_mtd = mtdpart_get_master(master); ++ part_offset = mtdpart_get_offset(master); ++ ++ part = kzalloc(sizeof(*part), GFP_KERNEL); ++Index: linux-4.14.193/drivers/net/phy/swconfig.c ++=================================================================== ++--- linux-4.14.193.orig/drivers/net/phy/swconfig.c +++++ linux-4.14.193/drivers/net/phy/swconfig.c ++@@ -591,8 +591,13 @@ swconfig_parse_ports(struct sk_buff *msg ++ ++ port = &val->value.ports[val->len]; ++ +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ if (nla_parse_nested_deprecated(tb, SWITCH_PORT_ATTR_MAX, nla, ++ port_policy, NULL)) +++#else +++ if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla, +++ port_policy, NULL)) +++#endif ++ return -EINVAL; ++ ++ if (!tb[SWITCH_PORT_ID]) ++@@ -613,7 +618,11 @@ swconfig_parse_link(struct sk_buff *msg, ++ { ++ struct nlattr *tb[SWITCH_LINK_ATTR_MAX + 1]; ++ +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ if (nla_parse_nested_deprecated(tb, SWITCH_LINK_ATTR_MAX, nla, link_policy, NULL)) +++#else +++ if (nla_parse_nested(tb, SWITCH_LINK_ATTR_MAX, nla, link_policy, NULL)) +++#endif ++ return -EINVAL; ++ ++ link->duplex = !!tb[SWITCH_LINK_FLAG_DUPLEX]; ++@@ -991,56 +1000,106 @@ swconfig_done(struct netlink_callback *c ++ static struct genl_ops swconfig_ops[] = { ++ { ++ .cmd = SWITCH_CMD_LIST_GLOBAL, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .doit = swconfig_list_attrs, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_LIST_VLAN, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .doit = swconfig_list_attrs, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_LIST_PORT, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .doit = swconfig_list_attrs, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_GET_GLOBAL, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .doit = swconfig_get_attr, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_GET_VLAN, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .doit = swconfig_get_attr, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_GET_PORT, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .doit = swconfig_get_attr, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_SET_GLOBAL, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .flags = GENL_ADMIN_PERM, ++ .doit = swconfig_set_attr, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_SET_VLAN, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .flags = GENL_ADMIN_PERM, ++ .doit = swconfig_set_attr, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_SET_PORT, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .flags = GENL_ADMIN_PERM, ++ .doit = swconfig_set_attr, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ }, ++ { ++ .cmd = SWITCH_CMD_GET_SWITCH, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0) ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +++#endif ++ .dumpit = swconfig_dump_switches, +++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +++ .policy = switch_policy, +++#endif ++ .done = swconfig_done, ++ } ++ }; ++@@ -1050,7 +1109,9 @@ static struct genl_family switch_fam = { ++ .hdrsize = 0, ++ .version = 1, ++ .maxattr = SWITCH_ATTR_MAX, +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) ++ .policy = switch_policy, +++#endif ++ .module = THIS_MODULE, ++ .ops = swconfig_ops, ++ .n_ops = ARRAY_SIZE(swconfig_ops), ++Index: linux-4.14.193/drivers/net/phy/swconfig_leds.c ++=================================================================== ++--- linux-4.14.193.orig/drivers/net/phy/swconfig_leds.c +++++ linux-4.14.193/drivers/net/phy/swconfig_leds.c ++@@ -321,6 +321,14 @@ err_free: ++ return err; ++ } ++ +++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) +++static void +++swconfig_trig_activate_void(struct led_classdev *led_cdev) +++{ +++ swconfig_trig_activate(led_cdev); +++} +++#endif +++ ++ static void ++ swconfig_trig_deactivate(struct led_classdev *led_cdev) ++ { ++@@ -515,7 +523,11 @@ swconfig_create_led_trigger(struct switc ++ ++ sw_trig->swdev = swdev; ++ sw_trig->trig.name = swdev->devname; +++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) +++ sw_trig->trig.activate = swconfig_trig_activate_void; +++#else ++ sw_trig->trig.activate = swconfig_trig_activate; +++#endif ++ sw_trig->trig.deactivate = swconfig_trig_deactivate; ++ ++ INIT_DELAYED_WORK(&sw_trig->sw_led_work, swconfig_led_work_func); +diff --git a/target/linux/ar71xx/tiny/config-default b/target/linux/ar71xx/tiny/config-default +new file mode 100644 +index 0000000000..1148d8c451 +--- /dev/null ++++ b/target/linux/ar71xx/tiny/config-default +@@ -0,0 +1,76 @@ ++CONFIG_ATH79_DEV_AP9X_PCI=y ++CONFIG_ATH79_DEV_DSA=y ++CONFIG_ATH79_DEV_ETH=y ++CONFIG_ATH79_DEV_GPIO_BUTTONS=y ++CONFIG_ATH79_DEV_LEDS_GPIO=y ++CONFIG_ATH79_DEV_M25P80=y ++# CONFIG_ATH79_DEV_NFC is not set ++CONFIG_ATH79_DEV_SPI=y ++CONFIG_ATH79_DEV_USB=y ++CONFIG_ATH79_DEV_WMAC=y ++CONFIG_ATH79_MACH_BHR_4GRV2=y ++CONFIG_ATH79_MACH_DIR_600_A1=y ++CONFIG_ATH79_MACH_DIR_615_C1=y ++CONFIG_ATH79_MACH_DIR_615_I1=y ++CONFIG_ATH79_MACH_ENS202EXT=y ++CONFIG_ATH79_MACH_F9K1115V2=y ++CONFIG_ATH79_MACH_NBG460N=y ++CONFIG_ATH79_MACH_TEW_632BRP=y ++CONFIG_ATH79_MACH_TEW_712BR=y ++CONFIG_ATH79_MACH_TL_MR11U=y ++CONFIG_ATH79_MACH_TL_MR13U=y ++CONFIG_ATH79_MACH_TL_MR3020=y ++CONFIG_ATH79_MACH_TL_MR3X20=y ++CONFIG_ATH79_MACH_TL_WA701ND_V2=y ++CONFIG_ATH79_MACH_TL_WA7210N_V2=y ++CONFIG_ATH79_MACH_TL_WA801ND_V3=y ++CONFIG_ATH79_MACH_TL_WA830RE_V2=y ++CONFIG_ATH79_MACH_TL_WA850RE_V2=y ++CONFIG_ATH79_MACH_TL_WA855RE_V1=y ++CONFIG_ATH79_MACH_TL_WA901ND=y ++CONFIG_ATH79_MACH_TL_WA901ND_V2=y ++CONFIG_ATH79_MACH_TL_WA901ND_V4=y ++CONFIG_ATH79_MACH_TL_WAX50RE=y ++CONFIG_ATH79_MACH_TL_WDR3320_V2=y ++CONFIG_ATH79_MACH_TL_WDR3500=y ++CONFIG_ATH79_MACH_TL_WR1041N_V2=y ++CONFIG_ATH79_MACH_TL_WR703N=y ++CONFIG_ATH79_MACH_TL_WR720N_V3=y ++CONFIG_ATH79_MACH_TL_WR741ND=y ++CONFIG_ATH79_MACH_TL_WR741ND_V4=y ++CONFIG_ATH79_MACH_TL_WR802N_V1=y ++CONFIG_ATH79_MACH_TL_WR802N_V2=y ++CONFIG_ATH79_MACH_TL_WR840N_V2=y ++CONFIG_ATH79_MACH_TL_WR841N_V1=y ++CONFIG_ATH79_MACH_TL_WR841N_V8=y ++CONFIG_ATH79_MACH_TL_WR841N_V9=y ++CONFIG_ATH79_MACH_TL_WR940N_V4=y ++CONFIG_ATH79_MACH_TL_WR941ND=y ++CONFIG_ATH79_MACH_TL_WR941ND_V6=y ++CONFIG_ATH79_MACH_WHR_HP_G300N=y ++CONFIG_ATH79_MACH_WLAE_AG300N=y ++CONFIG_ATH79_MACH_WNR2000=y ++CONFIG_ATH79_MACH_WNR2000_V3=y ++CONFIG_ATH79_MACH_WNR2000_V4=y ++CONFIG_ATH79_MACH_WP543=y ++CONFIG_ATH79_MACH_WPE72=y ++CONFIG_ATH79_MACH_ZBT_WE1526=y ++CONFIG_ATH79_NVRAM=y ++CONFIG_ATH79_PCI_ATH9K_FIXUP=y ++CONFIG_BLK_MQ_PCI=y ++CONFIG_HW_HAS_PCI=y ++CONFIG_MYLOADER=y ++CONFIG_PCI=y ++CONFIG_PCI_AR724X=y ++CONFIG_PCI_DISABLE_COMMON_QUIRKS=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_SERIAL_AR933X=y ++CONFIG_SERIAL_AR933X_CONSOLE=y ++CONFIG_SERIAL_AR933X_NR_UARTS=2 ++CONFIG_SOC_AR71XX=y ++CONFIG_SOC_AR724X=y ++CONFIG_SOC_AR913X=y ++CONFIG_SOC_AR933X=y ++CONFIG_SOC_AR934X=y ++CONFIG_SOC_QCA953X=y ++CONFIG_SOC_QCA956X=y +diff --git a/target/linux/ar71xx/tiny/profiles/00-default.mk b/target/linux/ar71xx/tiny/profiles/00-default.mk +new file mode 100644 +index 0000000000..edddeb3bf6 +--- /dev/null ++++ b/target/linux/ar71xx/tiny/profiles/00-default.mk +@@ -0,0 +1,11 @@ ++define Profile/Default ++ NAME:=Default Profile (all drivers) ++ PACKAGES:= \ ++ kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport ++ PRIORITY := 1 ++endef ++ ++define Profile/Default/Description ++ Default package set compatible with most boards. ++endef ++$(eval $(call Profile,Default)) +diff --git a/target/linux/ar71xx/tiny/target.mk b/target/linux/ar71xx/tiny/target.mk +new file mode 100644 +index 0000000000..89d4447e1e +--- /dev/null ++++ b/target/linux/ar71xx/tiny/target.mk +@@ -0,0 +1,10 @@ ++BOARDNAME:=Devices with small flash ++FEATURES += squashfs small_flash ++ ++DEFAULT_PACKAGES += wpad-mini ++ ++define Target/Description ++ Build firmware images for Atheros AR71xx/AR913x/AR934x based boards with small NOR flash. ++endef ++ ++ +diff --git a/target/linux/generic/backport-4.14/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch b/target/linux/generic/backport-4.14/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch +new file mode 100644 +index 0000000000..7ac4f9d240 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch +@@ -0,0 +1,30 @@ ++From 13b1ecc3401653a355798eb1dee10cc1608202f4 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Mon, 18 Jan 2016 12:27:49 +0100 ++Subject: [PATCH 33/34] Kbuild: don't hardcode path to awk in ++ scripts/ld-version.sh ++ ++On some systems /usr/bin/awk does not exist, or is broken. Find it via ++$PATH instead. ++ ++Signed-off-by: Felix Fietkau ++--- ++ scripts/ld-version.sh | 4 +++- ++ 1 file changed, 3 insertions(+), 1 deletion(-) ++ ++--- a/scripts/ld-version.sh +++++ b/scripts/ld-version.sh ++@@ -1,6 +1,7 @@ ++-#!/usr/bin/awk -f +++#!/bin/sh ++ # SPDX-License-Identifier: GPL-2.0 ++ # extract linker version number from stdin and turn into single number +++exec awk ' ++ { ++ gsub(".*\\)", ""); ++ gsub(".*version ", ""); ++@@ -9,3 +10,4 @@ ++ print a[1]*100000000 + a[2]*1000000 + a[3]*10000; ++ exit ++ } +++' +diff --git a/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch b/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch +new file mode 100644 +index 0000000000..1c82a9576a +--- /dev/null ++++ b/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch +@@ -0,0 +1,23 @@ ++From 173019b66dcc9d68ad9333aa744dad1e369b5aa8 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sun, 9 Jul 2017 00:26:53 +0200 ++Subject: [PATCH 34/34] kernel: add compile fix for linux 4.9 on x86 ++ ++Signed-off-by: Felix Fietkau ++--- ++ Makefile | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++--- a/Makefile +++++ b/Makefile ++@@ -429,8 +429,8 @@ KBUILD_LDFLAGS_MODULE := -T $(srctree)/s ++ GCC_PLUGINS_CFLAGS := ++ CLANG_FLAGS := ++ ++-export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC ++-export CPP AR NM STRIP OBJCOPY OBJDUMP HOSTLDFLAGS HOST_LOADLIBES +++export ARCH SRCARCH SUBARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD +++export CC CPP AR NM STRIP OBJCOPY OBJDUMP HOSTLDFLAGS HOST_LOADLIBES ++ export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE ++ export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS ++ +diff --git a/target/linux/generic/backport-4.14/012-kbuild-add-macro-for-controlling-warnings-to-linux-c.patch b/target/linux/generic/backport-4.14/012-kbuild-add-macro-for-controlling-warnings-to-linux-c.patch +new file mode 100644 +index 0000000000..8993b6376c +--- /dev/null ++++ b/target/linux/generic/backport-4.14/012-kbuild-add-macro-for-controlling-warnings-to-linux-c.patch +@@ -0,0 +1,142 @@ ++From: Arnd Bergmann ++Date: Tue, 19 Jun 2018 13:14:56 -0700 ++Subject: [PATCH] kbuild: add macro for controlling warnings to ++ linux/compiler.h ++ ++I have occasionally run into a situation where it would make sense to ++control a compiler warning from a source file rather than doing so from ++a Makefile using the $(cc-disable-warning, ...) or $(cc-option, ...) ++helpers. ++ ++The approach here is similar to what glibc uses, using __diag() and ++related macros to encapsulate a _Pragma("GCC diagnostic ...") statement ++that gets turned into the respective "#pragma GCC diagnostic ..." by ++the preprocessor when the macro gets expanded. ++ ++Like glibc, I also have an argument to pass the affected compiler ++version, but decided to actually evaluate that one. For now, this ++supports GCC_4_6, GCC_4_7, GCC_4_8, GCC_4_9, GCC_5, GCC_6, GCC_7, ++GCC_8 and GCC_9. Adding support for CLANG_5 and other interesting ++versions is straightforward here. GNU compilers starting with gcc-4.2 ++could support it in principle, but "#pragma GCC diagnostic push" ++was only added in gcc-4.6, so it seems simpler to not deal with those ++at all. The same versions show a large number of warnings already, ++so it seems easier to just leave it at that and not do a more ++fine-grained control for them. ++ ++The use cases I found so far include: ++ ++- turning off the gcc-8 -Wattribute-alias warning inside of the ++ SYSCALL_DEFINEx() macro without having to do it globally. ++ ++- Reducing the build time for a simple re-make after a change, ++ once we move the warnings from ./Makefile and ++ ./scripts/Makefile.extrawarn into linux/compiler.h ++ ++- More control over the warnings based on other configurations, ++ using preprocessor syntax instead of Makefile syntax. This should make ++ it easier for the average developer to understand and change things. ++ ++- Adding an easy way to turn the W=1 option on unconditionally ++ for a subdirectory or a specific file. This has been requested ++ by several developers in the past that want to have their subsystems ++ W=1 clean. ++ ++- Integrating clang better into the build systems. Clang supports ++ more warnings than GCC, and we probably want to classify them ++ as default, W=1, W=2 etc, but there are cases in which the ++ warnings should be classified differently due to excessive false ++ positives from one or the other compiler. ++ ++- Adding a way to turn the default warnings into errors (e.g. using ++ a new "make E=0" tag) while not also turning the W=1 warnings into ++ errors. ++ ++This patch for now just adds the minimal infrastructure in order to ++do the first of the list above. As the #pragma GCC diagnostic ++takes precedence over command line options, the next step would be ++to convert a lot of the individual Makefiles that set nonstandard ++options to use __diag() instead. ++ ++[paul.burton@mips.com: ++ - Rebase atop current master. ++ - Add __diag_GCC, or more generally __diag_, abstraction to ++ avoid code outside of linux/compiler-gcc.h needing to duplicate ++ knowledge about different GCC versions. ++ - Add a comment argument to __diag_{ignore,warn,error} which isn't ++ used in the expansion of the macros but serves to push people to ++ document the reason for using them - per feedback from Kees Cook. ++ - Translate severity to GCC-specific pragmas in linux/compiler-gcc.h ++ rather than using GCC-specific in linux/compiler_types.h. ++ - Drop all but GCC 8 macros, since we only need to define macros for ++ versions that we need to introduce pragmas for, and as of this ++ series that's just GCC 8. ++ - Capitalize comments in linux/compiler-gcc.h to match the style of ++ the rest of the file. ++ - Line up macro definitions with tabs in linux/compiler-gcc.h.] ++ ++Signed-off-by: Arnd Bergmann ++Signed-off-by: Paul Burton ++Tested-by: Christophe Leroy ++Tested-by: Stafford Horne ++Signed-off-by: Masahiro Yamada ++--- ++ ++--- a/include/linux/compiler-gcc.h +++++ b/include/linux/compiler-gcc.h ++@@ -366,3 +366,30 @@ ++ #if GCC_VERSION >= 50100 ++ #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 ++ #endif +++ +++ +++/* +++ * Turn individual warnings and errors on and off locally, depending +++ * on version. +++ */ +++#define __diag_GCC(version, severity, s) \ +++ __diag_GCC_ ## version(__diag_GCC_ ## severity s) +++ +++/* Severity used in pragma directives */ +++#define __diag_GCC_ignore ignored +++#define __diag_GCC_warn warning +++#define __diag_GCC_error error +++ +++/* Compilers before gcc-4.6 do not understand "#pragma GCC diagnostic push" */ +++#if GCC_VERSION >= 40600 +++#define __diag_str1(s) #s +++#define __diag_str(s) __diag_str1(s) +++#define __diag(s) _Pragma(__diag_str(GCC diagnostic s)) +++#endif +++ +++#if GCC_VERSION >= 80000 +++#define __diag_GCC_8(s) __diag(s) +++#else +++#define __diag_GCC_8(s) +++#endif +++ ++--- a/include/linux/compiler_types.h +++++ b/include/linux/compiler_types.h ++@@ -287,4 +287,22 @@ struct ftrace_likely_data { ++ # define __native_word(t) (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long)) ++ #endif ++ +++#ifndef __diag +++#define __diag(string) +++#endif +++ +++#ifndef __diag_GCC +++#define __diag_GCC(version, severity, string) +++#endif +++ +++#define __diag_push() __diag(push) +++#define __diag_pop() __diag(pop) +++ +++#define __diag_ignore(compiler, version, option, comment) \ +++ __diag_ ## compiler(version, ignore, option) +++#define __diag_warn(compiler, version, option, comment) \ +++ __diag_ ## compiler(version, warn, option) +++#define __diag_error(compiler, version, option, comment) \ +++ __diag_ ## compiler(version, error, option) +++ ++ #endif /* __LINUX_COMPILER_TYPES_H */ +diff --git a/target/linux/generic/backport-4.14/013-disable-Wattribute-alias-warning-for-SYSCALL_DEFINEx.patch b/target/linux/generic/backport-4.14/013-disable-Wattribute-alias-warning-for-SYSCALL_DEFINEx.patch +new file mode 100644 +index 0000000000..2440ed8c0d +--- /dev/null ++++ b/target/linux/generic/backport-4.14/013-disable-Wattribute-alias-warning-for-SYSCALL_DEFINEx.patch +@@ -0,0 +1,88 @@ ++From: Arnd Bergmann ++Date: Tue, 19 Jun 2018 13:14:57 -0700 ++Subject: [PATCH] disable -Wattribute-alias warning for SYSCALL_DEFINEx() ++ ++gcc-8 warns for every single definition of a system call entry ++point, e.g.: ++ ++include/linux/compat.h:56:18: error: 'compat_sys_rt_sigprocmask' alias between functions of incompatible types 'long int(int, compat_sigset_t *, compat_sigset_t *, compat_size_t)' {aka 'long int(int, struct *, struct *, unsigned int)'} and 'long int(long int, long int, long int, long int)' [-Werror=attribute-alias] ++ asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))\ ++ ^~~~~~~~~~ ++include/linux/compat.h:45:2: note: in expansion of macro 'COMPAT_SYSCALL_DEFINEx' ++ COMPAT_SYSCALL_DEFINEx(4, _##name, __VA_ARGS__) ++ ^~~~~~~~~~~~~~~~~~~~~~ ++kernel/signal.c:2601:1: note: in expansion of macro 'COMPAT_SYSCALL_DEFINE4' ++ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, ++ ^~~~~~~~~~~~~~~~~~~~~~ ++include/linux/compat.h:60:18: note: aliased declaration here ++ asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\ ++ ^~~~~~~~~~ ++ ++The new warning seems reasonable in principle, but it doesn't ++help us here, since we rely on the type mismatch to sanitize the ++system call arguments. After I reported this as GCC PR82435, a new ++-Wno-attribute-alias option was added that could be used to turn the ++warning off globally on the command line, but I'd prefer to do it a ++little more fine-grained. ++ ++Interestingly, turning a warning off and on again inside of ++a single macro doesn't always work, in this case I had to add ++an extra statement inbetween and decided to copy the __SC_TEST ++one from the native syscall to the compat syscall macro. See ++https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83256 for more details ++about this. ++ ++[paul.burton@mips.com: ++ - Rebase atop current master. ++ - Split GCC & version arguments to __diag_ignore() in order to match ++ changes to the preceding patch. ++ - Add the comment argument to match the preceding patch.] ++ ++Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82435 ++Signed-off-by: Arnd Bergmann ++Signed-off-by: Paul Burton ++Tested-by: Christophe Leroy ++Tested-by: Stafford Horne ++Signed-off-by: Masahiro Yamada ++--- ++ ++--- a/include/linux/compat.h +++++ b/include/linux/compat.h ++@@ -48,6 +48,9 @@ ++ COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) ++ ++ #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ +++ __diag_push(); \ +++ __diag_ignore(GCC, 8, "-Wattribute-alias", \ +++ "Type aliasing is used to sanitize syscall arguments");\ ++ asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))\ ++ __attribute__((alias(__stringify(compat_SyS##name)))); \ ++ static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ ++@@ -56,6 +59,7 @@ ++ { \ ++ return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ ++ } \ +++ __diag_pop(); \ ++ static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) ++ ++ #ifndef compat_user_stack_pointer ++--- a/include/linux/syscalls.h +++++ b/include/linux/syscalls.h ++@@ -208,6 +208,9 @@ static inline int is_syscall_trace_event ++ ++ #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) ++ #define __SYSCALL_DEFINEx(x, name, ...) \ +++ __diag_push(); \ +++ __diag_ignore(GCC, 8, "-Wattribute-alias", \ +++ "Type aliasing is used to sanitize syscall arguments");\ ++ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ ++ __attribute__((alias(__stringify(SyS##name)))); \ ++ static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ ++@@ -219,6 +222,7 @@ static inline int is_syscall_trace_event ++ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ ++ return ret; \ ++ } \ +++ __diag_pop(); \ ++ static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) ++ ++ /* +diff --git a/target/linux/generic/backport-4.14/020-backport_netfilter_rtcache.patch b/target/linux/generic/backport-4.14/020-backport_netfilter_rtcache.patch +new file mode 100644 +index 0000000000..88e5386c1f +--- /dev/null ++++ b/target/linux/generic/backport-4.14/020-backport_netfilter_rtcache.patch +@@ -0,0 +1,558 @@ ++From 1bb0c3ec899827cfa4668bb63a08713a40744d21 Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Sun, 9 Jul 2017 08:58:30 +0200 ++Subject: [PATCH] netfilter: conntrack: cache route for forwarded connections ++ ++... to avoid per-packet FIB lookup if possible. ++ ++The cached dst is re-used provided the input interface ++is the same as that of the previous packet in the same direction. ++ ++If not, the cached dst is invalidated. ++ ++For ipv6 we also need to store sernum, else dst_check doesn't work, ++pointed out by Eric Dumazet. ++ ++This should speed up forwarding when conntrack is already in use ++anyway, especially when using reverse path filtering -- active RPF ++enforces two FIB lookups for each packet. ++ ++Before the routing cache removal this didn't matter since RPF was performed ++only when route cache didn't yield a result; but without route cache it ++comes at higher price. ++ ++Julian Anastasov suggested to add NETDEV_UNREGISTER handler to ++avoid holding on to dsts of 'frozen' conntracks. ++ ++Signed-off-by: Florian Westphal ++--- ++ include/net/netfilter/nf_conntrack_extend.h | 4 + ++ include/net/netfilter/nf_conntrack_rtcache.h | 34 +++ ++ net/netfilter/Kconfig | 12 + ++ net/netfilter/Makefile | 3 + ++ net/netfilter/nf_conntrack_rtcache.c | 428 +++++++++++++++++++++++++++ ++ 5 files changed, 481 insertions(+) ++ create mode 100644 include/net/netfilter/nf_conntrack_rtcache.h ++ create mode 100644 net/netfilter/nf_conntrack_rtcache.c ++ ++--- a/include/net/netfilter/nf_conntrack_extend.h +++++ b/include/net/netfilter/nf_conntrack_extend.h ++@@ -28,6 +28,9 @@ enum nf_ct_ext_id { ++ #if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY) ++ NF_CT_EXT_SYNPROXY, ++ #endif +++#if IS_ENABLED(CONFIG_NF_CONNTRACK_RTCACHE) +++ NF_CT_EXT_RTCACHE, +++#endif ++ NF_CT_EXT_NUM, ++ }; ++ ++@@ -40,6 +43,7 @@ enum nf_ct_ext_id { ++ #define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout ++ #define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels ++ #define NF_CT_EXT_SYNPROXY_TYPE struct nf_conn_synproxy +++#define NF_CT_EXT_RTCACHE_TYPE struct nf_conn_rtcache ++ ++ /* Extensions: optional stuff which isn't permanently in struct. */ ++ struct nf_ct_ext { ++--- /dev/null +++++ b/include/net/netfilter/nf_conntrack_rtcache.h ++@@ -0,0 +1,34 @@ +++#include +++#include +++#include +++ +++struct dst_entry; +++ +++struct nf_conn_dst_cache { +++ struct dst_entry *dst; +++ int iif; +++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) +++ u32 cookie; +++#endif +++ +++}; +++ +++struct nf_conn_rtcache { +++ struct nf_conn_dst_cache cached_dst[IP_CT_DIR_MAX]; +++}; +++ +++static inline +++struct nf_conn_rtcache *nf_ct_rtcache_find(const struct nf_conn *ct) +++{ +++#if IS_ENABLED(CONFIG_NF_CONNTRACK_RTCACHE) +++ return nf_ct_ext_find(ct, NF_CT_EXT_RTCACHE); +++#else +++ return NULL; +++#endif +++} +++ +++static inline int nf_conn_rtcache_iif_get(const struct nf_conn_rtcache *rtc, +++ enum ip_conntrack_dir dir) +++{ +++ return rtc->cached_dst[dir].iif; +++} ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -118,6 +118,18 @@ config NF_CONNTRACK_EVENTS ++ ++ If unsure, say `N'. ++ +++config NF_CONNTRACK_RTCACHE +++ tristate "Cache route entries in conntrack objects" +++ depends on NETFILTER_ADVANCED +++ depends on NF_CONNTRACK +++ help +++ If this option is enabled, the connection tracking code will +++ cache routing information for each connection that is being +++ forwarded, at a cost of 32 bytes per conntrack object. +++ +++ To compile it as a module, choose M here. If unsure, say N. +++ The module will be called nf_conntrack_rtcache. +++ ++ config NF_CONNTRACK_TIMEOUT ++ bool 'Connection tracking timeout' ++ depends on NETFILTER_ADVANCED ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -19,6 +19,9 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += n ++ # connection tracking ++ obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o ++ +++# optional conntrack route cache extension +++obj-$(CONFIG_NF_CONNTRACK_RTCACHE) += nf_conntrack_rtcache.o +++ ++ obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o ++ ++ # netlink interface for nf_conntrack ++--- /dev/null +++++ b/net/netfilter/nf_conntrack_rtcache.c ++@@ -0,0 +1,428 @@ +++/* route cache for netfilter. +++ * +++ * (C) 2014 Red Hat GmbH +++ * +++ * 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. +++ */ +++ +++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +++ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++#include +++ +++#include +++#include +++#include +++#include +++ +++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) +++#include +++#endif +++ +++static void __nf_conn_rtcache_destroy(struct nf_conn_rtcache *rtc, +++ enum ip_conntrack_dir dir) +++{ +++ struct dst_entry *dst = rtc->cached_dst[dir].dst; +++ +++ dst_release(dst); +++} +++ +++static void nf_conn_rtcache_destroy(struct nf_conn *ct) +++{ +++ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct); +++ +++ if (!rtc) +++ return; +++ +++ __nf_conn_rtcache_destroy(rtc, IP_CT_DIR_ORIGINAL); +++ __nf_conn_rtcache_destroy(rtc, IP_CT_DIR_REPLY); +++} +++ +++static void nf_ct_rtcache_ext_add(struct nf_conn *ct) +++{ +++ struct nf_conn_rtcache *rtc; +++ +++ rtc = nf_ct_ext_add(ct, NF_CT_EXT_RTCACHE, GFP_ATOMIC); +++ if (rtc) { +++ rtc->cached_dst[IP_CT_DIR_ORIGINAL].iif = -1; +++ rtc->cached_dst[IP_CT_DIR_ORIGINAL].dst = NULL; +++ rtc->cached_dst[IP_CT_DIR_REPLY].iif = -1; +++ rtc->cached_dst[IP_CT_DIR_REPLY].dst = NULL; +++ } +++} +++ +++static struct nf_conn_rtcache *nf_ct_rtcache_find_usable(struct nf_conn *ct) +++{ +++ return nf_ct_rtcache_find(ct); +++} +++ +++static struct dst_entry * +++nf_conn_rtcache_dst_get(const struct nf_conn_rtcache *rtc, +++ enum ip_conntrack_dir dir) +++{ +++ return rtc->cached_dst[dir].dst; +++} +++ +++static u32 nf_rtcache_get_cookie(int pf, const struct dst_entry *dst) +++{ +++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) +++ if (pf == NFPROTO_IPV6) { +++ const struct rt6_info *rt = (const struct rt6_info *)dst; +++ +++ if (rt->rt6i_node) +++ return (u32)rt->rt6i_node->fn_sernum; +++ } +++#endif +++ return 0; +++} +++ +++static void nf_conn_rtcache_dst_set(int pf, +++ struct nf_conn_rtcache *rtc, +++ struct dst_entry *dst, +++ enum ip_conntrack_dir dir, int iif) +++{ +++ if (rtc->cached_dst[dir].iif != iif) +++ rtc->cached_dst[dir].iif = iif; +++ +++ if (rtc->cached_dst[dir].dst != dst) { +++ struct dst_entry *old; +++ +++ dst_hold(dst); +++ +++ old = xchg(&rtc->cached_dst[dir].dst, dst); +++ dst_release(old); +++ +++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) +++ if (pf == NFPROTO_IPV6) +++ rtc->cached_dst[dir].cookie = +++ nf_rtcache_get_cookie(pf, dst); +++#endif +++ } +++} +++ +++static void nf_conn_rtcache_dst_obsolete(struct nf_conn_rtcache *rtc, +++ enum ip_conntrack_dir dir) +++{ +++ struct dst_entry *old; +++ +++ pr_debug("Invalidate iif %d for dir %d on cache %p\n", +++ rtc->cached_dst[dir].iif, dir, rtc); +++ +++ old = xchg(&rtc->cached_dst[dir].dst, NULL); +++ dst_release(old); +++ rtc->cached_dst[dir].iif = -1; +++} +++ +++static unsigned int nf_rtcache_in(u_int8_t pf, +++ struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ struct nf_conn_rtcache *rtc; +++ enum ip_conntrack_info ctinfo; +++ enum ip_conntrack_dir dir; +++ struct dst_entry *dst; +++ struct nf_conn *ct; +++ int iif; +++ u32 cookie; +++ +++ if (skb_dst(skb) || skb->sk) +++ return NF_ACCEPT; +++ +++ ct = nf_ct_get(skb, &ctinfo); +++ if (!ct) +++ return NF_ACCEPT; +++ +++ rtc = nf_ct_rtcache_find_usable(ct); +++ if (!rtc) +++ return NF_ACCEPT; +++ +++ /* if iif changes, don't use cache and let ip stack +++ * do route lookup. +++ * +++ * If rp_filter is enabled it might toss skb, so +++ * we don't want to avoid these checks. +++ */ +++ dir = CTINFO2DIR(ctinfo); +++ iif = nf_conn_rtcache_iif_get(rtc, dir); +++ if (state->in->ifindex != iif) { +++ pr_debug("ct %p, iif %d, cached iif %d, skip cached entry\n", +++ ct, iif, state->in->ifindex); +++ return NF_ACCEPT; +++ } +++ dst = nf_conn_rtcache_dst_get(rtc, dir); +++ if (dst == NULL) +++ return NF_ACCEPT; +++ +++ cookie = nf_rtcache_get_cookie(pf, dst); +++ +++ dst = dst_check(dst, cookie); +++ pr_debug("obtained dst %p for skb %p, cookie %d\n", dst, skb, cookie); +++ if (likely(dst)) +++ skb_dst_set_noref(skb, dst); +++ else +++ nf_conn_rtcache_dst_obsolete(rtc, dir); +++ +++ return NF_ACCEPT; +++} +++ +++static unsigned int nf_rtcache_forward(u_int8_t pf, +++ struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ struct nf_conn_rtcache *rtc; +++ enum ip_conntrack_info ctinfo; +++ enum ip_conntrack_dir dir; +++ struct nf_conn *ct; +++ struct dst_entry *dst = skb_dst(skb); +++ int iif; +++ +++ ct = nf_ct_get(skb, &ctinfo); +++ if (!ct) +++ return NF_ACCEPT; +++ +++ if (dst && dst_xfrm(dst)) +++ return NF_ACCEPT; +++ +++ if (!nf_ct_is_confirmed(ct)) { +++ if (WARN_ON(nf_ct_rtcache_find(ct))) +++ return NF_ACCEPT; +++ nf_ct_rtcache_ext_add(ct); +++ return NF_ACCEPT; +++ } +++ +++ rtc = nf_ct_rtcache_find_usable(ct); +++ if (!rtc) +++ return NF_ACCEPT; +++ +++ dir = CTINFO2DIR(ctinfo); +++ iif = nf_conn_rtcache_iif_get(rtc, dir); +++ pr_debug("ct %p, skb %p, dir %d, iif %d, cached iif %d\n", +++ ct, skb, dir, iif, state->in->ifindex); +++ if (likely(state->in->ifindex == iif)) +++ return NF_ACCEPT; +++ +++ nf_conn_rtcache_dst_set(pf, rtc, skb_dst(skb), dir, state->in->ifindex); +++ return NF_ACCEPT; +++} +++ +++static unsigned int nf_rtcache_in4(void *priv, +++ struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ return nf_rtcache_in(NFPROTO_IPV4, skb, state); +++} +++ +++static unsigned int nf_rtcache_forward4(void *priv, +++ struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ return nf_rtcache_forward(NFPROTO_IPV4, skb, state); +++} +++ +++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) +++static unsigned int nf_rtcache_in6(void *priv, +++ struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ return nf_rtcache_in(NFPROTO_IPV6, skb, state); +++} +++ +++static unsigned int nf_rtcache_forward6(void *priv, +++ struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ return nf_rtcache_forward(NFPROTO_IPV6, skb, state); +++} +++#endif +++ +++static int nf_rtcache_dst_remove(struct nf_conn *ct, void *data) +++{ +++ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct); +++ struct net_device *dev = data; +++ +++ if (!rtc) +++ return 0; +++ +++ if (dev->ifindex == rtc->cached_dst[IP_CT_DIR_ORIGINAL].iif || +++ dev->ifindex == rtc->cached_dst[IP_CT_DIR_REPLY].iif) { +++ nf_conn_rtcache_dst_obsolete(rtc, IP_CT_DIR_ORIGINAL); +++ nf_conn_rtcache_dst_obsolete(rtc, IP_CT_DIR_REPLY); +++ } +++ +++ return 0; +++} +++ +++static int nf_rtcache_netdev_event(struct notifier_block *this, +++ unsigned long event, void *ptr) +++{ +++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); +++ struct net *net = dev_net(dev); +++ +++ if (event == NETDEV_DOWN) +++ nf_ct_iterate_cleanup_net(net, nf_rtcache_dst_remove, dev, 0, 0); +++ +++ return NOTIFY_DONE; +++} +++ +++static struct notifier_block nf_rtcache_notifier = { +++ .notifier_call = nf_rtcache_netdev_event, +++}; +++ +++static struct nf_hook_ops rtcache_ops[] = { +++ { +++ .hook = nf_rtcache_in4, +++ .pf = NFPROTO_IPV4, +++ .hooknum = NF_INET_PRE_ROUTING, +++ .priority = NF_IP_PRI_LAST, +++ }, +++ { +++ .hook = nf_rtcache_forward4, +++ .pf = NFPROTO_IPV4, +++ .hooknum = NF_INET_FORWARD, +++ .priority = NF_IP_PRI_LAST, +++ }, +++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) +++ { +++ .hook = nf_rtcache_in6, +++ .pf = NFPROTO_IPV6, +++ .hooknum = NF_INET_PRE_ROUTING, +++ .priority = NF_IP_PRI_LAST, +++ }, +++ { +++ .hook = nf_rtcache_forward6, +++ .pf = NFPROTO_IPV6, +++ .hooknum = NF_INET_FORWARD, +++ .priority = NF_IP_PRI_LAST, +++ }, +++#endif +++}; +++ +++static struct nf_ct_ext_type rtcache_extend __read_mostly = { +++ .len = sizeof(struct nf_conn_rtcache), +++ .align = __alignof__(struct nf_conn_rtcache), +++ .id = NF_CT_EXT_RTCACHE, +++ .destroy = nf_conn_rtcache_destroy, +++}; +++ +++static int __net_init rtcache_net_init(struct net *net) +++{ +++ return nf_register_net_hooks(net, rtcache_ops, ARRAY_SIZE(rtcache_ops)); +++} +++ +++static void __net_exit rtcache_net_exit(struct net *net) +++{ +++ /* remove hooks so no new connections get rtcache extension */ +++ nf_unregister_net_hooks(net, rtcache_ops, ARRAY_SIZE(rtcache_ops)); +++} +++ +++static struct pernet_operations rtcache_ops_net_ops = { +++ .init = rtcache_net_init, +++ .exit = rtcache_net_exit, +++}; +++ +++static int __init nf_conntrack_rtcache_init(void) +++{ +++ int ret = nf_ct_extend_register(&rtcache_extend); +++ +++ if (ret < 0) { +++ pr_err("nf_conntrack_rtcache: Unable to register extension\n"); +++ return ret; +++ } +++ +++ ret = register_pernet_subsys(&rtcache_ops_net_ops); +++ if (ret) { +++ nf_ct_extend_unregister(&rtcache_extend); +++ return ret; +++ } +++ +++ ret = register_netdevice_notifier(&nf_rtcache_notifier); +++ if (ret) { +++ nf_ct_extend_unregister(&rtcache_extend); +++ unregister_pernet_subsys(&rtcache_ops_net_ops); +++ } +++ +++ return ret; +++} +++ +++static int nf_rtcache_ext_remove(struct nf_conn *ct, void *data) +++{ +++ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct); +++ +++ return rtc != NULL; +++} +++ +++static bool __exit nf_conntrack_rtcache_wait_for_dying(struct net *net) +++{ +++ bool wait = false; +++ int cpu; +++ +++ for_each_possible_cpu(cpu) { +++ struct nf_conntrack_tuple_hash *h; +++ struct hlist_nulls_node *n; +++ struct nf_conn *ct; +++ struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); +++ +++ rcu_read_lock(); +++ spin_lock_bh(&pcpu->lock); +++ +++ hlist_nulls_for_each_entry(h, n, &pcpu->dying, hnnode) { +++ ct = nf_ct_tuplehash_to_ctrack(h); +++ if (nf_ct_rtcache_find(ct) != NULL) { +++ wait = true; +++ break; +++ } +++ } +++ spin_unlock_bh(&pcpu->lock); +++ rcu_read_unlock(); +++ } +++ +++ return wait; +++} +++ +++static void __exit nf_conntrack_rtcache_fini(void) +++{ +++ struct net *net; +++ int count = 0; +++ +++ synchronize_net(); +++ +++ unregister_netdevice_notifier(&nf_rtcache_notifier); +++ unregister_pernet_subsys(&rtcache_ops_net_ops); +++ +++ synchronize_net(); +++ +++ rtnl_lock(); +++ +++ /* zap all conntracks with rtcache extension */ +++ for_each_net(net) +++ nf_ct_iterate_cleanup_net(net, nf_rtcache_ext_remove, NULL, 0, 0); +++ +++ for_each_net(net) { +++ /* .. and make sure they're gone from dying list, too */ +++ while (nf_conntrack_rtcache_wait_for_dying(net)) { +++ msleep(200); +++ WARN_ONCE(++count > 25, "Waiting for all rtcache conntracks to go away\n"); +++ } +++ } +++ +++ rtnl_unlock(); +++ +++ synchronize_net(); +++ nf_ct_extend_unregister(&rtcache_extend); +++} +++module_init(nf_conntrack_rtcache_init); +++module_exit(nf_conntrack_rtcache_fini); +++ +++MODULE_LICENSE("GPL"); +++MODULE_AUTHOR("Florian Westphal "); +++MODULE_DESCRIPTION("Conntrack route cache extension"); +diff --git a/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch b/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch +new file mode 100644 +index 0000000000..4f6f5d2cfa +--- /dev/null ++++ b/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch +@@ -0,0 +1,85 @@ ++From: Eric Dumazet ++Date: Sat, 11 Nov 2017 15:54:12 -0800 ++Subject: [PATCH] tcp: allow drivers to tweak TSQ logic ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++I had many reports that TSQ logic breaks wifi aggregation. ++ ++Current logic is to allow up to 1 ms of bytes to be queued into qdisc ++and drivers queues. ++ ++But Wifi aggregation needs a bigger budget to allow bigger rates to ++be discovered by various TCP Congestion Controls algorithms. ++ ++This patch adds an extra socket field, allowing wifi drivers to select ++another log scale to derive TCP Small Queue credit from current pacing ++rate. ++ ++Initial value is 10, meaning that this patch does not change current ++behavior. ++ ++We expect wifi drivers to set this field to smaller values (tests have ++been done with values from 6 to 9) ++ ++They would have to use following template : ++ ++if (skb->sk && skb->sk->sk_pacing_shift != MY_PACING_SHIFT) ++ skb->sk->sk_pacing_shift = MY_PACING_SHIFT; ++ ++Ref: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1670041 ++Signed-off-by: Eric Dumazet ++Cc: Johannes Berg ++Cc: Toke Høiland-Jørgensen ++Cc: Kir Kolyshkin ++--- ++--- a/include/net/sock.h +++++ b/include/net/sock.h ++@@ -267,6 +267,7 @@ struct sock_common { ++ * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) ++ * @sk_gso_max_size: Maximum GSO segment size to build ++ * @sk_gso_max_segs: Maximum number of GSO segments +++ * @sk_pacing_shift: scaling factor for TCP Small Queues ++ * @sk_lingertime: %SO_LINGER l_linger setting ++ * @sk_backlog: always used with the per-socket spinlock held ++ * @sk_callback_lock: used with the callbacks in the end of this struct ++@@ -446,6 +447,8 @@ struct sock { ++ sk_type : 16; ++ #define SK_PROTOCOL_MAX U8_MAX ++ u16 sk_gso_max_segs; +++#define sk_pacing_shift sk_pacing_shift /* for backport checks */ +++ u8 sk_pacing_shift; ++ unsigned long sk_lingertime; ++ struct proto *sk_prot_creator; ++ rwlock_t sk_callback_lock; ++--- a/net/core/sock.c +++++ b/net/core/sock.c ++@@ -2750,6 +2750,7 @@ void sock_init_data(struct socket *sock, ++ ++ sk->sk_max_pacing_rate = ~0U; ++ sk->sk_pacing_rate = ~0U; +++ sk->sk_pacing_shift = 10; ++ sk->sk_incoming_cpu = -1; ++ /* ++ * Before updating sk_refcnt, we must commit prior changes to memory ++--- a/net/ipv4/tcp_output.c +++++ b/net/ipv4/tcp_output.c ++@@ -1699,7 +1699,7 @@ u32 tcp_tso_autosize(const struct sock * ++ { ++ u32 bytes, segs; ++ ++- bytes = min(sk->sk_pacing_rate >> 10, +++ bytes = min(sk->sk_pacing_rate >> sk->sk_pacing_shift, ++ sk->sk_gso_max_size - 1 - MAX_TCP_HEADER); ++ ++ /* Goal is to send at least one packet per ms, ++@@ -2217,7 +2217,7 @@ static bool tcp_small_queue_check(struct ++ { ++ unsigned int limit; ++ ++- limit = max(2 * skb->truesize, sk->sk_pacing_rate >> 10); +++ limit = max(2 * skb->truesize, sk->sk_pacing_rate >> sk->sk_pacing_shift); ++ limit = min_t(u32, limit, sysctl_tcp_limit_output_bytes); ++ limit <<= factor; ++ +diff --git a/target/linux/generic/backport-4.14/030-USB-serial-option-fix-dwm-158-3g-modem-interface.patch b/target/linux/generic/backport-4.14/030-USB-serial-option-fix-dwm-158-3g-modem-interface.patch +new file mode 100644 +index 0000000000..0e6aa87f9d +--- /dev/null ++++ b/target/linux/generic/backport-4.14/030-USB-serial-option-fix-dwm-158-3g-modem-interface.patch +@@ -0,0 +1,42 @@ ++From 4d304a6fe93538ce356b4593dc43476b50c023e7 Mon Sep 17 00:00:00 2001 ++From: Giuseppe Lippolis ++Date: Mon, 23 Apr 2018 09:03:06 +0200 ++Subject: USB: serial: option: blacklist unused dwm-158 interfaces ++ ++The dwm-158 interface 4 and 5 doesn't answer to the AT commands ++and doesn't appears a option interface. ++Tested on openwrt distribution (kernel 4.14 using the old blacklist ++definitions). ++ ++Lars Melin also writes: ++ ++ Blacklisting interface 4 and 5 is correct because: ++ ++ MI_00 D-Link Mobile Broadband Device (cdc_ether) ++ MI_02 D-Link HSPA+DataCard Diagnostics Interface (also ppp modem) ++ MI_03 D-Link HSPA+DataCard NMEA Device ++ MI_04 D-Link HSPA+DataCard Speech Port ++ MI_05 D-Link HSPA+DataCard Debug Port ++ MI_06 USB Mass Storage Device ++ ++Signed-off-by: Giuseppe Lippolis ++[ johan: add Lars's comment on the interface layout and reword summary ] ++Cc: Lars Melin ++Cc: Dan Williams ++Signed-off-by: Johan Hovold ++--- ++ drivers/usb/serial/option.c | 3 ++- ++ 1 file changed, 2 insertions(+), 1 deletion(-) ++ ++--- a/drivers/usb/serial/option.c +++++ b/drivers/usb/serial/option.c ++@@ -1990,7 +1990,8 @@ static const struct usb_device_id option ++ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d01, 0xff) }, /* D-Link DWM-156 (variant) */ ++ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d02, 0xff) }, ++ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d03, 0xff) }, ++- { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff) }, /* D-Link DWM-158 */ +++ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff), /* D-Link DWM-158 */ +++ .driver_info = RSVD(4) | RSVD(5) }, ++ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d0e, 0xff) }, /* D-Link DWM-157 C1 */ ++ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */ ++ .driver_info = RSVD(4) }, +diff --git a/target/linux/generic/backport-4.14/030-v4.17-0001-usb-dwc2-add-support-for-host-mode-external-vbus-sup.patch b/target/linux/generic/backport-4.14/030-v4.17-0001-usb-dwc2-add-support-for-host-mode-external-vbus-sup.patch +new file mode 100644 +index 0000000000..4d029ebfe2 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/030-v4.17-0001-usb-dwc2-add-support-for-host-mode-external-vbus-sup.patch +@@ -0,0 +1,109 @@ ++From 531ef5ebea96394ddb7f554d4d88e017dde30a59 Mon Sep 17 00:00:00 2001 ++From: Amelie Delaunay ++Date: Tue, 13 Feb 2018 09:28:12 +0100 ++Subject: [PATCH] usb: dwc2: add support for host mode external vbus supply ++ ++This patch adds a way to enable an external vbus supply in host mode, ++when dwc2 drvvbus signal is not used. ++ ++This patch is very similar to the one done in U-Boot dwc2 driver [1]. It ++also adds dynamic vbus supply management depending on the role and state ++of the core. ++ ++[1] https://lists.denx.de/pipermail/u-boot/2017-March/283434.html ++ ++Signed-off-by: Amelie Delaunay ++Signed-off-by: Felipe Balbi ++--- ++ drivers/usb/dwc2/core.h | 2 ++ ++ drivers/usb/dwc2/hcd.c | 26 ++++++++++++++++++++++++++ ++ 2 files changed, 28 insertions(+) ++ ++--- a/drivers/usb/dwc2/core.h +++++ b/drivers/usb/dwc2/core.h ++@@ -777,6 +777,7 @@ struct dwc2_hregs_backup { ++ * @plat: The platform specific configuration data. This can be ++ * removed once all SoCs support usb transceiver. ++ * @supplies: Definition of USB power supplies +++ * @vbus_supply: Regulator supplying vbus. ++ * @phyif: PHY interface width ++ * @lock: Spinlock that protects all the driver data structures ++ * @priv: Stores a pointer to the struct usb_hcd ++@@ -914,6 +915,7 @@ struct dwc2_hsotg { ++ struct usb_phy *uphy; ++ struct dwc2_hsotg_plat *plat; ++ struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES]; +++ struct regulator *vbus_supply; ++ u32 phyif; ++ ++ spinlock_t lock; ++--- a/drivers/usb/dwc2/hcd.c +++++ b/drivers/usb/dwc2/hcd.c ++@@ -359,6 +359,23 @@ static void dwc2_gusbcfg_init(struct dwc ++ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); ++ } ++ +++static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg) +++{ +++ hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); +++ if (IS_ERR(hsotg->vbus_supply)) +++ return 0; +++ +++ return regulator_enable(hsotg->vbus_supply); +++} +++ +++static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg) +++{ +++ if (hsotg->vbus_supply) +++ return regulator_disable(hsotg->vbus_supply); +++ +++ return 0; +++} +++ ++ /** ++ * dwc2_enable_host_interrupts() - Enables the Host mode interrupts ++ * ++@@ -3346,6 +3363,7 @@ static void dwc2_conn_id_status_change(s ++ ++ /* B-Device connector (Device Mode) */ ++ if (gotgctl & GOTGCTL_CONID_B) { +++ dwc2_vbus_supply_exit(hsotg); ++ /* Wait for switch to device mode */ ++ dev_dbg(hsotg->dev, "connId B\n"); ++ if (hsotg->bus_suspended) { ++@@ -4455,6 +4473,9 @@ static int _dwc2_hcd_start(struct usb_hc ++ } ++ ++ spin_unlock_irqrestore(&hsotg->lock, flags); +++ +++ dwc2_vbus_supply_init(hsotg); +++ ++ return 0; ++ } ++ ++@@ -4482,6 +4503,8 @@ static void _dwc2_hcd_stop(struct usb_hc ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ spin_unlock_irqrestore(&hsotg->lock, flags); ++ +++ dwc2_vbus_supply_exit(hsotg); +++ ++ usleep_range(1000, 3000); ++ } ++ ++@@ -4518,6 +4541,7 @@ static int _dwc2_hcd_suspend(struct usb_ ++ hprt0 |= HPRT0_SUSP; ++ hprt0 &= ~HPRT0_PWR; ++ dwc2_writel(hprt0, hsotg->regs + HPRT0); +++ dwc2_vbus_supply_exit(hsotg); ++ } ++ ++ /* Enter hibernation */ ++@@ -4598,6 +4622,8 @@ static int _dwc2_hcd_resume(struct usb_h ++ spin_unlock_irqrestore(&hsotg->lock, flags); ++ dwc2_port_resume(hsotg); ++ } else { +++ dwc2_vbus_supply_init(hsotg); +++ ++ /* Wait for controller to correctly update D+/D- level */ ++ usleep_range(3000, 5000); ++ +diff --git a/target/linux/generic/backport-4.14/030-v4.17-0002-usb-dwc2-dwc2_vbus_supply_init-fix-error-check.patch b/target/linux/generic/backport-4.14/030-v4.17-0002-usb-dwc2-dwc2_vbus_supply_init-fix-error-check.patch +new file mode 100644 +index 0000000000..02b61fe84f +--- /dev/null ++++ b/target/linux/generic/backport-4.14/030-v4.17-0002-usb-dwc2-dwc2_vbus_supply_init-fix-error-check.patch +@@ -0,0 +1,55 @@ ++From 438fea2a6325933868aebc20279e2669c9a21207 Mon Sep 17 00:00:00 2001 ++From: Tomeu Vizoso ++Date: Mon, 26 Mar 2018 11:00:01 +0200 ++Subject: [PATCH] usb: dwc2: dwc2_vbus_supply_init: fix error check ++ ++devm_regulator_get_optional returns -ENODEV if the regulator isn't ++there, so if that's the case we have to make sure not to leave -ENODEV ++in the regulator pointer. ++ ++Also, make sure we return 0 in that case, but correctly propagate any ++other errors. Also propagate the error from _dwc2_hcd_start. ++ ++Fixes: 531ef5ebea96 ("usb: dwc2: add support for host mode external vbus supply") ++Cc: Amelie Delaunay ++Reviewed-by: Amelie Delaunay ++Reviewed-by: Heiko Stuebner ++Reviewed-by: Grigor Tovmasyan ++Tested-by: Heiko Stuebner ++Acked-by: Minas Harutyunyan ++Signed-off-by: Tomeu Vizoso ++Signed-off-by: Felipe Balbi ++--- ++ drivers/usb/dwc2/hcd.c | 13 ++++++++----- ++ 1 file changed, 8 insertions(+), 5 deletions(-) ++ ++--- a/drivers/usb/dwc2/hcd.c +++++ b/drivers/usb/dwc2/hcd.c ++@@ -361,9 +361,14 @@ static void dwc2_gusbcfg_init(struct dwc ++ ++ static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg) ++ { +++ int ret; +++ ++ hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); ++- if (IS_ERR(hsotg->vbus_supply)) ++- return 0; +++ if (IS_ERR(hsotg->vbus_supply)) { +++ ret = PTR_ERR(hsotg->vbus_supply); +++ hsotg->vbus_supply = NULL; +++ return ret == -ENODEV ? 0 : ret; +++ } ++ ++ return regulator_enable(hsotg->vbus_supply); ++ } ++@@ -4474,9 +4479,7 @@ static int _dwc2_hcd_start(struct usb_hc ++ ++ spin_unlock_irqrestore(&hsotg->lock, flags); ++ ++- dwc2_vbus_supply_init(hsotg); ++- ++- return 0; +++ return dwc2_vbus_supply_init(hsotg); ++ } ++ ++ /* +diff --git a/target/linux/generic/backport-4.14/040-v4.17-0001-mtd-move-code-adding-master-MTD-out-of-mtd_add_devic.patch b/target/linux/generic/backport-4.14/040-v4.17-0001-mtd-move-code-adding-master-MTD-out-of-mtd_add_devic.patch +new file mode 100644 +index 0000000000..df6429776f +--- /dev/null ++++ b/target/linux/generic/backport-4.14/040-v4.17-0001-mtd-move-code-adding-master-MTD-out-of-mtd_add_devic.patch +@@ -0,0 +1,74 @@ ++From 2c77c57d22adb05b21cdb333a0c42bdfa0e19835 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Tue, 16 Jan 2018 16:45:41 +0100 ++Subject: [PATCH] mtd: move code adding master MTD out of ++ mtd_add_device_partitions() ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This change is a small cleanup of mtd_device_parse_register(). When ++using MTD_PARTITIONED_MASTER it makes sure a master MTD is registered ++before dealing with partitions. The advantage of this is not mixing ++code handling master MTD with code handling partitions. ++ ++This commit doesn't change any behavior except from a slightly different ++failure code path. The new code may need to call del_mtd_device when ++something goes wrong. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/mtdcore.c | 25 +++++++++++++------------ ++ 1 file changed, 13 insertions(+), 12 deletions(-) ++ ++--- a/drivers/mtd/mtdcore.c +++++ b/drivers/mtd/mtdcore.c ++@@ -641,20 +641,12 @@ static int mtd_add_device_partitions(str ++ { ++ const struct mtd_partition *real_parts = parts->parts; ++ int nbparts = parts->nr_parts; ++- int ret; ++ ++- if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { ++- ret = add_mtd_device(mtd); ++- if (ret) ++- return ret; ++- } +++ if (!nbparts && !device_is_registered(&mtd->dev)) +++ return add_mtd_device(mtd); ++ ++- if (nbparts > 0) { ++- ret = add_mtd_partitions(mtd, real_parts, nbparts); ++- if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) ++- del_mtd_device(mtd); ++- return ret; ++- } +++ if (nbparts > 0) +++ return add_mtd_partitions(mtd, real_parts, nbparts); ++ ++ return 0; ++ } ++@@ -714,6 +706,12 @@ int mtd_device_parse_register(struct mtd ++ ++ mtd_set_dev_defaults(mtd); ++ +++ if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { +++ ret = add_mtd_device(mtd); +++ if (ret) +++ return ret; +++ } +++ ++ memset(&parsed, 0, sizeof(parsed)); ++ ++ ret = parse_mtd_partitions(mtd, types, &parsed, parser_data); ++@@ -753,6 +751,9 @@ int mtd_device_parse_register(struct mtd ++ out: ++ /* Cleanup any parsed partitions */ ++ mtd_part_parser_cleanup(&parsed); +++ if (ret && device_is_registered(&mtd->dev)) +++ del_mtd_device(mtd); +++ ++ return ret; ++ } ++ EXPORT_SYMBOL_GPL(mtd_device_parse_register); +diff --git a/target/linux/generic/backport-4.14/040-v4.17-0002-mtd-get-rid-of-the-mtd_add_device_partitions.patch b/target/linux/generic/backport-4.14/040-v4.17-0002-mtd-get-rid-of-the-mtd_add_device_partitions.patch +new file mode 100644 +index 0000000000..1042e674c3 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/040-v4.17-0002-mtd-get-rid-of-the-mtd_add_device_partitions.patch +@@ -0,0 +1,93 @@ ++From 0dbe4ea78d69756efeb0bba0764f6bd4a9ee9567 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Tue, 16 Jan 2018 16:45:42 +0100 ++Subject: [PATCH] mtd: get rid of the mtd_add_device_partitions() ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This simplifies code a bit by: ++1) Avoiding an extra (tiny) function ++2) Checking for amount of parsed (found) partitions just once ++3) Avoiding clearing/filling struct mtd_partitions manually ++ ++With this commit proper functions are called directly from the ++mtd_device_parse_register(). It doesn't need to use minor tricks like ++memsetting struct to 0 to trigger an expected ++mtd_add_device_partitions() behavior. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/mtdcore.c | 43 ++++++++++++------------------------------- ++ 1 file changed, 12 insertions(+), 31 deletions(-) ++ ++--- a/drivers/mtd/mtdcore.c +++++ b/drivers/mtd/mtdcore.c ++@@ -636,21 +636,6 @@ out_error: ++ return ret; ++ } ++ ++-static int mtd_add_device_partitions(struct mtd_info *mtd, ++- struct mtd_partitions *parts) ++-{ ++- const struct mtd_partition *real_parts = parts->parts; ++- int nbparts = parts->nr_parts; ++- ++- if (!nbparts && !device_is_registered(&mtd->dev)) ++- return add_mtd_device(mtd); ++- ++- if (nbparts > 0) ++- return add_mtd_partitions(mtd, real_parts, nbparts); ++- ++- return 0; ++-} ++- ++ /* ++ * Set a few defaults based on the parent devices, if not provided by the ++ * driver ++@@ -701,7 +686,7 @@ int mtd_device_parse_register(struct mtd ++ const struct mtd_partition *parts, ++ int nr_parts) ++ { ++- struct mtd_partitions parsed; +++ struct mtd_partitions parsed = { }; ++ int ret; ++ ++ mtd_set_dev_defaults(mtd); ++@@ -712,24 +697,20 @@ int mtd_device_parse_register(struct mtd ++ return ret; ++ } ++ ++- memset(&parsed, 0, sizeof(parsed)); ++- +++ /* Prefer parsed partitions over driver-provided fallback */ ++ ret = parse_mtd_partitions(mtd, types, &parsed, parser_data); ++- if ((ret < 0 || parsed.nr_parts == 0) && parts && nr_parts) { ++- /* Fall back to driver-provided partitions */ ++- parsed = (struct mtd_partitions){ ++- .parts = parts, ++- .nr_parts = nr_parts, ++- }; ++- } else if (ret < 0) { ++- /* Didn't come up with parsed OR fallback partitions */ ++- pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n", ++- ret); ++- /* Don't abort on errors; we can still use unpartitioned MTD */ ++- memset(&parsed, 0, sizeof(parsed)); +++ if (!ret && parsed.nr_parts) { +++ parts = parsed.parts; +++ nr_parts = parsed.nr_parts; ++ } ++ ++- ret = mtd_add_device_partitions(mtd, &parsed); +++ if (nr_parts) +++ ret = add_mtd_partitions(mtd, parts, nr_parts); +++ else if (!device_is_registered(&mtd->dev)) +++ ret = add_mtd_device(mtd); +++ else +++ ret = 0; +++ ++ if (ret) ++ goto out; ++ +diff --git a/target/linux/generic/backport-4.14/041-v4.17-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch b/target/linux/generic/backport-4.14/041-v4.17-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch +new file mode 100644 +index 0000000000..765b6b95df +--- /dev/null ++++ b/target/linux/generic/backport-4.14/041-v4.17-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch +@@ -0,0 +1,200 @@ ++From 5b644aa012f67fd211138a067b9f351f30bdcc60 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Wed, 14 Mar 2018 13:10:42 +0100 ++Subject: [PATCH] mtd: partitions: add of_match_table parser matching for the ++ "ofpart" type ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++In order to properly support compatibility strings as described in the ++bindings/mtd/partition.txt "ofpart" type should be treated as an ++indication for looking into OF. MTD should check "compatible" property ++and search for a matching parser rather than blindly trying the one ++supporting "fixed-partitions". ++ ++It also means that existing "fixed-partitions" parser should get renamed ++to use a more meaningful name. ++ ++This commit achievies that aim by introducing a new mtd_part_of_parse(). ++It works by looking for a matching parser for every string in the ++"compatibility" property (starting with the most specific one). ++ ++Please note that driver-specified parsers still take a precedence. It's ++assumed that driver providing a parser type has a good reason for that ++(e.g. having platform data with device-specific info). Also doing ++otherwise could break existing setups. The same applies to using default ++parsers (including "cmdlinepart") as some overwrite DT data with cmdline ++argument. ++ ++Partition parsers can now provide an of_match_table to enable ++flash<-->parser matching via device tree as documented in the ++mtd/partition.txt. ++ ++This support is currently limited to built-in parsers as it uses ++request_module() and friends. This should be sufficient for most cases ++though as compiling parsers as modules isn't a common choice. ++ ++Signed-off-by: Brian Norris ++Signed-off-by: Rafał Miłecki ++Tested-by: Peter Rosin ++Reviewed-by: Richard Weinberger ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/mtdpart.c | 116 +++++++++++++++++++++++++++++++++++++---- ++ include/linux/mtd/partitions.h | 1 + ++ 2 files changed, 108 insertions(+), 9 deletions(-) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -30,6 +30,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "mtdcore.h" ++ ++@@ -919,6 +920,92 @@ static int mtd_part_do_parse(struct mtd_ ++ } ++ ++ /** +++ * mtd_part_get_compatible_parser - find MTD parser by a compatible string +++ * +++ * @compat: compatible string describing partitions in a device tree +++ * +++ * MTD parsers can specify supported partitions by providing a table of +++ * compatibility strings. This function finds a parser that advertises support +++ * for a passed value of "compatible". +++ */ +++static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat) +++{ +++ struct mtd_part_parser *p, *ret = NULL; +++ +++ spin_lock(&part_parser_lock); +++ +++ list_for_each_entry(p, &part_parsers, list) { +++ const struct of_device_id *matches; +++ +++ matches = p->of_match_table; +++ if (!matches) +++ continue; +++ +++ for (; matches->compatible[0]; matches++) { +++ if (!strcmp(matches->compatible, compat) && +++ try_module_get(p->owner)) { +++ ret = p; +++ break; +++ } +++ } +++ +++ if (ret) +++ break; +++ } +++ +++ spin_unlock(&part_parser_lock); +++ +++ return ret; +++} +++ +++static int mtd_part_of_parse(struct mtd_info *master, +++ struct mtd_partitions *pparts) +++{ +++ struct mtd_part_parser *parser; +++ struct device_node *np; +++ struct property *prop; +++ const char *compat; +++ const char *fixed = "ofpart"; +++ int ret, err = 0; +++ +++ np = of_get_child_by_name(mtd_get_of_node(master), "partitions"); +++ of_property_for_each_string(np, "compatible", prop, compat) { +++ parser = mtd_part_get_compatible_parser(compat); +++ if (!parser) +++ continue; +++ ret = mtd_part_do_parse(parser, master, pparts, NULL); +++ if (ret > 0) { +++ of_node_put(np); +++ return ret; +++ } +++ mtd_part_parser_put(parser); +++ if (ret < 0 && !err) +++ err = ret; +++ } +++ of_node_put(np); +++ +++ /* +++ * For backward compatibility we have to try the "ofpart" +++ * parser. It supports old DT format with partitions specified as a +++ * direct subnodes of a flash device DT node without any compatibility +++ * specified we could match. +++ */ +++ parser = mtd_part_parser_get(fixed); +++ if (!parser && !request_module("%s", fixed)) +++ parser = mtd_part_parser_get(fixed); +++ if (parser) { +++ ret = mtd_part_do_parse(parser, master, pparts, NULL); +++ if (ret > 0) +++ return ret; +++ mtd_part_parser_put(parser); +++ if (ret < 0 && !err) +++ err = ret; +++ } +++ +++ return err; +++} +++ +++/** ++ * parse_mtd_partitions - parse MTD partitions ++ * @master: the master partition (describes whole MTD device) ++ * @types: names of partition parsers to try or %NULL ++@@ -950,19 +1037,30 @@ int parse_mtd_partitions(struct mtd_info ++ types = default_mtd_part_types; ++ ++ for ( ; *types; types++) { ++- pr_debug("%s: parsing partitions %s\n", master->name, *types); ++- parser = mtd_part_parser_get(*types); ++- if (!parser && !request_module("%s", *types)) +++ /* +++ * ofpart is a special type that means OF partitioning info +++ * should be used. It requires a bit different logic so it is +++ * handled in a separated function. +++ */ +++ if (!strcmp(*types, "ofpart")) { +++ ret = mtd_part_of_parse(master, pparts); +++ } else { +++ pr_debug("%s: parsing partitions %s\n", master->name, +++ *types); ++ parser = mtd_part_parser_get(*types); ++- pr_debug("%s: got parser %s\n", master->name, ++- parser ? parser->name : NULL); ++- if (!parser) ++- continue; ++- ret = mtd_part_do_parse(parser, master, pparts, data); +++ if (!parser && !request_module("%s", *types)) +++ parser = mtd_part_parser_get(*types); +++ pr_debug("%s: got parser %s\n", master->name, +++ parser ? parser->name : NULL); +++ if (!parser) +++ continue; +++ ret = mtd_part_do_parse(parser, master, pparts, data); +++ if (ret <= 0) +++ mtd_part_parser_put(parser); +++ } ++ /* Found partitions! */ ++ if (ret > 0) ++ return 0; ++- mtd_part_parser_put(parser); ++ /* ++ * Stash the first error we see; only report it if no parser ++ * succeeds ++--- a/include/linux/mtd/partitions.h +++++ b/include/linux/mtd/partitions.h ++@@ -77,6 +77,7 @@ struct mtd_part_parser { ++ struct list_head list; ++ struct module *owner; ++ const char *name; +++ const struct of_device_id *of_match_table; ++ int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, ++ struct mtd_part_parser_data *); ++ void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); +diff --git a/target/linux/generic/backport-4.14/041-v4.17-0002-mtd-rename-ofpart-parser-to-fixed-partitions-as-it-f.patch b/target/linux/generic/backport-4.14/041-v4.17-0002-mtd-rename-ofpart-parser-to-fixed-partitions-as-it-f.patch +new file mode 100644 +index 0000000000..22ad40bf44 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/041-v4.17-0002-mtd-rename-ofpart-parser-to-fixed-partitions-as-it-f.patch +@@ -0,0 +1,74 @@ ++From c0faf43482e7f7dfb6d61847cb93d17748560b24 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Wed, 14 Mar 2018 13:10:43 +0100 ++Subject: [PATCH] mtd: rename "ofpart" parser to "fixed-partitions" as it fits ++ it better ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Type "ofpart" means that OF should be used to get partitioning info and ++this driver supports "fixed-partitions" binding only. Renaming it should ++lead to less confusion especially when parsers for new compatibility ++strings start to appear. ++ ++Signed-off-by: Rafał Miłecki ++Reviewed-by: Richard Weinberger ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/mtdpart.c | 4 ++-- ++ drivers/mtd/ofpart.c | 11 ++++++----- ++ 2 files changed, 8 insertions(+), 7 deletions(-) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -965,7 +965,7 @@ static int mtd_part_of_parse(struct mtd_ ++ struct device_node *np; ++ struct property *prop; ++ const char *compat; ++- const char *fixed = "ofpart"; +++ const char *fixed = "fixed-partitions"; ++ int ret, err = 0; ++ ++ np = of_get_child_by_name(mtd_get_of_node(master), "partitions"); ++@@ -985,7 +985,7 @@ static int mtd_part_of_parse(struct mtd_ ++ of_node_put(np); ++ ++ /* ++- * For backward compatibility we have to try the "ofpart" +++ * For backward compatibility we have to try the "fixed-partitions" ++ * parser. It supports old DT format with partitions specified as a ++ * direct subnodes of a flash device DT node without any compatibility ++ * specified we could match. ++--- a/drivers/mtd/ofpart.c +++++ b/drivers/mtd/ofpart.c ++@@ -25,9 +25,9 @@ static bool node_has_compatible(struct d ++ return of_get_property(pp, "compatible", NULL); ++ } ++ ++-static int parse_ofpart_partitions(struct mtd_info *master, ++- const struct mtd_partition **pparts, ++- struct mtd_part_parser_data *data) +++static int parse_fixed_partitions(struct mtd_info *master, +++ const struct mtd_partition **pparts, +++ struct mtd_part_parser_data *data) ++ { ++ struct mtd_partition *parts; ++ struct device_node *mtd_node; ++@@ -141,8 +141,8 @@ ofpart_none: ++ } ++ ++ static struct mtd_part_parser ofpart_parser = { ++- .parse_fn = parse_ofpart_partitions, ++- .name = "ofpart", +++ .parse_fn = parse_fixed_partitions, +++ .name = "fixed-partitions", ++ }; ++ ++ static int parse_ofoldpart_partitions(struct mtd_info *master, ++@@ -229,4 +229,5 @@ MODULE_AUTHOR("Vitaly Wool, David Gibson ++ * with the same name. Since we provide the ofoldpart parser, we should have ++ * the corresponding alias. ++ */ +++MODULE_ALIAS("fixed-partitions"); ++ MODULE_ALIAS("ofoldpart"); +diff --git a/target/linux/generic/backport-4.14/041-v4.17-0003-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch b/target/linux/generic/backport-4.14/041-v4.17-0003-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch +new file mode 100644 +index 0000000000..d6958c3eac +--- /dev/null ++++ b/target/linux/generic/backport-4.14/041-v4.17-0003-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch +@@ -0,0 +1,44 @@ ++From 97b0c7c0df3efd7048ed39d7e2dee34cafd55887 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Wed, 14 Mar 2018 13:10:44 +0100 ++Subject: [PATCH] mtd: ofpart: add of_match_table with "fixed-partitions" ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This allows using this parser with any flash driver that takes care of ++setting of_node (using mtd_set_of_node helper) correctly. Up to now ++support for "fixed-partitions" DT compatibility string was working only ++with flash drivers that were specifying "ofpart" (manually or by letting ++mtd use the default set of parsers). ++ ++This matches existing bindings documentation. ++ ++Signed-off-by: Rafał Miłecki ++Reviewed-by: Brian Norris ++Tested-by: Brian Norris ++Reviewed-by: Richard Weinberger ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/ofpart.c | 7 +++++++ ++ 1 file changed, 7 insertions(+) ++ ++--- a/drivers/mtd/ofpart.c +++++ b/drivers/mtd/ofpart.c ++@@ -140,9 +140,16 @@ ofpart_none: ++ return ret; ++ } ++ +++static const struct of_device_id parse_ofpart_match_table[] = { +++ { .compatible = "fixed-partitions" }, +++ {}, +++}; +++MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); +++ ++ static struct mtd_part_parser ofpart_parser = { ++ .parse_fn = parse_fixed_partitions, ++ .name = "fixed-partitions", +++ .of_match_table = parse_ofpart_match_table, ++ }; ++ ++ static int parse_ofoldpart_partitions(struct mtd_info *master, +diff --git a/target/linux/generic/backport-4.14/042-v4.18-0001-mtd-move-code-adding-registering-partitions-to-the-p.patch b/target/linux/generic/backport-4.14/042-v4.18-0001-mtd-move-code-adding-registering-partitions-to-the-p.patch +new file mode 100644 +index 0000000000..d017fd452b +--- /dev/null ++++ b/target/linux/generic/backport-4.14/042-v4.18-0001-mtd-move-code-adding-registering-partitions-to-the-p.patch +@@ -0,0 +1,168 @@ ++From 5ac67ce36cfe38b4c104a42ce52c5c8d526f1c95 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Tue, 27 Mar 2018 22:35:41 +0200 ++Subject: [PATCH] mtd: move code adding (registering) partitions to the ++ parse_mtd_partitions() ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This commit slightly simplifies the code. Every parse_mtd_partitions() ++caller (out of two existing ones) had to add partitions & cleanup parser ++on its own. This moves that responsibility into the function. ++ ++That change also allows dropping struct mtd_partitions argument. ++ ++There is one minor behavior change caused by this cleanup. If ++parse_mtd_partitions() fails to add partitions (add_mtd_partitions() ++return an error) then mtd_device_parse_register() will still try to ++add (register) fallback partitions. It's a real corner case affecting ++one of uncommon error paths and shouldn't cause any harm. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/mtdcore.c | 14 ++++---------- ++ drivers/mtd/mtdcore.h | 1 - ++ drivers/mtd/mtdpart.c | 44 ++++++++++++++++---------------------------- ++ 3 files changed, 20 insertions(+), 39 deletions(-) ++ ++--- a/drivers/mtd/mtdcore.c +++++ b/drivers/mtd/mtdcore.c ++@@ -686,7 +686,6 @@ int mtd_device_parse_register(struct mtd ++ const struct mtd_partition *parts, ++ int nr_parts) ++ { ++- struct mtd_partitions parsed = { }; ++ int ret; ++ ++ mtd_set_dev_defaults(mtd); ++@@ -698,13 +697,10 @@ int mtd_device_parse_register(struct mtd ++ } ++ ++ /* Prefer parsed partitions over driver-provided fallback */ ++- ret = parse_mtd_partitions(mtd, types, &parsed, parser_data); ++- if (!ret && parsed.nr_parts) { ++- parts = parsed.parts; ++- nr_parts = parsed.nr_parts; ++- } ++- ++- if (nr_parts) +++ ret = parse_mtd_partitions(mtd, types, parser_data); +++ if (ret > 0) +++ ret = 0; +++ else if (nr_parts) ++ ret = add_mtd_partitions(mtd, parts, nr_parts); ++ else if (!device_is_registered(&mtd->dev)) ++ ret = add_mtd_device(mtd); ++@@ -730,8 +726,6 @@ int mtd_device_parse_register(struct mtd ++ } ++ ++ out: ++- /* Cleanup any parsed partitions */ ++- mtd_part_parser_cleanup(&parsed); ++ if (ret && device_is_registered(&mtd->dev)) ++ del_mtd_device(mtd); ++ ++--- a/drivers/mtd/mtdcore.h +++++ b/drivers/mtd/mtdcore.h ++@@ -15,7 +15,6 @@ int del_mtd_partitions(struct mtd_info * ++ struct mtd_partitions; ++ ++ int parse_mtd_partitions(struct mtd_info *master, const char * const *types, ++- struct mtd_partitions *pparts, ++ struct mtd_part_parser_data *data); ++ ++ void mtd_part_parser_cleanup(struct mtd_partitions *parts); ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -383,20 +383,7 @@ static inline void free_partition(struct ++ */ ++ static int mtd_parse_part(struct mtd_part *slave, const char *const *types) ++ { ++- struct mtd_partitions parsed; ++- int err; ++- ++- err = parse_mtd_partitions(&slave->mtd, types, &parsed, NULL); ++- if (err) ++- return err; ++- else if (!parsed.nr_parts) ++- return -ENOENT; ++- ++- err = add_mtd_partitions(&slave->mtd, parsed.parts, parsed.nr_parts); ++- ++- mtd_part_parser_cleanup(&parsed); ++- ++- return err; +++ return parse_mtd_partitions(&slave->mtd, types, NULL); ++ } ++ ++ static struct mtd_part *allocate_partition(struct mtd_info *parent, ++@@ -1006,30 +993,27 @@ static int mtd_part_of_parse(struct mtd_ ++ } ++ ++ /** ++- * parse_mtd_partitions - parse MTD partitions +++ * parse_mtd_partitions - parse and register MTD partitions +++ * ++ * @master: the master partition (describes whole MTD device) ++ * @types: names of partition parsers to try or %NULL ++- * @pparts: info about partitions found is returned here ++ * @data: MTD partition parser-specific data ++ * ++- * This function tries to find partition on MTD device @master. It uses MTD ++- * partition parsers, specified in @types. However, if @types is %NULL, then ++- * the default list of parsers is used. The default list contains only the +++ * This function tries to find & register partitions on MTD device @master. It +++ * uses MTD partition parsers, specified in @types. However, if @types is %NULL, +++ * then the default list of parsers is used. The default list contains only the ++ * "cmdlinepart" and "ofpart" parsers ATM. ++ * Note: If there are more then one parser in @types, the kernel only takes the ++ * partitions parsed out by the first parser. ++ * ++ * This function may return: ++ * o a negative error code in case of failure ++- * o zero otherwise, and @pparts will describe the partitions, number of ++- * partitions, and the parser which parsed them. Caller must release ++- * resources with mtd_part_parser_cleanup() when finished with the returned ++- * data. +++ * o number of found partitions otherwise ++ */ ++ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, ++- struct mtd_partitions *pparts, ++ struct mtd_part_parser_data *data) ++ { +++ struct mtd_partitions pparts = { }; ++ struct mtd_part_parser *parser; ++ int ret, err = 0; ++ ++@@ -1043,7 +1027,7 @@ int parse_mtd_partitions(struct mtd_info ++ * handled in a separated function. ++ */ ++ if (!strcmp(*types, "ofpart")) { ++- ret = mtd_part_of_parse(master, pparts); +++ ret = mtd_part_of_parse(master, &pparts); ++ } else { ++ pr_debug("%s: parsing partitions %s\n", master->name, ++ *types); ++@@ -1054,13 +1038,17 @@ int parse_mtd_partitions(struct mtd_info ++ parser ? parser->name : NULL); ++ if (!parser) ++ continue; ++- ret = mtd_part_do_parse(parser, master, pparts, data); +++ ret = mtd_part_do_parse(parser, master, &pparts, data); ++ if (ret <= 0) ++ mtd_part_parser_put(parser); ++ } ++ /* Found partitions! */ ++- if (ret > 0) ++- return 0; +++ if (ret > 0) { +++ err = add_mtd_partitions(master, pparts.parts, +++ pparts.nr_parts); +++ mtd_part_parser_cleanup(&pparts); +++ return err ? err : pparts.nr_parts; +++ } ++ /* ++ * Stash the first error we see; only report it if no parser ++ * succeeds +diff --git a/target/linux/generic/backport-4.14/043-v4.18-mtd-bcm47xxpart-improve-handling-TRX-partition-size.patch b/target/linux/generic/backport-4.14/043-v4.18-mtd-bcm47xxpart-improve-handling-TRX-partition-size.patch +new file mode 100644 +index 0000000000..e08f8dad32 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/043-v4.18-mtd-bcm47xxpart-improve-handling-TRX-partition-size.patch +@@ -0,0 +1,70 @@ ++From 237ea0d4762cc14d0fc80e80d61f0f08e1050c7f Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Thu, 12 Apr 2018 07:24:52 +0200 ++Subject: [PATCH] mtd: bcm47xxpart: improve handling TRX partition size ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++When bcm47xxpart finds a TRX partition (container) it's supposed to jump ++to the end of it and keep looking for more partitions. TRX and its ++subpartitions are handled by a separate parser. ++ ++The problem with old code was relying on the length specified in a TRX ++header. That isn't reliable as TRX is commonly modified to have checksum ++cover only non-changing subpartitions. Otherwise modifying e.g. a rootfs ++would result in CRC32 mismatch and bootloader refusing to boot a ++firmware. ++ ++Fix it by trying better to figure out a real TRX size. We can securely ++assume that TRX has to cover all subpartitions and the last one is at ++least of a block size in size. Then compare it with a length field. ++ ++This makes code more optimal & reliable thanks to skipping data that ++shouldn't be parsed. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/bcm47xxpart.c | 22 ++++++++++++++++++---- ++ 1 file changed, 18 insertions(+), 4 deletions(-) ++ ++--- a/drivers/mtd/bcm47xxpart.c +++++ b/drivers/mtd/bcm47xxpart.c ++@@ -186,6 +186,8 @@ static int bcm47xxpart_parse(struct mtd_ ++ /* TRX */ ++ if (buf[0x000 / 4] == TRX_MAGIC) { ++ struct trx_header *trx; +++ uint32_t last_subpart; +++ uint32_t trx_size; ++ ++ if (trx_num >= ARRAY_SIZE(trx_parts)) ++ pr_warn("No enough space to store another TRX found at 0x%X\n", ++@@ -195,11 +197,23 @@ static int bcm47xxpart_parse(struct mtd_ ++ bcm47xxpart_add_part(&parts[curr_part++], "firmware", ++ offset, 0); ++ ++- /* Jump to the end of TRX */ +++ /* +++ * Try to find TRX size. The "length" field isn't fully +++ * reliable as it could be decreased to make CRC32 cover +++ * only part of TRX data. It's commonly used as checksum +++ * can't cover e.g. ever-changing rootfs partition. +++ * Use offsets as helpers for assuming min TRX size. +++ */ ++ trx = (struct trx_header *)buf; ++- offset = roundup(offset + trx->length, blocksize); ++- /* Next loop iteration will increase the offset */ ++- offset -= blocksize; +++ last_subpart = max3(trx->offset[0], trx->offset[1], +++ trx->offset[2]); +++ trx_size = max(trx->length, last_subpart + blocksize); +++ +++ /* +++ * Skip the TRX data. Decrease offset by block size as +++ * the next loop iteration will increase it. +++ */ +++ offset += roundup(trx_size, blocksize) - blocksize; ++ continue; ++ } ++ +diff --git a/target/linux/generic/backport-4.14/044-v4.18-mtd-bcm47xxpart-add-of_match_table-with-a-new-DT-bin.patch b/target/linux/generic/backport-4.14/044-v4.18-mtd-bcm47xxpart-add-of_match_table-with-a-new-DT-bin.patch +new file mode 100644 +index 0000000000..de0ff1f818 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/044-v4.18-mtd-bcm47xxpart-add-of_match_table-with-a-new-DT-bin.patch +@@ -0,0 +1,39 @@ ++From cf589ce71e84d3b8811c65740645af254c5248c0 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Wed, 9 May 2018 10:17:29 +0200 ++Subject: [PATCH] mtd: bcm47xxpart: add of_match_table with a new DT binding ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This allows using bcm47xxpart parser to find partitions on flash ++described in DT using the "brcm,bcm947xx-cfe-partitions" compatible ++property. It means this parser doesn't have to be explicitly selected by ++a flash driver anymore. It can be used e.g. together with a generic ++m25p80 / spi-nor if device is just properly described. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/bcm47xxpart.c | 7 +++++++ ++ 1 file changed, 7 insertions(+) ++ ++--- a/drivers/mtd/bcm47xxpart.c +++++ b/drivers/mtd/bcm47xxpart.c ++@@ -304,9 +304,16 @@ static int bcm47xxpart_parse(struct mtd_ ++ return curr_part; ++ }; ++ +++static const struct of_device_id bcm47xxpart_of_match_table[] = { +++ { .compatible = "brcm,bcm947xx-cfe-partitions" }, +++ {}, +++}; +++MODULE_DEVICE_TABLE(of, bcm47xxpart_of_match_table); +++ ++ static struct mtd_part_parser bcm47xxpart_mtd_parser = { ++ .parse_fn = bcm47xxpart_parse, ++ .name = "bcm47xxpart", +++ .of_match_table = bcm47xxpart_of_match_table, ++ }; ++ module_mtd_part_parser(bcm47xxpart_mtd_parser); ++ +diff --git a/target/linux/generic/backport-4.14/045-v4.19-mtd-parsers-trx-add-of_match_table-with-the-new-DT-b.patch b/target/linux/generic/backport-4.14/045-v4.19-mtd-parsers-trx-add-of_match_table-with-the-new-DT-b.patch +new file mode 100644 +index 0000000000..5841dd55f3 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/045-v4.19-mtd-parsers-trx-add-of_match_table-with-the-new-DT-b.patch +@@ -0,0 +1,37 @@ ++From 98534a58c8a40cdc9e3bcb04d74719fbcedfeb52 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Tue, 26 Jun 2018 00:05:08 +0200 ++Subject: [PATCH] mtd: parsers: trx: add of_match_table with the new DT binding ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This allows using TRX parser to find TRX partitions on flash device ++described in DT using a proper binding. It's useful for devices storing ++firmware on a separated flash and having rootfs partition in it. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/parsers/parser_trx.c | 7 +++++++ ++ 1 file changed, 7 insertions(+) ++ ++--- a/drivers/mtd/parsers/parser_trx.c +++++ b/drivers/mtd/parsers/parser_trx.c ++@@ -116,9 +116,16 @@ static int parser_trx_parse(struct mtd_i ++ return i; ++ }; ++ +++static const struct of_device_id mtd_parser_trx_of_match_table[] = { +++ { .compatible = "brcm,trx" }, +++ {}, +++}; +++MODULE_DEVICE_TABLE(of, mtd_parser_trx_of_match_table); +++ ++ static struct mtd_part_parser mtd_parser_trx = { ++ .parse_fn = parser_trx_parse, ++ .name = "trx", +++ .of_match_table = mtd_parser_trx_of_match_table, ++ }; ++ module_mtd_part_parser(mtd_parser_trx); ++ +diff --git a/target/linux/generic/backport-4.14/046-v4.19-mtd-partitions-use-DT-info-for-parsing-partitions-wi.patch b/target/linux/generic/backport-4.14/046-v4.19-mtd-partitions-use-DT-info-for-parsing-partitions-wi.patch +new file mode 100644 +index 0000000000..eff1a01692 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/046-v4.19-mtd-partitions-use-DT-info-for-parsing-partitions-wi.patch +@@ -0,0 +1,102 @@ ++From 76a832254ab05502c9394cc51ded6f0abe0e0bee Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Fri, 13 Jul 2018 16:32:21 +0200 ++Subject: [PATCH] mtd: partitions: use DT info for parsing partitions with ++ "compatible" prop ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++So far only flash devices could be described in DT regarding partitions ++parsing. That could be done with "partitions" subnode and a proper ++"compatible" string. ++ ++Some devices may use hierarchical (multi-level) layouts and may mix used ++layouts (fixed and dynamic). Describing that in DT is done by specifying ++"compatible" for DT-represented partition plus optionally more ++properties and/or subnodes. ++ ++To support such layouts each DT partition has to be checked for ++additional description. ++ ++Please note this implementation will work in parallel with support for ++partition type specified for non-DT setups. That already works since ++commit 1a0915be1926 ("mtd: partitions: add support for partition ++parsers"). ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/mtdpart.c | 33 +++++++++++++-------------------- ++ 1 file changed, 13 insertions(+), 20 deletions(-) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -370,22 +370,6 @@ static inline void free_partition(struct ++ kfree(p); ++ } ++ ++-/** ++- * mtd_parse_part - parse MTD partition looking for subpartitions ++- * ++- * @slave: part that is supposed to be a container and should be parsed ++- * @types: NULL-terminated array with names of partition parsers to try ++- * ++- * Some partitions are kind of containers with extra subpartitions (volumes). ++- * There can be various formats of such containers. This function tries to use ++- * specified parsers to analyze given partition and registers found ++- * subpartitions on success. ++- */ ++-static int mtd_parse_part(struct mtd_part *slave, const char *const *types) ++-{ ++- return parse_mtd_partitions(&slave->mtd, types, NULL); ++-} ++- ++ static struct mtd_part *allocate_partition(struct mtd_info *parent, ++ const struct mtd_partition *part, int partno, ++ uint64_t cur_offset) ++@@ -803,8 +787,8 @@ int add_mtd_partitions(struct mtd_info * ++ } ++ ++ mtd_add_partition_attrs(slave); ++- if (parts[i].types) ++- mtd_parse_part(slave, parts[i].types); +++ /* Look for subpartitions */ +++ parse_mtd_partitions(&slave->mtd, parts[i].types, NULL); ++ ++ cur_offset = slave->offset + slave->mtd.size; ++ } ++@@ -885,6 +869,12 @@ static const char * const default_mtd_pa ++ NULL ++ }; ++ +++/* Check DT only when looking for subpartitions. */ +++static const char * const default_subpartition_types[] = { +++ "ofpart", +++ NULL +++}; +++ ++ static int mtd_part_do_parse(struct mtd_part_parser *parser, ++ struct mtd_info *master, ++ struct mtd_partitions *pparts, ++@@ -955,7 +945,9 @@ static int mtd_part_of_parse(struct mtd_ ++ const char *fixed = "fixed-partitions"; ++ int ret, err = 0; ++ ++- np = of_get_child_by_name(mtd_get_of_node(master), "partitions"); +++ np = mtd_get_of_node(master); +++ if (!mtd_is_partition(master)) +++ np = of_get_child_by_name(np, "partitions"); ++ of_property_for_each_string(np, "compatible", prop, compat) { ++ parser = mtd_part_get_compatible_parser(compat); ++ if (!parser) ++@@ -1018,7 +1010,8 @@ int parse_mtd_partitions(struct mtd_info ++ int ret, err = 0; ++ ++ if (!types) ++- types = default_mtd_part_types; +++ types = mtd_is_partition(master) ? default_subpartition_types : +++ default_mtd_part_types; ++ ++ for ( ; *types; types++) { ++ /* +diff --git a/target/linux/generic/backport-4.14/047-v4.21-mtd-keep-original-flags-for-every-struct-mtd_info.patch b/target/linux/generic/backport-4.14/047-v4.21-mtd-keep-original-flags-for-every-struct-mtd_info.patch +new file mode 100644 +index 0000000000..7f90cf946a +--- /dev/null ++++ b/target/linux/generic/backport-4.14/047-v4.21-mtd-keep-original-flags-for-every-struct-mtd_info.patch +@@ -0,0 +1,58 @@ ++From 1186af457cc186c5ed01708da71b1ffbdf0a2638 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Tue, 20 Nov 2018 09:55:45 +0100 ++Subject: [PATCH] mtd: keep original flags for every struct mtd_info ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++When allocating a new partition mtd subsystem runs internal tests in the ++allocate_partition(). They may result in modifying specified flags (e.g. ++dropping some /features/ like write access). ++ ++Those constraints don't have to be necessary true for subpartitions. It ++may happen parent partition isn't block aligned (effectively disabling ++write access) while subpartition may fit blocks nicely. In such case all ++checks should be run again (starting with original flags value). ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/mtdcore.c | 2 ++ ++ drivers/mtd/mtdpart.c | 3 ++- ++ include/linux/mtd/mtd.h | 1 + ++ 3 files changed, 5 insertions(+), 1 deletion(-) ++ ++--- a/drivers/mtd/mtdcore.c +++++ b/drivers/mtd/mtdcore.c ++@@ -650,6 +650,8 @@ static void mtd_set_dev_defaults(struct ++ } else { ++ pr_debug("mtd device won't show a device symlink in sysfs\n"); ++ } +++ +++ mtd->orig_flags = mtd->flags; ++ } ++ ++ /** ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -394,7 +394,8 @@ static struct mtd_part *allocate_partiti ++ ++ /* set up the MTD object for this partition */ ++ slave->mtd.type = parent->type; ++- slave->mtd.flags = parent->flags & ~part->mask_flags; +++ slave->mtd.flags = parent->orig_flags & ~part->mask_flags; +++ slave->mtd.orig_flags = slave->mtd.flags; ++ slave->mtd.size = part->size; ++ slave->mtd.writesize = parent->writesize; ++ slave->mtd.writebufsize = parent->writebufsize; ++--- a/include/linux/mtd/mtd.h +++++ b/include/linux/mtd/mtd.h ++@@ -218,6 +218,7 @@ struct mtd_debug_info { ++ struct mtd_info { ++ u_char type; ++ uint32_t flags; +++ uint32_t orig_flags; /* Flags as before running mtd checks */ ++ uint64_t size; // Total size of the MTD ++ ++ /* "Major" erase size for the device. Naïve users may take this +diff --git a/target/linux/generic/backport-4.14/048-v4.21-mtd-improve-calculating-partition-boundaries-when-ch.patch b/target/linux/generic/backport-4.14/048-v4.21-mtd-improve-calculating-partition-boundaries-when-ch.patch +new file mode 100644 +index 0000000000..58163e6935 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/048-v4.21-mtd-improve-calculating-partition-boundaries-when-ch.patch +@@ -0,0 +1,55 @@ ++From 6750f61a13a0197c40e4a40739117493b15f19e8 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Tue, 20 Nov 2018 10:24:09 +0100 ++Subject: [PATCH] mtd: improve calculating partition boundaries when checking ++ for alignment ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++When checking for alignment mtd should check absolute offsets. It's ++important for subpartitions as it doesn't make sense to check their ++relative addresses. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Boris Brezillon ++--- ++ drivers/mtd/mtdpart.c | 13 +++++++++++-- ++ 1 file changed, 11 insertions(+), 2 deletions(-) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -61,6 +61,15 @@ static inline struct mtd_part *mtd_to_pa ++ return container_of(mtd, struct mtd_part, mtd); ++ } ++ +++static u64 part_absolute_offset(struct mtd_info *mtd) +++{ +++ struct mtd_part *part = mtd_to_part(mtd); +++ +++ if (!mtd_is_partition(mtd)) +++ return 0; +++ +++ return part_absolute_offset(part->parent) + part->offset; +++} ++ ++ /* ++ * MTD methods which simply translate the effective address and pass through ++@@ -562,7 +571,7 @@ static struct mtd_part *allocate_partiti ++ if (!(slave->mtd.flags & MTD_NO_ERASE)) ++ wr_alignment = slave->mtd.erasesize; ++ ++- tmp = slave->offset; +++ tmp = part_absolute_offset(parent) + slave->offset; ++ remainder = do_div(tmp, wr_alignment); ++ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { ++ /* Doesn't start on a boundary of major erase size */ ++@@ -573,7 +582,7 @@ static struct mtd_part *allocate_partiti ++ part->name); ++ } ++ ++- tmp = slave->mtd.size; +++ tmp = part_absolute_offset(parent) + slave->mtd.size; ++ remainder = do_div(tmp, wr_alignment); ++ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { ++ slave->mtd.flags &= ~MTD_WRITEABLE; +diff --git a/target/linux/generic/backport-4.14/050-v4.19-f2fs-skip-verifying-block-address-non-regular-inode.patch b/target/linux/generic/backport-4.14/050-v4.19-f2fs-skip-verifying-block-address-non-regular-inode.patch +new file mode 100644 +index 0000000000..65ab16a97a +--- /dev/null ++++ b/target/linux/generic/backport-4.14/050-v4.19-f2fs-skip-verifying-block-address-non-regular-inode.patch +@@ -0,0 +1,69 @@ ++From dda9f4b9cac6bdd2a96253b4444d7a6ce5132edb Mon Sep 17 00:00:00 2001 ++From: Chao Yu ++Date: Sat, 11 Aug 2018 23:42:09 +0800 ++Subject: f2fs: fix to skip verifying block address for non-regular inode ++ ++generic/184 1s ... [failed, exit status 1]- output mismatch ++ --- tests/generic/184.out 2015-01-11 16:52:27.643681072 +0800 ++ QA output created by 184 - silence is golden ++ +rm: cannot remove '/mnt/f2fs/null': Bad address ++ +mknod: '/mnt/f2fs/null': Bad address ++ +chmod: cannot access '/mnt/f2fs/null': Bad address ++ +./tests/generic/184: line 36: /mnt/f2fs/null: Bad address ++ ... ++ ++F2FS-fs (zram0): access invalid blkaddr:259 ++EIP: f2fs_is_valid_blkaddr+0x14b/0x1b0 [f2fs] ++ f2fs_iget+0x927/0x1010 [f2fs] ++ f2fs_lookup+0x26e/0x630 [f2fs] ++ __lookup_slow+0xb3/0x140 ++ lookup_slow+0x31/0x50 ++ walk_component+0x185/0x1f0 ++ path_lookupat+0x51/0x190 ++ filename_lookup+0x7f/0x140 ++ user_path_at_empty+0x36/0x40 ++ vfs_statx+0x61/0xc0 ++ __do_sys_stat64+0x29/0x40 ++ sys_stat64+0x13/0x20 ++ do_fast_syscall_32+0xaa/0x22c ++ entry_SYSENTER_32+0x53/0x86 ++ ++In f2fs_iget(), we will check inode's first block address, if it is valid, ++we will set FI_FIRST_BLOCK_WRITTEN flag in inode. ++ ++But we should only do this for regular inode, otherwise, like special ++inode, i_addr[0] is used for storing device info instead of block address, ++it will fail checking flow obviously. ++ ++So for non-regular inode, let's skip verifying address and setting flag. ++ ++Signed-off-by: Chao Yu ++Signed-off-by: Jaegeuk Kim ++--- ++ fs/f2fs/inode.c | 14 ++++++++------ ++ 1 file changed, 8 insertions(+), 6 deletions(-) ++ ++--- a/fs/f2fs/inode.c +++++ b/fs/f2fs/inode.c ++@@ -310,13 +310,15 @@ static int do_read_inode(struct inode *i ++ /* get rdev by using inline_info */ ++ __get_inode_rdev(inode, ri); ++ ++- err = __written_first_block(sbi, ri); ++- if (err < 0) { ++- f2fs_put_page(node_page, 1); ++- return err; +++ if (S_ISREG(inode->i_mode)) { +++ err = __written_first_block(sbi, ri); +++ if (err < 0) { +++ f2fs_put_page(node_page, 1); +++ return err; +++ } +++ if (!err) +++ set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN); ++ } ++- if (!err) ++- set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN); ++ ++ if (!need_inode_block_update(sbi, inode->i_ino)) ++ fi->last_disk_size = inode->i_size; +diff --git a/target/linux/generic/backport-4.14/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch b/target/linux/generic/backport-4.14/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch +new file mode 100644 +index 0000000000..db239e0a00 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch +@@ -0,0 +1,50 @@ ++From 12acd136913ccdf394eeb2bc8686ff5505368119 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Thu, 12 Oct 2017 10:21:26 +0200 ++Subject: [PATCH] net: bgmac: enable master mode for BCM54210E and B50212E PHYs ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++There are 4 very similar PHYs: ++0x600d84a1: BCM54210E (rev B0) ++0x600d84a2: BCM54210E (rev B1) ++0x600d84a5: B50212E (rev B0) ++0x600d84a6: B50212E (rev B1) ++that need setting master mode manually. It's because they run in slave ++mode by default with Automatic Slave/Master configuration disabled which ++can lead to unreliable connection with massive ping loss. ++ ++So far it was reported for a board with BCM47189 SoC and B50212E B1 PHY ++connected to the bgmac supported ethernet device. Telling PHY driver to ++setup PHY properly solves this issue. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: David S. Miller ++--- ++ drivers/net/ethernet/broadcom/bgmac-bcma.c | 8 +++++++- ++ 1 file changed, 7 insertions(+), 1 deletion(-) ++ ++--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c +++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c ++@@ -184,13 +184,19 @@ static int bgmac_probe(struct bcma_devic ++ ++ if (!bgmac_is_bcm4707_family(core) && ++ !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) { +++ struct phy_device *phydev; +++ ++ mii_bus = bcma_mdio_mii_register(bgmac); ++ if (IS_ERR(mii_bus)) { ++ err = PTR_ERR(mii_bus); ++ goto err; ++ } ++- ++ bgmac->mii_bus = mii_bus; +++ +++ phydev = mdiobus_get_phy(bgmac->mii_bus, bgmac->phyaddr); +++ if (ci->id == BCMA_CHIP_ID_BCM53573 && phydev && +++ (phydev->drv->phy_id & phydev->drv->phy_id_mask) == PHY_ID_BCM54210E) +++ phydev->dev_flags |= PHY_BRCM_EN_MASTER_MODE; ++ } ++ ++ if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) { +diff --git a/target/linux/generic/backport-4.14/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch b/target/linux/generic/backport-4.14/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch +new file mode 100644 +index 0000000000..a22d272656 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch +@@ -0,0 +1,54 @@ ++From 2355a6546a053b1c16ebefd6ce1f0cccc00e1da5 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Thu, 12 Oct 2017 10:21:25 +0200 ++Subject: [PATCH] net: phy: broadcom: support new device flag for setting ++ master mode ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Some of Broadcom's PHYs run by default in slave mode with Automatic ++Slave/Master configuration disabled. It stops them from working properly ++with some devices. ++ ++So far it has been verified for BCM54210E and BCM50212E which don't ++work well with Intel's I217-LM and I218-LM: ++http://ark.intel.com/products/60019/Intel-Ethernet-Connection-I217-LM ++http://ark.intel.com/products/71307/Intel-Ethernet-Connection-I218-LM ++I was told there is massive ping loss. ++ ++This commit adds support for a new flag which can be set by an ethernet ++driver to fixup PHY setup. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: David S. Miller ++--- ++ drivers/net/phy/broadcom.c | 6 ++++++ ++ include/linux/brcmphy.h | 1 + ++ 2 files changed, 7 insertions(+) ++ ++--- a/drivers/net/phy/broadcom.c +++++ b/drivers/net/phy/broadcom.c ++@@ -43,6 +43,12 @@ static int bcm54210e_config_init(struct ++ val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN; ++ bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val); ++ +++ if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) { +++ val = phy_read(phydev, MII_CTRL1000); +++ val |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER; +++ phy_write(phydev, MII_CTRL1000, val); +++ } +++ ++ return 0; ++ } ++ ++--- a/include/linux/brcmphy.h +++++ b/include/linux/brcmphy.h ++@@ -64,6 +64,7 @@ ++ #define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000 ++ #define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000 ++ #define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00008000 +++#define PHY_BRCM_EN_MASTER_MODE 0x00010000 ++ ++ /* Broadcom BCM7xxx specific workarounds */ ++ #define PHY_BRCM_7XXX_REV(x) (((x) >> 8) & 0xff) +diff --git a/target/linux/generic/backport-4.14/080-v5.1-0001-bcma-keep-a-direct-pointer-to-the-struct-device.patch b/target/linux/generic/backport-4.14/080-v5.1-0001-bcma-keep-a-direct-pointer-to-the-struct-device.patch +new file mode 100644 +index 0000000000..cc32aee17b +--- /dev/null ++++ b/target/linux/generic/backport-4.14/080-v5.1-0001-bcma-keep-a-direct-pointer-to-the-struct-device.patch +@@ -0,0 +1,199 @@ ++From 5a1c18b761ddb299a06746948b9ec2814b04fa92 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Wed, 2 Jan 2019 00:00:01 +0100 ++Subject: [PATCH] bcma: keep a direct pointer to the struct device ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Accessing struct device is pretty useful/common so having a direct ++pointer: ++1) Simplifies some code ++2) Makes bcma_bus_get_host_dev() unneeded ++3) Allows further improvements like using dev_* printing helpers ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ drivers/bcma/bcma_private.h | 1 - ++ drivers/bcma/driver_gpio.c | 2 +- ++ drivers/bcma/host_pci.c | 2 ++ ++ drivers/bcma/host_soc.c | 4 ++-- ++ drivers/bcma/main.c | 45 +++++++++---------------------------- ++ include/linux/bcma/bcma.h | 11 +++------ ++ 6 files changed, 18 insertions(+), 47 deletions(-) ++ ++--- a/drivers/bcma/bcma_private.h +++++ b/drivers/bcma/bcma_private.h ++@@ -33,7 +33,6 @@ int __init bcma_bus_early_register(struc ++ int bcma_bus_suspend(struct bcma_bus *bus); ++ int bcma_bus_resume(struct bcma_bus *bus); ++ #endif ++-struct device *bcma_bus_get_host_dev(struct bcma_bus *bus); ++ ++ /* scan.c */ ++ void bcma_detect_chip(struct bcma_bus *bus); ++--- a/drivers/bcma/driver_gpio.c +++++ b/drivers/bcma/driver_gpio.c ++@@ -183,7 +183,7 @@ int bcma_gpio_init(struct bcma_drv_cc *c ++ chip->direction_input = bcma_gpio_direction_input; ++ chip->direction_output = bcma_gpio_direction_output; ++ chip->owner = THIS_MODULE; ++- chip->parent = bcma_bus_get_host_dev(bus); +++ chip->parent = bus->dev; ++ #if IS_BUILTIN(CONFIG_OF) ++ chip->of_node = cc->core->dev.of_node; ++ #endif ++--- a/drivers/bcma/host_pci.c +++++ b/drivers/bcma/host_pci.c ++@@ -196,6 +196,8 @@ static int bcma_host_pci_probe(struct pc ++ goto err_pci_release_regions; ++ } ++ +++ bus->dev = &dev->dev; +++ ++ /* Map MMIO */ ++ err = -ENOMEM; ++ bus->mmio = pci_iomap(dev, 0, ~0UL); ++--- a/drivers/bcma/host_soc.c +++++ b/drivers/bcma/host_soc.c ++@@ -179,7 +179,6 @@ int __init bcma_host_soc_register(struct ++ /* Host specific */ ++ bus->hosttype = BCMA_HOSTTYPE_SOC; ++ bus->ops = &bcma_host_soc_ops; ++- bus->host_pdev = NULL; ++ ++ /* Initialize struct, detect chip */ ++ bcma_init_bus(bus); ++@@ -213,6 +212,8 @@ static int bcma_host_soc_probe(struct pl ++ if (!bus) ++ return -ENOMEM; ++ +++ bus->dev = dev; +++ ++ /* Map MMIO */ ++ bus->mmio = of_iomap(np, 0); ++ if (!bus->mmio) ++@@ -221,7 +222,6 @@ static int bcma_host_soc_probe(struct pl ++ /* Host specific */ ++ bus->hosttype = BCMA_HOSTTYPE_SOC; ++ bus->ops = &bcma_host_soc_ops; ++- bus->host_pdev = pdev; ++ ++ /* Initialize struct, detect chip */ ++ bcma_init_bus(bus); ++--- a/drivers/bcma/main.c +++++ b/drivers/bcma/main.c ++@@ -223,8 +223,8 @@ unsigned int bcma_core_irq(struct bcma_d ++ mips_irq = bcma_core_mips_irq(core); ++ return mips_irq <= 4 ? mips_irq + 2 : 0; ++ } ++- if (bus->host_pdev) ++- return bcma_of_get_irq(&bus->host_pdev->dev, core, num); +++ if (bus->dev) +++ return bcma_of_get_irq(bus->dev, core, num); ++ return 0; ++ case BCMA_HOSTTYPE_SDIO: ++ return 0; ++@@ -239,18 +239,18 @@ void bcma_prepare_core(struct bcma_bus * ++ core->dev.release = bcma_release_core_dev; ++ core->dev.bus = &bcma_bus_type; ++ dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); ++- core->dev.parent = bcma_bus_get_host_dev(bus); ++- if (core->dev.parent) ++- bcma_of_fill_device(core->dev.parent, core); +++ core->dev.parent = bus->dev; +++ if (bus->dev) +++ bcma_of_fill_device(bus->dev, core); ++ ++ switch (bus->hosttype) { ++ case BCMA_HOSTTYPE_PCI: ++- core->dma_dev = &bus->host_pci->dev; +++ core->dma_dev = bus->dev; ++ core->irq = bus->host_pci->irq; ++ break; ++ case BCMA_HOSTTYPE_SOC: ++- if (IS_ENABLED(CONFIG_OF) && bus->host_pdev) { ++- core->dma_dev = &bus->host_pdev->dev; +++ if (IS_ENABLED(CONFIG_OF) && bus->dev) { +++ core->dma_dev = bus->dev; ++ } else { ++ core->dev.dma_mask = &core->dev.coherent_dma_mask; ++ core->dma_dev = &core->dev; ++@@ -261,28 +261,6 @@ void bcma_prepare_core(struct bcma_bus * ++ } ++ } ++ ++-struct device *bcma_bus_get_host_dev(struct bcma_bus *bus) ++-{ ++- switch (bus->hosttype) { ++- case BCMA_HOSTTYPE_PCI: ++- if (bus->host_pci) ++- return &bus->host_pci->dev; ++- else ++- return NULL; ++- case BCMA_HOSTTYPE_SOC: ++- if (bus->host_pdev) ++- return &bus->host_pdev->dev; ++- else ++- return NULL; ++- case BCMA_HOSTTYPE_SDIO: ++- if (bus->host_sdio) ++- return &bus->host_sdio->dev; ++- else ++- return NULL; ++- } ++- return NULL; ++-} ++- ++ void bcma_init_bus(struct bcma_bus *bus) ++ { ++ mutex_lock(&bcma_buses_mutex); ++@@ -402,7 +380,6 @@ int bcma_bus_register(struct bcma_bus *b ++ { ++ int err; ++ struct bcma_device *core; ++- struct device *dev; ++ ++ /* Scan for devices (cores) */ ++ err = bcma_bus_scan(bus); ++@@ -425,10 +402,8 @@ int bcma_bus_register(struct bcma_bus *b ++ bcma_core_pci_early_init(&bus->drv_pci[0]); ++ } ++ ++- dev = bcma_bus_get_host_dev(bus); ++- if (dev) { ++- of_platform_default_populate(dev->of_node, NULL, dev); ++- } +++ if (bus->dev) +++ of_platform_default_populate(bus->dev->of_node, NULL, bus->dev); ++ ++ /* Cores providing flash access go before SPROM init */ ++ list_for_each_entry(core, &bus->cores, list) { ++--- a/include/linux/bcma/bcma.h +++++ b/include/linux/bcma/bcma.h ++@@ -332,6 +332,8 @@ extern int bcma_arch_register_fallback_s ++ struct ssb_sprom *out)); ++ ++ struct bcma_bus { +++ struct device *dev; +++ ++ /* The MMIO area. */ ++ void __iomem *mmio; ++ ++@@ -339,14 +341,7 @@ struct bcma_bus { ++ ++ enum bcma_hosttype hosttype; ++ bool host_is_pcie2; /* Used for BCMA_HOSTTYPE_PCI only */ ++- union { ++- /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ ++- struct pci_dev *host_pci; ++- /* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */ ++- struct sdio_func *host_sdio; ++- /* Pointer to platform device (only for BCMA_HOSTTYPE_SOC) */ ++- struct platform_device *host_pdev; ++- }; +++ struct pci_dev *host_pci; /* PCI bus pointer (BCMA_HOSTTYPE_PCI only) */ ++ ++ struct bcma_chipinfo chipinfo; ++ +diff --git a/target/linux/generic/backport-4.14/080-v5.1-0002-bcma-use-dev_-printing-functions.patch b/target/linux/generic/backport-4.14/080-v5.1-0002-bcma-use-dev_-printing-functions.patch +new file mode 100644 +index 0000000000..7ce8ba8967 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/080-v5.1-0002-bcma-use-dev_-printing-functions.patch +@@ -0,0 +1,36 @@ ++From 777bc4801a6868fcbff09ffb6e30f023e7c5ed38 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Wed, 2 Jan 2019 00:00:02 +0100 ++Subject: [PATCH] bcma: use dev_* printing functions ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++It provides more meaningful messages. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ drivers/bcma/bcma_private.h | 8 ++++---- ++ 1 file changed, 4 insertions(+), 4 deletions(-) ++ ++--- a/drivers/bcma/bcma_private.h +++++ b/drivers/bcma/bcma_private.h ++@@ -10,13 +10,13 @@ ++ #include ++ ++ #define bcma_err(bus, fmt, ...) \ ++- pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) +++ dev_err((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) ++ #define bcma_warn(bus, fmt, ...) \ ++- pr_warn("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) +++ dev_warn((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) ++ #define bcma_info(bus, fmt, ...) \ ++- pr_info("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) +++ dev_info((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) ++ #define bcma_debug(bus, fmt, ...) \ ++- pr_debug("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) +++ dev_dbg((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) ++ ++ struct bcma_bus; ++ +diff --git a/target/linux/generic/backport-4.14/085-v4.16-0001-i2c-gpio-Enable-working-over-slow-can_sleep-GPIOs.patch b/target/linux/generic/backport-4.14/085-v4.16-0001-i2c-gpio-Enable-working-over-slow-can_sleep-GPIOs.patch +new file mode 100644 +index 0000000000..ead6675e0b +--- /dev/null ++++ b/target/linux/generic/backport-4.14/085-v4.16-0001-i2c-gpio-Enable-working-over-slow-can_sleep-GPIOs.patch +@@ -0,0 +1,84 @@ ++From f11a04464ae57e8db1bb7634547842b43e36a898 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= ++Date: Fri, 22 Dec 2017 22:47:16 +0100 ++Subject: i2c: gpio: Enable working over slow can_sleep GPIOs ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++"Slow" GPIOs (usually those connected over an SPI or an I2C bus) are, ++well, slow in their operation. It is generally a good idea to avoid ++using them for time-critical operation, but sometimes the hardware just ++sucks, and the software has to cope. In addition to that, the I2C bus ++itself does not actually define any strict timing limits; the bus is ++free to go all the way down to DC. The timeouts (and therefore the ++slowest acceptable frequency) are present only in SMBus. ++ ++The `can_sleep` is IMHO a wrong concept to use here. My SPI-to-quad-UART ++chip (MAX14830) is connected via a 26MHz SPI bus, and it happily drives ++SCL at 200kHz (5µs pulses) during my benchmarks. That's faster than the ++maximal allowed speed of the traditional I2C. ++ ++The previous version of this code did not really block operation over ++slow GPIO pins, anyway. Instead, it just resorted to printing a warning ++with a backtrace each time a GPIO pin was accessed, thereby slowing ++things down even more. ++ ++Finally, it's not just me. A similar patch was originally submitted in ++2015 [1]. ++ ++[1] https://patchwork.ozlabs.org/patch/450956/ ++ ++Signed-off-by: Jan Kundrát ++Acked-by: Uwe Kleine-König ++Signed-off-by: Wolfram Sang ++--- ++ drivers/i2c/busses/i2c-gpio.c | 11 +++++++---- ++ 1 file changed, 7 insertions(+), 4 deletions(-) ++ ++--- a/drivers/i2c/busses/i2c-gpio.c +++++ b/drivers/i2c/busses/i2c-gpio.c ++@@ -44,7 +44,7 @@ static void i2c_gpio_setsda_val(void *da ++ { ++ struct i2c_gpio_platform_data *pdata = data; ++ ++- gpio_set_value(pdata->sda_pin, state); +++ gpio_set_value_cansleep(pdata->sda_pin, state); ++ } ++ ++ /* Toggle SCL by changing the direction of the pin. */ ++@@ -68,21 +68,21 @@ static void i2c_gpio_setscl_val(void *da ++ { ++ struct i2c_gpio_platform_data *pdata = data; ++ ++- gpio_set_value(pdata->scl_pin, state); +++ gpio_set_value_cansleep(pdata->scl_pin, state); ++ } ++ ++ static int i2c_gpio_getsda(void *data) ++ { ++ struct i2c_gpio_platform_data *pdata = data; ++ ++- return gpio_get_value(pdata->sda_pin); +++ return gpio_get_value_cansleep(pdata->sda_pin); ++ } ++ ++ static int i2c_gpio_getscl(void *data) ++ { ++ struct i2c_gpio_platform_data *pdata = data; ++ ++- return gpio_get_value(pdata->scl_pin); +++ return gpio_get_value_cansleep(pdata->scl_pin); ++ } ++ ++ static int of_i2c_gpio_get_pins(struct device_node *np, ++@@ -175,6 +175,9 @@ static int i2c_gpio_probe(struct platfor ++ memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata)); ++ } ++ +++ if (gpiod_cansleep(gpio_to_desc(pdata->sda_pin)) || gpiod_cansleep(gpio_to_desc(pdata->scl_pin))) +++ dev_warn(&pdev->dev, "Slow GPIO pins might wreak havoc into I2C/SMBus bus timing"); +++ ++ if (pdata->sda_is_open_drain) { ++ gpio_direction_output(pdata->sda_pin, 1); ++ bit_data->setsda = i2c_gpio_setsda_val; +diff --git a/target/linux/generic/backport-4.14/090-net-bridge-add-support-for-port-isolation.patch b/target/linux/generic/backport-4.14/090-net-bridge-add-support-for-port-isolation.patch +new file mode 100644 +index 0000000000..6237177a45 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/090-net-bridge-add-support-for-port-isolation.patch +@@ -0,0 +1,145 @@ ++From: Nikolay Aleksandrov ++Date: Thu, 24 May 2018 11:56:48 +0300 ++Subject: [PATCH] net: bridge: add support for port isolation ++ ++This patch adds support for a new port flag - BR_ISOLATED. If it is set ++then isolated ports cannot communicate between each other, but they can ++still communicate with non-isolated ports. The same can be achieved via ++ACLs but they can't scale with large number of ports and also the ++complexity of the rules grows. This feature can be used to achieve ++isolated vlan functionality (similar to pvlan) as well, though currently ++it will be port-wide (for all vlans on the port). The new test in ++should_deliver uses data that is already cache hot and the new boolean ++is used to avoid an additional source port test in should_deliver. ++ ++Signed-off-by: Nikolay Aleksandrov ++Reviewed-by: Toshiaki Makita ++Signed-off-by: David S. Miller ++--- ++ ++--- a/include/uapi/linux/if_link.h +++++ b/include/uapi/linux/if_link.h ++@@ -326,6 +326,8 @@ enum { ++ IFLA_BRPORT_MCAST_TO_UCAST, ++ IFLA_BRPORT_VLAN_TUNNEL, ++ IFLA_BRPORT_BCAST_FLOOD, +++ IFLA_BRPORT_NEIGH_SUPPRESS, +++ IFLA_BRPORT_ISOLATED, ++ __IFLA_BRPORT_MAX ++ }; ++ #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) ++--- a/net/bridge/br_forward.c +++++ b/net/bridge/br_forward.c ++@@ -30,7 +30,8 @@ static inline int should_deliver(const s ++ vg = nbp_vlan_group_rcu(p); ++ return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) && ++ br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING && ++- nbp_switchdev_allowed_egress(p, skb); +++ nbp_switchdev_allowed_egress(p, skb) && +++ !br_skb_isolated(p, skb); ++ } ++ ++ int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) ++--- a/net/bridge/br_input.c +++++ b/net/bridge/br_input.c ++@@ -170,6 +170,7 @@ int br_handle_frame_finish(struct net *n ++ goto drop; ++ ++ BR_INPUT_SKB_CB(skb)->brdev = br->dev; +++ BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED); ++ ++ if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP)) ++ br_do_proxy_arp(skb, br, vid, p); ++--- a/net/bridge/br_netlink.c +++++ b/net/bridge/br_netlink.c ++@@ -138,6 +138,7 @@ static inline size_t br_port_info_size(v ++ + nla_total_size(1) /* IFLA_BRPORT_PROXYARP */ ++ + nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */ ++ + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */ +++ + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */ ++ + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ ++ + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ ++ + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ ++@@ -208,7 +209,8 @@ static int br_port_fill_attrs(struct sk_ ++ p->topology_change_ack) || ++ nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending) || ++ nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(p->flags & ++- BR_VLAN_TUNNEL))) +++ BR_VLAN_TUNNEL)) || +++ nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED))) ++ return -EMSGSIZE; ++ ++ timerval = br_timer_value(&p->message_age_timer); ++@@ -637,6 +639,7 @@ static const struct nla_policy br_port_p ++ [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 }, ++ [IFLA_BRPORT_MCAST_FLOOD] = { .type = NLA_U8 }, ++ [IFLA_BRPORT_BCAST_FLOOD] = { .type = NLA_U8 }, +++ [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 }, ++ }; ++ ++ /* Change the state of the port and notify spanning tree */ ++@@ -773,6 +776,11 @@ static int br_setport(struct net_bridge_ ++ return err; ++ } ++ #endif +++ +++ err = br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED); +++ if (err) +++ return err; +++ ++ br_port_flags_change(p, old_flags ^ p->flags); ++ return 0; ++ } ++--- a/net/bridge/br_private.h +++++ b/net/bridge/br_private.h ++@@ -407,6 +407,7 @@ struct br_input_skb_cb { ++ #endif ++ ++ bool proxyarp_replied; +++ bool src_port_isolated; ++ ++ #ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ bool vlan_filtered; ++@@ -554,6 +555,14 @@ int br_forward_finish(struct net *net, s ++ void br_flood(struct net_bridge *br, struct sk_buff *skb, ++ enum br_pkt_type pkt_type, bool local_rcv, bool local_orig); ++ +++/* return true if both source port and dest port are isolated */ +++static inline bool br_skb_isolated(const struct net_bridge_port *to, +++ const struct sk_buff *skb) +++{ +++ return BR_INPUT_SKB_CB(skb)->src_port_isolated && +++ (to->flags & BR_ISOLATED); +++} +++ ++ /* br_if.c */ ++ void br_port_carrier_check(struct net_bridge_port *p); ++ int br_add_bridge(struct net *net, const char *name); ++--- a/net/bridge/br_sysfs_if.c +++++ b/net/bridge/br_sysfs_if.c ++@@ -174,6 +174,7 @@ BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP); ++ BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI); ++ BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD); ++ BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); +++BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); ++ ++ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING ++ static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) ++@@ -223,6 +224,7 @@ static const struct brport_attribute *br ++ &brport_attr_proxyarp_wifi, ++ &brport_attr_multicast_flood, ++ &brport_attr_broadcast_flood, +++ &brport_attr_isolated, ++ NULL ++ }; ++ ++--- a/include/linux/if_bridge.h +++++ b/include/linux/if_bridge.h ++@@ -49,6 +49,7 @@ struct br_ip_list { ++ #define BR_MULTICAST_TO_UNICAST BIT(12) ++ #define BR_VLAN_TUNNEL BIT(13) ++ #define BR_BCAST_FLOOD BIT(14) +++#define BR_ISOLATED BIT(16) ++ ++ #define BR_DEFAULT_AGEING_TIME (300 * HZ) ++ +diff --git a/target/linux/generic/backport-4.14/095-Allow-class-e-address-assignment-via-ifconfig-ioctl.patch b/target/linux/generic/backport-4.14/095-Allow-class-e-address-assignment-via-ifconfig-ioctl.patch +new file mode 100644 +index 0000000000..e2698dd02e +--- /dev/null ++++ b/target/linux/generic/backport-4.14/095-Allow-class-e-address-assignment-via-ifconfig-ioctl.patch +@@ -0,0 +1,79 @@ ++From 46bf067870156abd61fe24d14c2486d15b8b502c Mon Sep 17 00:00:00 2001 ++From: Dave Taht ++Date: Fri, 14 Dec 2018 18:38:40 +0000 ++Subject: [PATCH 1/1] Allow class-e address assignment in ifconfig and early ++ boot ++ ++While the linux kernel became mostly "class-e clean" a decade ago, ++and most distributions long ago switched to the iproute2 suite ++of utilities, which allow class-e (240.0.0.0/4) address assignment, ++distributions relying on busybox, toybox and other forms of ++ifconfig cannot assign class-e addresses without this kernel patch. ++ ++With this patch, also, a boot command line on these addresses is feasible: ++(ip=248.0.1.2::248.0.1.1:255.255.255.0). ++ ++While CIDR has been obsolete for 2 decades, and a survey of all the ++userspace open source code in the world shows most IN_whatever macros ++are also obsolete... rather than obsolete CIDR from this ioctl entirely, ++this patch merely enables class-e assignment, sanely. ++ ++H/T to Vince Fuller and his original patch here: ++ https://lkml.org/lkml/2008/1/7/370 ++ ++Signed-off-by: Dave Taht ++Reviewed-by: John Gilmore ++--- ++ include/uapi/linux/in.h | 8 ++++++-- ++ net/ipv4/devinet.c | 4 +++- ++ net/ipv4/ipconfig.c | 2 ++ ++ 3 files changed, 11 insertions(+), 3 deletions(-) ++ ++--- a/include/uapi/linux/in.h +++++ b/include/uapi/linux/in.h ++@@ -268,8 +268,12 @@ struct sockaddr_in { ++ #define IN_MULTICAST(a) IN_CLASSD(a) ++ #define IN_MULTICAST_NET 0xF0000000 ++ ++-#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000) ++-#define IN_BADCLASS(a) IN_EXPERIMENTAL((a)) +++#define IN_BADCLASS(a) (((long int) (a) ) == (long int)0xffffffff) +++#define IN_EXPERIMENTAL(a) IN_BADCLASS((a)) +++ +++#define IN_CLASSE(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000) +++#define IN_CLASSE_NET 0xffffffff +++#define IN_CLASSE_NSHIFT 0 ++ ++ /* Address to accept any incoming messages. */ ++ #define INADDR_ANY ((unsigned long int) 0x00000000) ++--- a/net/ipv4/devinet.c +++++ b/net/ipv4/devinet.c ++@@ -935,7 +935,7 @@ static int inet_abc_len(__be32 addr) ++ { ++ int rc = -1; /* Something else, probably a multicast. */ ++ ++- if (ipv4_is_zeronet(addr)) +++ if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr)) ++ rc = 0; ++ else { ++ __u32 haddr = ntohl(addr); ++@@ -946,6 +946,8 @@ static int inet_abc_len(__be32 addr) ++ rc = 16; ++ else if (IN_CLASSC(haddr)) ++ rc = 24; +++ else if (IN_CLASSE(haddr)) +++ rc = 32; ++ } ++ ++ return rc; ++--- a/net/ipv4/ipconfig.c +++++ b/net/ipv4/ipconfig.c ++@@ -457,6 +457,8 @@ static int __init ic_defaults(void) ++ ic_netmask = htonl(IN_CLASSB_NET); ++ else if (IN_CLASSC(ntohl(ic_myaddr))) ++ ic_netmask = htonl(IN_CLASSC_NET); +++ else if (IN_CLASSE(ntohl(ic_myaddr))) +++ ic_netmask = htonl(IN_CLASSE_NET); ++ else { ++ pr_err("IP-Config: Unable to guess netmask for address %pI4\n", ++ &ic_myaddr); +diff --git a/target/linux/generic/backport-4.14/101-arm-cns3xxx-use-actual-size-reads-for-PCIe.patch b/target/linux/generic/backport-4.14/101-arm-cns3xxx-use-actual-size-reads-for-PCIe.patch +new file mode 100644 +index 0000000000..2b3384391a +--- /dev/null ++++ b/target/linux/generic/backport-4.14/101-arm-cns3xxx-use-actual-size-reads-for-PCIe.patch +@@ -0,0 +1,46 @@ ++From 4cc30de79d293f1e8c5f50ae3a9c005def9564a0 Mon Sep 17 00:00:00 2001 ++From: Koen Vandeputte ++Date: Mon, 7 Jan 2019 14:14:27 +0100 ++Subject: [PATCH 2/2] arm: cns3xxx: use actual size reads for PCIe ++ ++commit 802b7c06adc7 ("ARM: cns3xxx: Convert PCI to use generic config accessors") ++reimplemented cns3xxx_pci_read_config() using pci_generic_config_read32(), ++which preserved the property of only doing 32-bit reads. ++ ++It also replaced cns3xxx_pci_write_config() with pci_generic_config_write(), ++so it changed writes from always being 32 bits to being the actual size, ++which works just fine. ++ ++Due to: ++- The documentation does not mention that only 32 bit access is allowed. ++- Writes are already executed using the actual size ++- Extensive testing shows that 8b, 16b and 32b reads work as intended ++ ++It makes perfectly sense to also swap 32 bit reading in favor of actual size. ++ ++Fixes: 802b7c06adc7 ("ARM: cns3xxx: Convert PCI to use generic config accessors") ++Suggested-by: Bjorn Helgaas ++Signed-off-by: Koen Vandeputte ++CC: Arnd Bergmann ++CC: Krzysztof Halasa ++CC: Olof Johansson ++CC: Robin Leblon ++CC: Rob Herring ++CC: Russell King ++CC: Tim Harvey ++CC: stable@vger.kernel.org # v4.0+ ++--- ++ arch/arm/mach-cns3xxx/pcie.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/arch/arm/mach-cns3xxx/pcie.c +++++ b/arch/arm/mach-cns3xxx/pcie.c ++@@ -93,7 +93,7 @@ static int cns3xxx_pci_read_config(struc ++ u32 mask = (0x1ull << (size * 8)) - 1; ++ int shift = (where % 4) * 8; ++ ++- ret = pci_generic_config_read32(bus, devfn, where, size, val); +++ ret = pci_generic_config_read(bus, devfn, where, size, val); ++ ++ if (ret == PCIBIOS_SUCCESSFUL && !bus->number && !devfn && ++ (where & 0xffc) == PCI_CLASS_REVISION) +diff --git a/target/linux/generic/backport-4.14/183-net-qmi_wwan-add-Wistron-Neweb-D19Q1.patch b/target/linux/generic/backport-4.14/183-net-qmi_wwan-add-Wistron-Neweb-D19Q1.patch +new file mode 100644 +index 0000000000..078c9aaa50 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/183-net-qmi_wwan-add-Wistron-Neweb-D19Q1.patch +@@ -0,0 +1,54 @@ ++From eb5a26bcaddb35fd42a978ad37831e58b1118853 Mon Sep 17 00:00:00 2001 ++From: Pawel Dembicki ++Date: Tue, 17 Apr 2018 19:53:59 +0200 ++Subject: [PATCH] net: qmi_wwan: add Wistron Neweb D19Q1 ++ ++This modem is embedded on dlink dwr-960 router. ++The oem configuration states: ++ ++T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 ++D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 ++P: Vendor=1435 ProdID=d191 Rev=ff.ff ++S: Manufacturer=Android ++S: Product=Android ++S: SerialNumber=0123456789ABCDEF ++C:* #Ifs= 6 Cfg#= 1 Atr=80 MxPwr=500mA ++I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) ++E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) ++E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) ++E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms ++E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) ++E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms ++E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan ++E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms ++E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++I:* If#= 5 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none) ++E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms ++E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=125us ++ ++Tested on openwrt distribution ++ ++Signed-off-by: Pawel Dembicki ++--- ++ drivers/net/usb/qmi_wwan.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/net/usb/qmi_wwan.c +++++ b/drivers/net/usb/qmi_wwan.c ++@@ -1138,6 +1138,7 @@ static const struct usb_device_id produc ++ {QMI_FIXED_INTF(0x1435, 0xd181, 3)}, /* Wistron NeWeb D18Q1 */ ++ {QMI_FIXED_INTF(0x1435, 0xd181, 4)}, /* Wistron NeWeb D18Q1 */ ++ {QMI_FIXED_INTF(0x1435, 0xd181, 5)}, /* Wistron NeWeb D18Q1 */ +++ {QMI_FIXED_INTF(0x1435, 0xd191, 4)}, /* Wistron NeWeb D19Q1 */ ++ {QMI_QUIRK_SET_DTR(0x1508, 0x1001, 4)}, /* Fibocom NL668 series */ ++ {QMI_FIXED_INTF(0x1690, 0x7588, 4)}, /* ASKEY WWHC050 */ ++ {QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */ +diff --git a/target/linux/generic/backport-4.14/270-batman-adv-Let-packet.h-include-its-headers-directly.patch b/target/linux/generic/backport-4.14/270-batman-adv-Let-packet.h-include-its-headers-directly.patch +new file mode 100644 +index 0000000000..9b3dfc1fd3 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/270-batman-adv-Let-packet.h-include-its-headers-directly.patch +@@ -0,0 +1,36 @@ ++From: Sven Eckelmann ++Date: Thu, 21 Dec 2017 10:17:38 +0100 ++Subject: [PATCH] batman-adv: Let packet.h include its headers directly ++ ++The headers used by packet.h should also be included by it directly. main.h ++is currently dealing with it in batman-adv, but this will no longer work ++when this header is moved to include/uapi/linux/. ++ ++Signed-off-by: Sven Eckelmann ++Signed-off-by: David S. Miller ++--- ++ ++--- a/net/batman-adv/main.h +++++ b/net/batman-adv/main.h ++@@ -184,10 +184,8 @@ enum batadv_uev_type { ++ ++ /* Kernel headers */ ++ ++-#include /* for packet.h */ ++ #include ++ #include ++-#include /* for packet.h */ ++ #include ++ #include ++ #include ++--- a/net/batman-adv/packet.h +++++ b/net/batman-adv/packet.h ++@@ -19,6 +19,8 @@ ++ #define _NET_BATMAN_ADV_PACKET_H_ ++ ++ #include +++#include +++#include ++ #include ++ ++ #define batadv_tp_is_error(n) ((u8)(n) > 127 ? 1 : 0) +diff --git a/target/linux/generic/backport-4.14/271-batman-adv-Remove-usage-of-BIT-x-in-packet.h.patch b/target/linux/generic/backport-4.14/271-batman-adv-Remove-usage-of-BIT-x-in-packet.h.patch +new file mode 100644 +index 0000000000..5466d234d8 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/271-batman-adv-Remove-usage-of-BIT-x-in-packet.h.patch +@@ -0,0 +1,72 @@ ++From: Sven Eckelmann ++Date: Thu, 21 Dec 2017 10:17:39 +0100 ++Subject: [PATCH] batman-adv: Remove usage of BIT(x) in packet.h ++ ++The BIT(x) macro is no longer available for uapi headers because it is ++defined outside of it (linux/bitops.h). The use of it must therefore be ++avoided and replaced by an appropriate other representation. ++ ++Signed-off-by: Sven Eckelmann ++Signed-off-by: David S. Miller ++--- ++ ++--- a/net/batman-adv/packet.h +++++ b/net/batman-adv/packet.h ++@@ -19,7 +19,6 @@ ++ #define _NET_BATMAN_ADV_PACKET_H_ ++ ++ #include ++-#include ++ #include ++ #include ++ ++@@ -85,9 +84,9 @@ enum batadv_subtype { ++ * one hop neighbor on the interface where it was originally received. ++ */ ++ enum batadv_iv_flags { ++- BATADV_NOT_BEST_NEXT_HOP = BIT(0), ++- BATADV_PRIMARIES_FIRST_HOP = BIT(1), ++- BATADV_DIRECTLINK = BIT(2), +++ BATADV_NOT_BEST_NEXT_HOP = 1UL << 0, +++ BATADV_PRIMARIES_FIRST_HOP = 1UL << 1, +++ BATADV_DIRECTLINK = 1UL << 2, ++ }; ++ ++ /* ICMP message types */ ++@@ -108,9 +107,9 @@ enum batadv_icmp_packettype { ++ * @BATADV_MCAST_WANT_ALL_IPV6: we want all IPv6 multicast packets ++ */ ++ enum batadv_mcast_flags { ++- BATADV_MCAST_WANT_ALL_UNSNOOPABLES = BIT(0), ++- BATADV_MCAST_WANT_ALL_IPV4 = BIT(1), ++- BATADV_MCAST_WANT_ALL_IPV6 = BIT(2), +++ BATADV_MCAST_WANT_ALL_UNSNOOPABLES = 1UL << 0, +++ BATADV_MCAST_WANT_ALL_IPV4 = 1UL << 1, +++ BATADV_MCAST_WANT_ALL_IPV6 = 1UL << 2, ++ }; ++ ++ /* tt data subtypes */ ++@@ -124,10 +123,10 @@ enum batadv_mcast_flags { ++ * @BATADV_TT_FULL_TABLE: contains full table to replace existing table ++ */ ++ enum batadv_tt_data_flags { ++- BATADV_TT_OGM_DIFF = BIT(0), ++- BATADV_TT_REQUEST = BIT(1), ++- BATADV_TT_RESPONSE = BIT(2), ++- BATADV_TT_FULL_TABLE = BIT(4), +++ BATADV_TT_OGM_DIFF = 1UL << 0, +++ BATADV_TT_REQUEST = 1UL << 1, +++ BATADV_TT_RESPONSE = 1UL << 2, +++ BATADV_TT_FULL_TABLE = 1UL << 4, ++ }; ++ ++ /** ++@@ -135,7 +134,7 @@ enum batadv_tt_data_flags { ++ * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not ++ */ ++ enum batadv_vlan_flags { ++- BATADV_VLAN_HAS_TAG = BIT(15), +++ BATADV_VLAN_HAS_TAG = 1UL << 15, ++ }; ++ ++ /* claim frame types for the bridge loop avoidance */ +diff --git a/target/linux/generic/backport-4.14/272-batman-adv-Remove-kernel-fixed-width-types-in-packet.patch b/target/linux/generic/backport-4.14/272-batman-adv-Remove-kernel-fixed-width-types-in-packet.patch +new file mode 100644 +index 0000000000..c46a8f74c7 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/272-batman-adv-Remove-kernel-fixed-width-types-in-packet.patch +@@ -0,0 +1,386 @@ ++From: Sven Eckelmann ++Date: Thu, 21 Dec 2017 10:17:40 +0100 ++Subject: [PATCH] batman-adv: Remove kernel fixed width types in packet.h ++ ++The uapi headers use the __u8/__u16/... version of the fixed width types ++instead of u8/u16/... The use of the latter must be avoided before ++packet.h is copied to include/uapi/linux/. ++ ++Signed-off-by: Sven Eckelmann ++Signed-off-by: David S. Miller ++--- ++ ++--- a/net/batman-adv/packet.h +++++ b/net/batman-adv/packet.h ++@@ -22,7 +22,7 @@ ++ #include ++ #include ++ ++-#define batadv_tp_is_error(n) ((u8)(n) > 127 ? 1 : 0) +++#define batadv_tp_is_error(n) ((__u8)(n) > 127 ? 1 : 0) ++ ++ /** ++ * enum batadv_packettype - types for batman-adv encapsulated packets ++@@ -169,8 +169,8 @@ enum batadv_tvlv_type { ++ * transport the claim type and the group id ++ */ ++ struct batadv_bla_claim_dst { ++- u8 magic[3]; /* FF:43:05 */ ++- u8 type; /* bla_claimframe */ +++ __u8 magic[3]; /* FF:43:05 */ +++ __u8 type; /* bla_claimframe */ ++ __be16 group; /* group id */ ++ }; ++ ++@@ -190,15 +190,15 @@ struct batadv_bla_claim_dst { ++ * @tvlv_len: length of tvlv data following the ogm header ++ */ ++ struct batadv_ogm_packet { ++- u8 packet_type; ++- u8 version; ++- u8 ttl; ++- u8 flags; +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 flags; ++ __be32 seqno; ++- u8 orig[ETH_ALEN]; ++- u8 prev_sender[ETH_ALEN]; ++- u8 reserved; ++- u8 tq; +++ __u8 orig[ETH_ALEN]; +++ __u8 prev_sender[ETH_ALEN]; +++ __u8 reserved; +++ __u8 tq; ++ __be16 tvlv_len; ++ /* __packed is not needed as the struct size is divisible by 4, ++ * and the largest data type in this struct has a size of 4. ++@@ -219,12 +219,12 @@ struct batadv_ogm_packet { ++ * @throughput: the currently flooded path throughput ++ */ ++ struct batadv_ogm2_packet { ++- u8 packet_type; ++- u8 version; ++- u8 ttl; ++- u8 flags; +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 flags; ++ __be32 seqno; ++- u8 orig[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; ++ __be16 tvlv_len; ++ __be32 throughput; ++ /* __packed is not needed as the struct size is divisible by 4, ++@@ -243,9 +243,9 @@ struct batadv_ogm2_packet { ++ * @elp_interval: currently used ELP sending interval in ms ++ */ ++ struct batadv_elp_packet { ++- u8 packet_type; ++- u8 version; ++- u8 orig[ETH_ALEN]; +++ __u8 packet_type; +++ __u8 version; +++ __u8 orig[ETH_ALEN]; ++ __be32 seqno; ++ __be32 elp_interval; ++ }; ++@@ -268,14 +268,14 @@ struct batadv_elp_packet { ++ * members are padded the same way as they are in real packets. ++ */ ++ struct batadv_icmp_header { ++- u8 packet_type; ++- u8 version; ++- u8 ttl; ++- u8 msg_type; /* see ICMP message types above */ ++- u8 dst[ETH_ALEN]; ++- u8 orig[ETH_ALEN]; ++- u8 uid; ++- u8 align[3]; +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 msg_type; /* see ICMP message types above */ +++ __u8 dst[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __u8 uid; +++ __u8 align[3]; ++ }; ++ ++ /** ++@@ -291,14 +291,14 @@ struct batadv_icmp_header { ++ * @seqno: ICMP sequence number ++ */ ++ struct batadv_icmp_packet { ++- u8 packet_type; ++- u8 version; ++- u8 ttl; ++- u8 msg_type; /* see ICMP message types above */ ++- u8 dst[ETH_ALEN]; ++- u8 orig[ETH_ALEN]; ++- u8 uid; ++- u8 reserved; +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 msg_type; /* see ICMP message types above */ +++ __u8 dst[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __u8 uid; +++ __u8 reserved; ++ __be16 seqno; ++ }; ++ ++@@ -320,15 +320,15 @@ struct batadv_icmp_packet { ++ * store it using network order ++ */ ++ struct batadv_icmp_tp_packet { ++- u8 packet_type; ++- u8 version; ++- u8 ttl; ++- u8 msg_type; /* see ICMP message types above */ ++- u8 dst[ETH_ALEN]; ++- u8 orig[ETH_ALEN]; ++- u8 uid; ++- u8 subtype; ++- u8 session[2]; +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 msg_type; /* see ICMP message types above */ +++ __u8 dst[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __u8 uid; +++ __u8 subtype; +++ __u8 session[2]; ++ __be32 seqno; ++ __be32 timestamp; ++ }; ++@@ -359,16 +359,16 @@ enum batadv_icmp_tp_subtype { ++ * @rr: route record array ++ */ ++ struct batadv_icmp_packet_rr { ++- u8 packet_type; ++- u8 version; ++- u8 ttl; ++- u8 msg_type; /* see ICMP message types above */ ++- u8 dst[ETH_ALEN]; ++- u8 orig[ETH_ALEN]; ++- u8 uid; ++- u8 rr_cur; +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 msg_type; /* see ICMP message types above */ +++ __u8 dst[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __u8 uid; +++ __u8 rr_cur; ++ __be16 seqno; ++- u8 rr[BATADV_RR_LEN][ETH_ALEN]; +++ __u8 rr[BATADV_RR_LEN][ETH_ALEN]; ++ }; ++ ++ #define BATADV_ICMP_MAX_PACKET_SIZE sizeof(struct batadv_icmp_packet_rr) ++@@ -394,11 +394,11 @@ struct batadv_icmp_packet_rr { ++ * @dest: originator destination of the unicast packet ++ */ ++ struct batadv_unicast_packet { ++- u8 packet_type; ++- u8 version; ++- u8 ttl; ++- u8 ttvn; /* destination translation table version number */ ++- u8 dest[ETH_ALEN]; +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 ttvn; /* destination translation table version number */ +++ __u8 dest[ETH_ALEN]; ++ /* "4 bytes boundary + 2 bytes" long to make the payload after the ++ * following ethernet header again 4 bytes boundary aligned ++ */ ++@@ -413,9 +413,9 @@ struct batadv_unicast_packet { ++ */ ++ struct batadv_unicast_4addr_packet { ++ struct batadv_unicast_packet u; ++- u8 src[ETH_ALEN]; ++- u8 subtype; ++- u8 reserved; +++ __u8 src[ETH_ALEN]; +++ __u8 subtype; +++ __u8 reserved; ++ /* "4 bytes boundary + 2 bytes" long to make the payload after the ++ * following ethernet header again 4 bytes boundary aligned ++ */ ++@@ -435,22 +435,22 @@ struct batadv_unicast_4addr_packet { ++ * @total_size: size of the merged packet ++ */ ++ struct batadv_frag_packet { ++- u8 packet_type; ++- u8 version; /* batman version field */ ++- u8 ttl; +++ __u8 packet_type; +++ __u8 version; /* batman version field */ +++ __u8 ttl; ++ #if defined(__BIG_ENDIAN_BITFIELD) ++- u8 no:4; ++- u8 priority:3; ++- u8 reserved:1; +++ __u8 no:4; +++ __u8 priority:3; +++ __u8 reserved:1; ++ #elif defined(__LITTLE_ENDIAN_BITFIELD) ++- u8 reserved:1; ++- u8 priority:3; ++- u8 no:4; +++ __u8 reserved:1; +++ __u8 priority:3; +++ __u8 no:4; ++ #else ++ #error "unknown bitfield endianness" ++ #endif ++- u8 dest[ETH_ALEN]; ++- u8 orig[ETH_ALEN]; +++ __u8 dest[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; ++ __be16 seqno; ++ __be16 total_size; ++ }; ++@@ -465,12 +465,12 @@ struct batadv_frag_packet { ++ * @orig: originator of the broadcast packet ++ */ ++ struct batadv_bcast_packet { ++- u8 packet_type; ++- u8 version; /* batman version field */ ++- u8 ttl; ++- u8 reserved; +++ __u8 packet_type; +++ __u8 version; /* batman version field */ +++ __u8 ttl; +++ __u8 reserved; ++ __be32 seqno; ++- u8 orig[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; ++ /* "4 bytes boundary + 2 bytes" long to make the payload after the ++ * following ethernet header again 4 bytes boundary aligned ++ */ ++@@ -494,19 +494,19 @@ struct batadv_bcast_packet { ++ * @coded_len: length of network coded part of the payload ++ */ ++ struct batadv_coded_packet { ++- u8 packet_type; ++- u8 version; /* batman version field */ ++- u8 ttl; ++- u8 first_ttvn; ++- /* u8 first_dest[ETH_ALEN]; - saved in mac header destination */ ++- u8 first_source[ETH_ALEN]; ++- u8 first_orig_dest[ETH_ALEN]; +++ __u8 packet_type; +++ __u8 version; /* batman version field */ +++ __u8 ttl; +++ __u8 first_ttvn; +++ /* __u8 first_dest[ETH_ALEN]; - saved in mac header destination */ +++ __u8 first_source[ETH_ALEN]; +++ __u8 first_orig_dest[ETH_ALEN]; ++ __be32 first_crc; ++- u8 second_ttl; ++- u8 second_ttvn; ++- u8 second_dest[ETH_ALEN]; ++- u8 second_source[ETH_ALEN]; ++- u8 second_orig_dest[ETH_ALEN]; +++ __u8 second_ttl; +++ __u8 second_ttvn; +++ __u8 second_dest[ETH_ALEN]; +++ __u8 second_source[ETH_ALEN]; +++ __u8 second_orig_dest[ETH_ALEN]; ++ __be32 second_crc; ++ __be16 coded_len; ++ }; ++@@ -525,14 +525,14 @@ struct batadv_coded_packet { ++ * @align: 2 bytes to align the header to a 4 byte boundary ++ */ ++ struct batadv_unicast_tvlv_packet { ++- u8 packet_type; ++- u8 version; /* batman version field */ ++- u8 ttl; ++- u8 reserved; ++- u8 dst[ETH_ALEN]; ++- u8 src[ETH_ALEN]; +++ __u8 packet_type; +++ __u8 version; /* batman version field */ +++ __u8 ttl; +++ __u8 reserved; +++ __u8 dst[ETH_ALEN]; +++ __u8 src[ETH_ALEN]; ++ __be16 tvlv_len; ++- u16 align; +++ __u16 align; ++ }; ++ ++ /** ++@@ -542,8 +542,8 @@ struct batadv_unicast_tvlv_packet { ++ * @len: tvlv container length ++ */ ++ struct batadv_tvlv_hdr { ++- u8 type; ++- u8 version; +++ __u8 type; +++ __u8 version; ++ __be16 len; ++ }; ++ ++@@ -566,8 +566,8 @@ struct batadv_tvlv_gateway_data { ++ * one batadv_tvlv_tt_vlan_data object per announced vlan ++ */ ++ struct batadv_tvlv_tt_data { ++- u8 flags; ++- u8 ttvn; +++ __u8 flags; +++ __u8 ttvn; ++ __be16 num_vlan; ++ }; ++ ++@@ -581,7 +581,7 @@ struct batadv_tvlv_tt_data { ++ struct batadv_tvlv_tt_vlan_data { ++ __be32 crc; ++ __be16 vid; ++- u16 reserved; +++ __u16 reserved; ++ }; ++ ++ /** ++@@ -593,9 +593,9 @@ struct batadv_tvlv_tt_vlan_data { ++ * @vid: VLAN identifier ++ */ ++ struct batadv_tvlv_tt_change { ++- u8 flags; ++- u8 reserved[3]; ++- u8 addr[ETH_ALEN]; +++ __u8 flags; +++ __u8 reserved[3]; +++ __u8 addr[ETH_ALEN]; ++ __be16 vid; ++ }; ++ ++@@ -605,7 +605,7 @@ struct batadv_tvlv_tt_change { ++ * @vid: VLAN identifier ++ */ ++ struct batadv_tvlv_roam_adv { ++- u8 client[ETH_ALEN]; +++ __u8 client[ETH_ALEN]; ++ __be16 vid; ++ }; ++ ++@@ -615,8 +615,8 @@ struct batadv_tvlv_roam_adv { ++ * @reserved: reserved field ++ */ ++ struct batadv_tvlv_mcast_data { ++- u8 flags; ++- u8 reserved[3]; +++ __u8 flags; +++ __u8 reserved[3]; ++ }; ++ ++ #endif /* _NET_BATMAN_ADV_PACKET_H_ */ +diff --git a/target/linux/generic/backport-4.14/273-batman-adv-Convert-packet.h-to-uapi-header.patch b/target/linux/generic/backport-4.14/273-batman-adv-Convert-packet.h-to-uapi-header.patch +new file mode 100644 +index 0000000000..a9f744fd13 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/273-batman-adv-Convert-packet.h-to-uapi-header.patch +@@ -0,0 +1,1665 @@ ++From: Sven Eckelmann ++Date: Thu, 21 Dec 2017 10:17:41 +0100 ++Subject: [PATCH] batman-adv: Convert packet.h to uapi header ++ ++The header file is used by different userspace programs to inject packets ++or to decode sniffed packets. It should therefore be available to them as ++userspace header. ++ ++Also other components in the kernel (like the flow dissector) require ++access to the packet definitions to be able to decode ETH_P_BATMAN ethernet ++packets. ++ ++Signed-off-by: Sven Eckelmann ++Signed-off-by: David S. Miller ++--- ++ rename net/batman-adv/packet.h => include/uapi/linux/batadv_packet.h (99%) ++ ++--- a/MAINTAINERS +++++ b/MAINTAINERS ++@@ -2551,6 +2551,7 @@ S: Maintained ++ F: Documentation/ABI/testing/sysfs-class-net-batman-adv ++ F: Documentation/ABI/testing/sysfs-class-net-mesh ++ F: Documentation/networking/batman-adv.rst +++F: include/uapi/linux/batadv_packet.h ++ F: include/uapi/linux/batman_adv.h ++ F: net/batman-adv/ ++ ++--- a/net/batman-adv/bat_iv_ogm.c +++++ b/net/batman-adv/bat_iv_ogm.c ++@@ -52,6 +52,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #include "bat_algo.h" ++@@ -63,7 +64,6 @@ ++ #include "netlink.h" ++ #include "network-coding.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "routing.h" ++ #include "send.h" ++ #include "translation-table.h" ++--- a/net/batman-adv/bat_v.c +++++ b/net/batman-adv/bat_v.c ++@@ -36,6 +36,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #include "bat_algo.h" ++@@ -48,7 +49,6 @@ ++ #include "log.h" ++ #include "netlink.h" ++ #include "originator.h" ++-#include "packet.h" ++ ++ struct sk_buff; ++ ++--- a/net/batman-adv/bat_v_elp.c +++++ b/net/batman-adv/bat_v_elp.c ++@@ -41,13 +41,13 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "bat_algo.h" ++ #include "bat_v_ogm.h" ++ #include "hard-interface.h" ++ #include "log.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "routing.h" ++ #include "send.h" ++ ++--- a/net/batman-adv/bat_v_ogm.c +++++ b/net/batman-adv/bat_v_ogm.c ++@@ -40,13 +40,13 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "bat_algo.h" ++ #include "hard-interface.h" ++ #include "hash.h" ++ #include "log.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "routing.h" ++ #include "send.h" ++ #include "translation-table.h" ++--- a/net/batman-adv/bridge_loop_avoidance.c +++++ b/net/batman-adv/bridge_loop_avoidance.c ++@@ -49,6 +49,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #include "hard-interface.h" ++@@ -56,7 +57,6 @@ ++ #include "log.h" ++ #include "netlink.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "soft-interface.h" ++ #include "sysfs.h" ++ #include "translation-table.h" ++--- a/net/batman-adv/distributed-arp-table.h +++++ b/net/batman-adv/distributed-arp-table.h ++@@ -23,9 +23,9 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "originator.h" ++-#include "packet.h" ++ ++ struct seq_file; ++ struct sk_buff; ++--- a/net/batman-adv/fragmentation.c +++++ b/net/batman-adv/fragmentation.c ++@@ -32,10 +32,10 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "hard-interface.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "routing.h" ++ #include "send.h" ++ #include "soft-interface.h" ++--- a/net/batman-adv/gateway_client.c +++++ b/net/batman-adv/gateway_client.c ++@@ -43,6 +43,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #include "gateway_common.h" ++@@ -50,7 +51,6 @@ ++ #include "log.h" ++ #include "netlink.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "routing.h" ++ #include "soft-interface.h" ++ #include "sysfs.h" ++--- a/net/batman-adv/gateway_common.c +++++ b/net/batman-adv/gateway_common.c ++@@ -26,10 +26,10 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "gateway_client.h" ++ #include "log.h" ++-#include "packet.h" ++ #include "tvlv.h" ++ ++ /** ++--- a/net/batman-adv/hard-interface.c +++++ b/net/batman-adv/hard-interface.c ++@@ -37,6 +37,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "bat_v.h" ++ #include "bridge_loop_avoidance.h" ++@@ -45,7 +46,6 @@ ++ #include "gateway_client.h" ++ #include "log.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "send.h" ++ #include "soft-interface.h" ++ #include "sysfs.h" ++--- a/net/batman-adv/icmp_socket.c +++++ b/net/batman-adv/icmp_socket.c ++@@ -42,11 +42,11 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "hard-interface.h" ++ #include "log.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "send.h" ++ ++ static struct batadv_socket_client *batadv_socket_client_hash[256]; ++--- a/net/batman-adv/main.c +++++ b/net/batman-adv/main.c ++@@ -45,6 +45,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #include "bat_algo.h" ++@@ -62,7 +63,6 @@ ++ #include "netlink.h" ++ #include "network-coding.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "routing.h" ++ #include "send.h" ++ #include "soft-interface.h" ++--- a/net/batman-adv/main.h +++++ b/net/batman-adv/main.h ++@@ -190,8 +190,8 @@ enum batadv_uev_type { ++ #include ++ #include ++ #include +++#include ++ ++-#include "packet.h" ++ #include "types.h" ++ ++ struct net_device; ++--- a/net/batman-adv/multicast.c +++++ b/net/batman-adv/multicast.c ++@@ -54,11 +54,11 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "hard-interface.h" ++ #include "hash.h" ++ #include "log.h" ++-#include "packet.h" ++ #include "translation-table.h" ++ #include "tvlv.h" ++ ++--- a/net/batman-adv/netlink.c +++++ b/net/batman-adv/netlink.c ++@@ -39,6 +39,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #include "bat_algo.h" ++@@ -46,7 +47,6 @@ ++ #include "gateway_client.h" ++ #include "hard-interface.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "soft-interface.h" ++ #include "tp_meter.h" ++ #include "translation-table.h" ++--- a/net/batman-adv/network-coding.c +++++ b/net/batman-adv/network-coding.c ++@@ -47,12 +47,12 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "hard-interface.h" ++ #include "hash.h" ++ #include "log.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "routing.h" ++ #include "send.h" ++ #include "tvlv.h" ++--- a/net/batman-adv/packet.h +++++ /dev/null ++@@ -1,622 +0,0 @@ ++-/* Copyright (C) 2007-2017 B.A.T.M.A.N. contributors: ++- * ++- * Marek Lindner, Simon Wunderlich ++- * ++- * This program is free software; you can redistribute it and/or ++- * modify it under the terms of version 2 of the GNU General Public ++- * License 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. ++- * ++- * You should have received a copy of the GNU General Public License ++- * along with this program; if not, see . ++- */ ++- ++-#ifndef _NET_BATMAN_ADV_PACKET_H_ ++-#define _NET_BATMAN_ADV_PACKET_H_ ++- ++-#include ++-#include ++-#include ++- ++-#define batadv_tp_is_error(n) ((__u8)(n) > 127 ? 1 : 0) ++- ++-/** ++- * enum batadv_packettype - types for batman-adv encapsulated packets ++- * @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV ++- * @BATADV_BCAST: broadcast packets carrying broadcast payload ++- * @BATADV_CODED: network coded packets ++- * @BATADV_ELP: echo location packets for B.A.T.M.A.N. V ++- * @BATADV_OGM2: originator messages for B.A.T.M.A.N. V ++- * ++- * @BATADV_UNICAST: unicast packets carrying unicast payload traffic ++- * @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original ++- * payload packet ++- * @BATADV_UNICAST_4ADDR: unicast packet including the originator address of ++- * the sender ++- * @BATADV_ICMP: unicast packet like IP ICMP used for ping or traceroute ++- * @BATADV_UNICAST_TVLV: unicast packet carrying TVLV containers ++- */ ++-enum batadv_packettype { ++- /* 0x00 - 0x3f: local packets or special rules for handling */ ++- BATADV_IV_OGM = 0x00, ++- BATADV_BCAST = 0x01, ++- BATADV_CODED = 0x02, ++- BATADV_ELP = 0x03, ++- BATADV_OGM2 = 0x04, ++- /* 0x40 - 0x7f: unicast */ ++-#define BATADV_UNICAST_MIN 0x40 ++- BATADV_UNICAST = 0x40, ++- BATADV_UNICAST_FRAG = 0x41, ++- BATADV_UNICAST_4ADDR = 0x42, ++- BATADV_ICMP = 0x43, ++- BATADV_UNICAST_TVLV = 0x44, ++-#define BATADV_UNICAST_MAX 0x7f ++- /* 0x80 - 0xff: reserved */ ++-}; ++- ++-/** ++- * enum batadv_subtype - packet subtype for unicast4addr ++- * @BATADV_P_DATA: user payload ++- * @BATADV_P_DAT_DHT_GET: DHT request message ++- * @BATADV_P_DAT_DHT_PUT: DHT store message ++- * @BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT ++- */ ++-enum batadv_subtype { ++- BATADV_P_DATA = 0x01, ++- BATADV_P_DAT_DHT_GET = 0x02, ++- BATADV_P_DAT_DHT_PUT = 0x03, ++- BATADV_P_DAT_CACHE_REPLY = 0x04, ++-}; ++- ++-/* this file is included by batctl which needs these defines */ ++-#define BATADV_COMPAT_VERSION 15 ++- ++-/** ++- * enum batadv_iv_flags - flags used in B.A.T.M.A.N. IV OGM packets ++- * @BATADV_NOT_BEST_NEXT_HOP: flag is set when ogm packet is forwarded and was ++- * previously received from someone else than the best neighbor. ++- * @BATADV_PRIMARIES_FIRST_HOP: flag unused. ++- * @BATADV_DIRECTLINK: flag is for the first hop or if rebroadcasted from a ++- * one hop neighbor on the interface where it was originally received. ++- */ ++-enum batadv_iv_flags { ++- BATADV_NOT_BEST_NEXT_HOP = 1UL << 0, ++- BATADV_PRIMARIES_FIRST_HOP = 1UL << 1, ++- BATADV_DIRECTLINK = 1UL << 2, ++-}; ++- ++-/* ICMP message types */ ++-enum batadv_icmp_packettype { ++- BATADV_ECHO_REPLY = 0, ++- BATADV_DESTINATION_UNREACHABLE = 3, ++- BATADV_ECHO_REQUEST = 8, ++- BATADV_TTL_EXCEEDED = 11, ++- BATADV_PARAMETER_PROBLEM = 12, ++- BATADV_TP = 15, ++-}; ++- ++-/** ++- * enum batadv_mcast_flags - flags for multicast capabilities and settings ++- * @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for ++- * 224.0.0.0/24 or ff02::1 ++- * @BATADV_MCAST_WANT_ALL_IPV4: we want all IPv4 multicast packets ++- * @BATADV_MCAST_WANT_ALL_IPV6: we want all IPv6 multicast packets ++- */ ++-enum batadv_mcast_flags { ++- BATADV_MCAST_WANT_ALL_UNSNOOPABLES = 1UL << 0, ++- BATADV_MCAST_WANT_ALL_IPV4 = 1UL << 1, ++- BATADV_MCAST_WANT_ALL_IPV6 = 1UL << 2, ++-}; ++- ++-/* tt data subtypes */ ++-#define BATADV_TT_DATA_TYPE_MASK 0x0F ++- ++-/** ++- * enum batadv_tt_data_flags - flags for tt data tvlv ++- * @BATADV_TT_OGM_DIFF: TT diff propagated through OGM ++- * @BATADV_TT_REQUEST: TT request message ++- * @BATADV_TT_RESPONSE: TT response message ++- * @BATADV_TT_FULL_TABLE: contains full table to replace existing table ++- */ ++-enum batadv_tt_data_flags { ++- BATADV_TT_OGM_DIFF = 1UL << 0, ++- BATADV_TT_REQUEST = 1UL << 1, ++- BATADV_TT_RESPONSE = 1UL << 2, ++- BATADV_TT_FULL_TABLE = 1UL << 4, ++-}; ++- ++-/** ++- * enum batadv_vlan_flags - flags for the four MSB of any vlan ID field ++- * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not ++- */ ++-enum batadv_vlan_flags { ++- BATADV_VLAN_HAS_TAG = 1UL << 15, ++-}; ++- ++-/* claim frame types for the bridge loop avoidance */ ++-enum batadv_bla_claimframe { ++- BATADV_CLAIM_TYPE_CLAIM = 0x00, ++- BATADV_CLAIM_TYPE_UNCLAIM = 0x01, ++- BATADV_CLAIM_TYPE_ANNOUNCE = 0x02, ++- BATADV_CLAIM_TYPE_REQUEST = 0x03, ++- BATADV_CLAIM_TYPE_LOOPDETECT = 0x04, ++-}; ++- ++-/** ++- * enum batadv_tvlv_type - tvlv type definitions ++- * @BATADV_TVLV_GW: gateway tvlv ++- * @BATADV_TVLV_DAT: distributed arp table tvlv ++- * @BATADV_TVLV_NC: network coding tvlv ++- * @BATADV_TVLV_TT: translation table tvlv ++- * @BATADV_TVLV_ROAM: roaming advertisement tvlv ++- * @BATADV_TVLV_MCAST: multicast capability tvlv ++- */ ++-enum batadv_tvlv_type { ++- BATADV_TVLV_GW = 0x01, ++- BATADV_TVLV_DAT = 0x02, ++- BATADV_TVLV_NC = 0x03, ++- BATADV_TVLV_TT = 0x04, ++- BATADV_TVLV_ROAM = 0x05, ++- BATADV_TVLV_MCAST = 0x06, ++-}; ++- ++-#pragma pack(2) ++-/* the destination hardware field in the ARP frame is used to ++- * transport the claim type and the group id ++- */ ++-struct batadv_bla_claim_dst { ++- __u8 magic[3]; /* FF:43:05 */ ++- __u8 type; /* bla_claimframe */ ++- __be16 group; /* group id */ ++-}; ++- ++-#pragma pack() ++- ++-/** ++- * struct batadv_ogm_packet - ogm (routing protocol) packet ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @flags: contains routing relevant flags - see enum batadv_iv_flags ++- * @seqno: sequence identification ++- * @orig: address of the source node ++- * @prev_sender: address of the previous sender ++- * @reserved: reserved byte for alignment ++- * @tq: transmission quality ++- * @tvlv_len: length of tvlv data following the ogm header ++- */ ++-struct batadv_ogm_packet { ++- __u8 packet_type; ++- __u8 version; ++- __u8 ttl; ++- __u8 flags; ++- __be32 seqno; ++- __u8 orig[ETH_ALEN]; ++- __u8 prev_sender[ETH_ALEN]; ++- __u8 reserved; ++- __u8 tq; ++- __be16 tvlv_len; ++- /* __packed is not needed as the struct size is divisible by 4, ++- * and the largest data type in this struct has a size of 4. ++- */ ++-}; ++- ++-#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) ++- ++-/** ++- * struct batadv_ogm2_packet - ogm2 (routing protocol) packet ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the general header ++- * @ttl: time to live for this packet, part of the general header ++- * @flags: reseved for routing relevant flags - currently always 0 ++- * @seqno: sequence number ++- * @orig: originator mac address ++- * @tvlv_len: length of the appended tvlv buffer (in bytes) ++- * @throughput: the currently flooded path throughput ++- */ ++-struct batadv_ogm2_packet { ++- __u8 packet_type; ++- __u8 version; ++- __u8 ttl; ++- __u8 flags; ++- __be32 seqno; ++- __u8 orig[ETH_ALEN]; ++- __be16 tvlv_len; ++- __be32 throughput; ++- /* __packed is not needed as the struct size is divisible by 4, ++- * and the largest data type in this struct has a size of 4. ++- */ ++-}; ++- ++-#define BATADV_OGM2_HLEN sizeof(struct batadv_ogm2_packet) ++- ++-/** ++- * struct batadv_elp_packet - elp (neighbor discovery) packet ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @orig: originator mac address ++- * @seqno: sequence number ++- * @elp_interval: currently used ELP sending interval in ms ++- */ ++-struct batadv_elp_packet { ++- __u8 packet_type; ++- __u8 version; ++- __u8 orig[ETH_ALEN]; ++- __be32 seqno; ++- __be32 elp_interval; ++-}; ++- ++-#define BATADV_ELP_HLEN sizeof(struct batadv_elp_packet) ++- ++-/** ++- * struct batadv_icmp_header - common members among all the ICMP packets ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @msg_type: ICMP packet type ++- * @dst: address of the destination node ++- * @orig: address of the source node ++- * @uid: local ICMP socket identifier ++- * @align: not used - useful for alignment purposes only ++- * ++- * This structure is used for ICMP packets parsing only and it is never sent ++- * over the wire. The alignment field at the end is there to ensure that ++- * members are padded the same way as they are in real packets. ++- */ ++-struct batadv_icmp_header { ++- __u8 packet_type; ++- __u8 version; ++- __u8 ttl; ++- __u8 msg_type; /* see ICMP message types above */ ++- __u8 dst[ETH_ALEN]; ++- __u8 orig[ETH_ALEN]; ++- __u8 uid; ++- __u8 align[3]; ++-}; ++- ++-/** ++- * struct batadv_icmp_packet - ICMP packet ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @msg_type: ICMP packet type ++- * @dst: address of the destination node ++- * @orig: address of the source node ++- * @uid: local ICMP socket identifier ++- * @reserved: not used - useful for alignment ++- * @seqno: ICMP sequence number ++- */ ++-struct batadv_icmp_packet { ++- __u8 packet_type; ++- __u8 version; ++- __u8 ttl; ++- __u8 msg_type; /* see ICMP message types above */ ++- __u8 dst[ETH_ALEN]; ++- __u8 orig[ETH_ALEN]; ++- __u8 uid; ++- __u8 reserved; ++- __be16 seqno; ++-}; ++- ++-/** ++- * struct batadv_icmp_tp_packet - ICMP TP Meter packet ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @msg_type: ICMP packet type ++- * @dst: address of the destination node ++- * @orig: address of the source node ++- * @uid: local ICMP socket identifier ++- * @subtype: TP packet subtype (see batadv_icmp_tp_subtype) ++- * @session: TP session identifier ++- * @seqno: the TP sequence number ++- * @timestamp: time when the packet has been sent. This value is filled in a ++- * TP_MSG and echoed back in the next TP_ACK so that the sender can compute the ++- * RTT. Since it is read only by the host which wrote it, there is no need to ++- * store it using network order ++- */ ++-struct batadv_icmp_tp_packet { ++- __u8 packet_type; ++- __u8 version; ++- __u8 ttl; ++- __u8 msg_type; /* see ICMP message types above */ ++- __u8 dst[ETH_ALEN]; ++- __u8 orig[ETH_ALEN]; ++- __u8 uid; ++- __u8 subtype; ++- __u8 session[2]; ++- __be32 seqno; ++- __be32 timestamp; ++-}; ++- ++-/** ++- * enum batadv_icmp_tp_subtype - ICMP TP Meter packet subtypes ++- * @BATADV_TP_MSG: Msg from sender to receiver ++- * @BATADV_TP_ACK: acknowledgment from receiver to sender ++- */ ++-enum batadv_icmp_tp_subtype { ++- BATADV_TP_MSG = 0, ++- BATADV_TP_ACK, ++-}; ++- ++-#define BATADV_RR_LEN 16 ++- ++-/** ++- * struct batadv_icmp_packet_rr - ICMP RouteRecord packet ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @msg_type: ICMP packet type ++- * @dst: address of the destination node ++- * @orig: address of the source node ++- * @uid: local ICMP socket identifier ++- * @rr_cur: number of entries the rr array ++- * @seqno: ICMP sequence number ++- * @rr: route record array ++- */ ++-struct batadv_icmp_packet_rr { ++- __u8 packet_type; ++- __u8 version; ++- __u8 ttl; ++- __u8 msg_type; /* see ICMP message types above */ ++- __u8 dst[ETH_ALEN]; ++- __u8 orig[ETH_ALEN]; ++- __u8 uid; ++- __u8 rr_cur; ++- __be16 seqno; ++- __u8 rr[BATADV_RR_LEN][ETH_ALEN]; ++-}; ++- ++-#define BATADV_ICMP_MAX_PACKET_SIZE sizeof(struct batadv_icmp_packet_rr) ++- ++-/* All packet headers in front of an ethernet header have to be completely ++- * divisible by 2 but not by 4 to make the payload after the ethernet ++- * header again 4 bytes boundary aligned. ++- * ++- * A packing of 2 is necessary to avoid extra padding at the end of the struct ++- * caused by a structure member which is larger than two bytes. Otherwise ++- * the structure would not fulfill the previously mentioned rule to avoid the ++- * misalignment of the payload after the ethernet header. It may also lead to ++- * leakage of information when the padding it not initialized before sending. ++- */ ++-#pragma pack(2) ++- ++-/** ++- * struct batadv_unicast_packet - unicast packet for network payload ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @ttvn: translation table version number ++- * @dest: originator destination of the unicast packet ++- */ ++-struct batadv_unicast_packet { ++- __u8 packet_type; ++- __u8 version; ++- __u8 ttl; ++- __u8 ttvn; /* destination translation table version number */ ++- __u8 dest[ETH_ALEN]; ++- /* "4 bytes boundary + 2 bytes" long to make the payload after the ++- * following ethernet header again 4 bytes boundary aligned ++- */ ++-}; ++- ++-/** ++- * struct batadv_unicast_4addr_packet - extended unicast packet ++- * @u: common unicast packet header ++- * @src: address of the source ++- * @subtype: packet subtype ++- * @reserved: reserved byte for alignment ++- */ ++-struct batadv_unicast_4addr_packet { ++- struct batadv_unicast_packet u; ++- __u8 src[ETH_ALEN]; ++- __u8 subtype; ++- __u8 reserved; ++- /* "4 bytes boundary + 2 bytes" long to make the payload after the ++- * following ethernet header again 4 bytes boundary aligned ++- */ ++-}; ++- ++-/** ++- * struct batadv_frag_packet - fragmented packet ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @dest: final destination used when routing fragments ++- * @orig: originator of the fragment used when merging the packet ++- * @no: fragment number within this sequence ++- * @priority: priority of frame, from ToS IP precedence or 802.1p ++- * @reserved: reserved byte for alignment ++- * @seqno: sequence identification ++- * @total_size: size of the merged packet ++- */ ++-struct batadv_frag_packet { ++- __u8 packet_type; ++- __u8 version; /* batman version field */ ++- __u8 ttl; ++-#if defined(__BIG_ENDIAN_BITFIELD) ++- __u8 no:4; ++- __u8 priority:3; ++- __u8 reserved:1; ++-#elif defined(__LITTLE_ENDIAN_BITFIELD) ++- __u8 reserved:1; ++- __u8 priority:3; ++- __u8 no:4; ++-#else ++-#error "unknown bitfield endianness" ++-#endif ++- __u8 dest[ETH_ALEN]; ++- __u8 orig[ETH_ALEN]; ++- __be16 seqno; ++- __be16 total_size; ++-}; ++- ++-/** ++- * struct batadv_bcast_packet - broadcast packet for network payload ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @reserved: reserved byte for alignment ++- * @seqno: sequence identification ++- * @orig: originator of the broadcast packet ++- */ ++-struct batadv_bcast_packet { ++- __u8 packet_type; ++- __u8 version; /* batman version field */ ++- __u8 ttl; ++- __u8 reserved; ++- __be32 seqno; ++- __u8 orig[ETH_ALEN]; ++- /* "4 bytes boundary + 2 bytes" long to make the payload after the ++- * following ethernet header again 4 bytes boundary aligned ++- */ ++-}; ++- ++-/** ++- * struct batadv_coded_packet - network coded packet ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @first_source: original source of first included packet ++- * @first_orig_dest: original destinal of first included packet ++- * @first_crc: checksum of first included packet ++- * @first_ttvn: tt-version number of first included packet ++- * @second_ttl: ttl of second packet ++- * @second_dest: second receiver of this coded packet ++- * @second_source: original source of second included packet ++- * @second_orig_dest: original destination of second included packet ++- * @second_crc: checksum of second included packet ++- * @second_ttvn: tt version number of second included packet ++- * @coded_len: length of network coded part of the payload ++- */ ++-struct batadv_coded_packet { ++- __u8 packet_type; ++- __u8 version; /* batman version field */ ++- __u8 ttl; ++- __u8 first_ttvn; ++- /* __u8 first_dest[ETH_ALEN]; - saved in mac header destination */ ++- __u8 first_source[ETH_ALEN]; ++- __u8 first_orig_dest[ETH_ALEN]; ++- __be32 first_crc; ++- __u8 second_ttl; ++- __u8 second_ttvn; ++- __u8 second_dest[ETH_ALEN]; ++- __u8 second_source[ETH_ALEN]; ++- __u8 second_orig_dest[ETH_ALEN]; ++- __be32 second_crc; ++- __be16 coded_len; ++-}; ++- ++-#pragma pack() ++- ++-/** ++- * struct batadv_unicast_tvlv_packet - generic unicast packet with tvlv payload ++- * @packet_type: batman-adv packet type, part of the general header ++- * @version: batman-adv protocol version, part of the genereal header ++- * @ttl: time to live for this packet, part of the genereal header ++- * @reserved: reserved field (for packet alignment) ++- * @src: address of the source ++- * @dst: address of the destination ++- * @tvlv_len: length of tvlv data following the unicast tvlv header ++- * @align: 2 bytes to align the header to a 4 byte boundary ++- */ ++-struct batadv_unicast_tvlv_packet { ++- __u8 packet_type; ++- __u8 version; /* batman version field */ ++- __u8 ttl; ++- __u8 reserved; ++- __u8 dst[ETH_ALEN]; ++- __u8 src[ETH_ALEN]; ++- __be16 tvlv_len; ++- __u16 align; ++-}; ++- ++-/** ++- * struct batadv_tvlv_hdr - base tvlv header struct ++- * @type: tvlv container type (see batadv_tvlv_type) ++- * @version: tvlv container version ++- * @len: tvlv container length ++- */ ++-struct batadv_tvlv_hdr { ++- __u8 type; ++- __u8 version; ++- __be16 len; ++-}; ++- ++-/** ++- * struct batadv_tvlv_gateway_data - gateway data propagated through gw tvlv ++- * container ++- * @bandwidth_down: advertised uplink download bandwidth ++- * @bandwidth_up: advertised uplink upload bandwidth ++- */ ++-struct batadv_tvlv_gateway_data { ++- __be32 bandwidth_down; ++- __be32 bandwidth_up; ++-}; ++- ++-/** ++- * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container ++- * @flags: translation table flags (see batadv_tt_data_flags) ++- * @ttvn: translation table version number ++- * @num_vlan: number of announced VLANs. In the TVLV this struct is followed by ++- * one batadv_tvlv_tt_vlan_data object per announced vlan ++- */ ++-struct batadv_tvlv_tt_data { ++- __u8 flags; ++- __u8 ttvn; ++- __be16 num_vlan; ++-}; ++- ++-/** ++- * struct batadv_tvlv_tt_vlan_data - vlan specific tt data propagated through ++- * the tt tvlv container ++- * @crc: crc32 checksum of the entries belonging to this vlan ++- * @vid: vlan identifier ++- * @reserved: unused, useful for alignment purposes ++- */ ++-struct batadv_tvlv_tt_vlan_data { ++- __be32 crc; ++- __be16 vid; ++- __u16 reserved; ++-}; ++- ++-/** ++- * struct batadv_tvlv_tt_change - translation table diff data ++- * @flags: status indicators concerning the non-mesh client (see ++- * batadv_tt_client_flags) ++- * @reserved: reserved field - useful for alignment purposes only ++- * @addr: mac address of non-mesh client that triggered this tt change ++- * @vid: VLAN identifier ++- */ ++-struct batadv_tvlv_tt_change { ++- __u8 flags; ++- __u8 reserved[3]; ++- __u8 addr[ETH_ALEN]; ++- __be16 vid; ++-}; ++- ++-/** ++- * struct batadv_tvlv_roam_adv - roaming advertisement ++- * @client: mac address of roaming client ++- * @vid: VLAN identifier ++- */ ++-struct batadv_tvlv_roam_adv { ++- __u8 client[ETH_ALEN]; ++- __be16 vid; ++-}; ++- ++-/** ++- * struct batadv_tvlv_mcast_data - payload of a multicast tvlv ++- * @flags: multicast flags announced by the orig node ++- * @reserved: reserved field ++- */ ++-struct batadv_tvlv_mcast_data { ++- __u8 flags; ++- __u8 reserved[3]; ++-}; ++- ++-#endif /* _NET_BATMAN_ADV_PACKET_H_ */ ++--- a/net/batman-adv/routing.c +++++ b/net/batman-adv/routing.c ++@@ -33,6 +33,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "bitarray.h" ++ #include "bridge_loop_avoidance.h" ++@@ -43,7 +44,6 @@ ++ #include "log.h" ++ #include "network-coding.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "send.h" ++ #include "soft-interface.h" ++ #include "tp_meter.h" ++--- a/net/batman-adv/send.h +++++ b/net/batman-adv/send.h ++@@ -23,8 +23,7 @@ ++ #include ++ #include ++ #include ++- ++-#include "packet.h" +++#include ++ ++ struct sk_buff; ++ ++--- a/net/batman-adv/soft-interface.c +++++ b/net/batman-adv/soft-interface.c ++@@ -48,6 +48,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "bat_algo.h" ++ #include "bridge_loop_avoidance.h" ++@@ -59,7 +60,6 @@ ++ #include "multicast.h" ++ #include "network-coding.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "send.h" ++ #include "sysfs.h" ++ #include "translation-table.h" ++--- a/net/batman-adv/sysfs.c +++++ b/net/batman-adv/sysfs.c ++@@ -37,6 +37,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "bridge_loop_avoidance.h" ++ #include "distributed-arp-table.h" ++@@ -45,7 +46,6 @@ ++ #include "hard-interface.h" ++ #include "log.h" ++ #include "network-coding.h" ++-#include "packet.h" ++ #include "soft-interface.h" ++ ++ static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) ++--- a/net/batman-adv/tp_meter.c +++++ b/net/batman-adv/tp_meter.c ++@@ -48,13 +48,13 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #include "hard-interface.h" ++ #include "log.h" ++ #include "netlink.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "send.h" ++ ++ /** ++--- a/net/batman-adv/translation-table.c +++++ b/net/batman-adv/translation-table.c ++@@ -50,6 +50,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #include "bridge_loop_avoidance.h" ++@@ -58,7 +59,6 @@ ++ #include "log.h" ++ #include "netlink.h" ++ #include "originator.h" ++-#include "packet.h" ++ #include "soft-interface.h" ++ #include "tvlv.h" ++ ++--- a/net/batman-adv/tvlv.c +++++ b/net/batman-adv/tvlv.c ++@@ -35,9 +35,9 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "originator.h" ++-#include "packet.h" ++ #include "send.h" ++ #include "tvlv.h" ++ ++--- a/net/batman-adv/types.h +++++ b/net/batman-adv/types.h ++@@ -35,10 +35,9 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++-#include "packet.h" ++- ++ struct seq_file; ++ ++ #ifdef CONFIG_BATMAN_ADV_DAT ++--- /dev/null +++++ b/include/uapi/linux/batadv_packet.h ++@@ -0,0 +1,623 @@ +++/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) */ +++/* Copyright (C) 2007-2017 B.A.T.M.A.N. contributors: +++ * +++ * Marek Lindner, Simon Wunderlich +++ * +++ * This program is free software; you can redistribute it and/or +++ * modify it under the terms of version 2 of the GNU General Public +++ * License 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. +++ * +++ * You should have received a copy of the GNU General Public License +++ * along with this program; if not, see . +++ */ +++ +++#ifndef _UAPI_LINUX_BATADV_PACKET_H_ +++#define _UAPI_LINUX_BATADV_PACKET_H_ +++ +++#include +++#include +++#include +++ +++#define batadv_tp_is_error(n) ((__u8)(n) > 127 ? 1 : 0) +++ +++/** +++ * enum batadv_packettype - types for batman-adv encapsulated packets +++ * @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV +++ * @BATADV_BCAST: broadcast packets carrying broadcast payload +++ * @BATADV_CODED: network coded packets +++ * @BATADV_ELP: echo location packets for B.A.T.M.A.N. V +++ * @BATADV_OGM2: originator messages for B.A.T.M.A.N. V +++ * +++ * @BATADV_UNICAST: unicast packets carrying unicast payload traffic +++ * @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original +++ * payload packet +++ * @BATADV_UNICAST_4ADDR: unicast packet including the originator address of +++ * the sender +++ * @BATADV_ICMP: unicast packet like IP ICMP used for ping or traceroute +++ * @BATADV_UNICAST_TVLV: unicast packet carrying TVLV containers +++ */ +++enum batadv_packettype { +++ /* 0x00 - 0x3f: local packets or special rules for handling */ +++ BATADV_IV_OGM = 0x00, +++ BATADV_BCAST = 0x01, +++ BATADV_CODED = 0x02, +++ BATADV_ELP = 0x03, +++ BATADV_OGM2 = 0x04, +++ /* 0x40 - 0x7f: unicast */ +++#define BATADV_UNICAST_MIN 0x40 +++ BATADV_UNICAST = 0x40, +++ BATADV_UNICAST_FRAG = 0x41, +++ BATADV_UNICAST_4ADDR = 0x42, +++ BATADV_ICMP = 0x43, +++ BATADV_UNICAST_TVLV = 0x44, +++#define BATADV_UNICAST_MAX 0x7f +++ /* 0x80 - 0xff: reserved */ +++}; +++ +++/** +++ * enum batadv_subtype - packet subtype for unicast4addr +++ * @BATADV_P_DATA: user payload +++ * @BATADV_P_DAT_DHT_GET: DHT request message +++ * @BATADV_P_DAT_DHT_PUT: DHT store message +++ * @BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT +++ */ +++enum batadv_subtype { +++ BATADV_P_DATA = 0x01, +++ BATADV_P_DAT_DHT_GET = 0x02, +++ BATADV_P_DAT_DHT_PUT = 0x03, +++ BATADV_P_DAT_CACHE_REPLY = 0x04, +++}; +++ +++/* this file is included by batctl which needs these defines */ +++#define BATADV_COMPAT_VERSION 15 +++ +++/** +++ * enum batadv_iv_flags - flags used in B.A.T.M.A.N. IV OGM packets +++ * @BATADV_NOT_BEST_NEXT_HOP: flag is set when ogm packet is forwarded and was +++ * previously received from someone else than the best neighbor. +++ * @BATADV_PRIMARIES_FIRST_HOP: flag unused. +++ * @BATADV_DIRECTLINK: flag is for the first hop or if rebroadcasted from a +++ * one hop neighbor on the interface where it was originally received. +++ */ +++enum batadv_iv_flags { +++ BATADV_NOT_BEST_NEXT_HOP = 1UL << 0, +++ BATADV_PRIMARIES_FIRST_HOP = 1UL << 1, +++ BATADV_DIRECTLINK = 1UL << 2, +++}; +++ +++/* ICMP message types */ +++enum batadv_icmp_packettype { +++ BATADV_ECHO_REPLY = 0, +++ BATADV_DESTINATION_UNREACHABLE = 3, +++ BATADV_ECHO_REQUEST = 8, +++ BATADV_TTL_EXCEEDED = 11, +++ BATADV_PARAMETER_PROBLEM = 12, +++ BATADV_TP = 15, +++}; +++ +++/** +++ * enum batadv_mcast_flags - flags for multicast capabilities and settings +++ * @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for +++ * 224.0.0.0/24 or ff02::1 +++ * @BATADV_MCAST_WANT_ALL_IPV4: we want all IPv4 multicast packets +++ * @BATADV_MCAST_WANT_ALL_IPV6: we want all IPv6 multicast packets +++ */ +++enum batadv_mcast_flags { +++ BATADV_MCAST_WANT_ALL_UNSNOOPABLES = 1UL << 0, +++ BATADV_MCAST_WANT_ALL_IPV4 = 1UL << 1, +++ BATADV_MCAST_WANT_ALL_IPV6 = 1UL << 2, +++}; +++ +++/* tt data subtypes */ +++#define BATADV_TT_DATA_TYPE_MASK 0x0F +++ +++/** +++ * enum batadv_tt_data_flags - flags for tt data tvlv +++ * @BATADV_TT_OGM_DIFF: TT diff propagated through OGM +++ * @BATADV_TT_REQUEST: TT request message +++ * @BATADV_TT_RESPONSE: TT response message +++ * @BATADV_TT_FULL_TABLE: contains full table to replace existing table +++ */ +++enum batadv_tt_data_flags { +++ BATADV_TT_OGM_DIFF = 1UL << 0, +++ BATADV_TT_REQUEST = 1UL << 1, +++ BATADV_TT_RESPONSE = 1UL << 2, +++ BATADV_TT_FULL_TABLE = 1UL << 4, +++}; +++ +++/** +++ * enum batadv_vlan_flags - flags for the four MSB of any vlan ID field +++ * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not +++ */ +++enum batadv_vlan_flags { +++ BATADV_VLAN_HAS_TAG = 1UL << 15, +++}; +++ +++/* claim frame types for the bridge loop avoidance */ +++enum batadv_bla_claimframe { +++ BATADV_CLAIM_TYPE_CLAIM = 0x00, +++ BATADV_CLAIM_TYPE_UNCLAIM = 0x01, +++ BATADV_CLAIM_TYPE_ANNOUNCE = 0x02, +++ BATADV_CLAIM_TYPE_REQUEST = 0x03, +++ BATADV_CLAIM_TYPE_LOOPDETECT = 0x04, +++}; +++ +++/** +++ * enum batadv_tvlv_type - tvlv type definitions +++ * @BATADV_TVLV_GW: gateway tvlv +++ * @BATADV_TVLV_DAT: distributed arp table tvlv +++ * @BATADV_TVLV_NC: network coding tvlv +++ * @BATADV_TVLV_TT: translation table tvlv +++ * @BATADV_TVLV_ROAM: roaming advertisement tvlv +++ * @BATADV_TVLV_MCAST: multicast capability tvlv +++ */ +++enum batadv_tvlv_type { +++ BATADV_TVLV_GW = 0x01, +++ BATADV_TVLV_DAT = 0x02, +++ BATADV_TVLV_NC = 0x03, +++ BATADV_TVLV_TT = 0x04, +++ BATADV_TVLV_ROAM = 0x05, +++ BATADV_TVLV_MCAST = 0x06, +++}; +++ +++#pragma pack(2) +++/* the destination hardware field in the ARP frame is used to +++ * transport the claim type and the group id +++ */ +++struct batadv_bla_claim_dst { +++ __u8 magic[3]; /* FF:43:05 */ +++ __u8 type; /* bla_claimframe */ +++ __be16 group; /* group id */ +++}; +++ +++#pragma pack() +++ +++/** +++ * struct batadv_ogm_packet - ogm (routing protocol) packet +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @flags: contains routing relevant flags - see enum batadv_iv_flags +++ * @seqno: sequence identification +++ * @orig: address of the source node +++ * @prev_sender: address of the previous sender +++ * @reserved: reserved byte for alignment +++ * @tq: transmission quality +++ * @tvlv_len: length of tvlv data following the ogm header +++ */ +++struct batadv_ogm_packet { +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 flags; +++ __be32 seqno; +++ __u8 orig[ETH_ALEN]; +++ __u8 prev_sender[ETH_ALEN]; +++ __u8 reserved; +++ __u8 tq; +++ __be16 tvlv_len; +++ /* __packed is not needed as the struct size is divisible by 4, +++ * and the largest data type in this struct has a size of 4. +++ */ +++}; +++ +++#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) +++ +++/** +++ * struct batadv_ogm2_packet - ogm2 (routing protocol) packet +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the general header +++ * @ttl: time to live for this packet, part of the general header +++ * @flags: reseved for routing relevant flags - currently always 0 +++ * @seqno: sequence number +++ * @orig: originator mac address +++ * @tvlv_len: length of the appended tvlv buffer (in bytes) +++ * @throughput: the currently flooded path throughput +++ */ +++struct batadv_ogm2_packet { +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 flags; +++ __be32 seqno; +++ __u8 orig[ETH_ALEN]; +++ __be16 tvlv_len; +++ __be32 throughput; +++ /* __packed is not needed as the struct size is divisible by 4, +++ * and the largest data type in this struct has a size of 4. +++ */ +++}; +++ +++#define BATADV_OGM2_HLEN sizeof(struct batadv_ogm2_packet) +++ +++/** +++ * struct batadv_elp_packet - elp (neighbor discovery) packet +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @orig: originator mac address +++ * @seqno: sequence number +++ * @elp_interval: currently used ELP sending interval in ms +++ */ +++struct batadv_elp_packet { +++ __u8 packet_type; +++ __u8 version; +++ __u8 orig[ETH_ALEN]; +++ __be32 seqno; +++ __be32 elp_interval; +++}; +++ +++#define BATADV_ELP_HLEN sizeof(struct batadv_elp_packet) +++ +++/** +++ * struct batadv_icmp_header - common members among all the ICMP packets +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @msg_type: ICMP packet type +++ * @dst: address of the destination node +++ * @orig: address of the source node +++ * @uid: local ICMP socket identifier +++ * @align: not used - useful for alignment purposes only +++ * +++ * This structure is used for ICMP packets parsing only and it is never sent +++ * over the wire. The alignment field at the end is there to ensure that +++ * members are padded the same way as they are in real packets. +++ */ +++struct batadv_icmp_header { +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 msg_type; /* see ICMP message types above */ +++ __u8 dst[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __u8 uid; +++ __u8 align[3]; +++}; +++ +++/** +++ * struct batadv_icmp_packet - ICMP packet +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @msg_type: ICMP packet type +++ * @dst: address of the destination node +++ * @orig: address of the source node +++ * @uid: local ICMP socket identifier +++ * @reserved: not used - useful for alignment +++ * @seqno: ICMP sequence number +++ */ +++struct batadv_icmp_packet { +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 msg_type; /* see ICMP message types above */ +++ __u8 dst[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __u8 uid; +++ __u8 reserved; +++ __be16 seqno; +++}; +++ +++/** +++ * struct batadv_icmp_tp_packet - ICMP TP Meter packet +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @msg_type: ICMP packet type +++ * @dst: address of the destination node +++ * @orig: address of the source node +++ * @uid: local ICMP socket identifier +++ * @subtype: TP packet subtype (see batadv_icmp_tp_subtype) +++ * @session: TP session identifier +++ * @seqno: the TP sequence number +++ * @timestamp: time when the packet has been sent. This value is filled in a +++ * TP_MSG and echoed back in the next TP_ACK so that the sender can compute the +++ * RTT. Since it is read only by the host which wrote it, there is no need to +++ * store it using network order +++ */ +++struct batadv_icmp_tp_packet { +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 msg_type; /* see ICMP message types above */ +++ __u8 dst[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __u8 uid; +++ __u8 subtype; +++ __u8 session[2]; +++ __be32 seqno; +++ __be32 timestamp; +++}; +++ +++/** +++ * enum batadv_icmp_tp_subtype - ICMP TP Meter packet subtypes +++ * @BATADV_TP_MSG: Msg from sender to receiver +++ * @BATADV_TP_ACK: acknowledgment from receiver to sender +++ */ +++enum batadv_icmp_tp_subtype { +++ BATADV_TP_MSG = 0, +++ BATADV_TP_ACK, +++}; +++ +++#define BATADV_RR_LEN 16 +++ +++/** +++ * struct batadv_icmp_packet_rr - ICMP RouteRecord packet +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @msg_type: ICMP packet type +++ * @dst: address of the destination node +++ * @orig: address of the source node +++ * @uid: local ICMP socket identifier +++ * @rr_cur: number of entries the rr array +++ * @seqno: ICMP sequence number +++ * @rr: route record array +++ */ +++struct batadv_icmp_packet_rr { +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 msg_type; /* see ICMP message types above */ +++ __u8 dst[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __u8 uid; +++ __u8 rr_cur; +++ __be16 seqno; +++ __u8 rr[BATADV_RR_LEN][ETH_ALEN]; +++}; +++ +++#define BATADV_ICMP_MAX_PACKET_SIZE sizeof(struct batadv_icmp_packet_rr) +++ +++/* All packet headers in front of an ethernet header have to be completely +++ * divisible by 2 but not by 4 to make the payload after the ethernet +++ * header again 4 bytes boundary aligned. +++ * +++ * A packing of 2 is necessary to avoid extra padding at the end of the struct +++ * caused by a structure member which is larger than two bytes. Otherwise +++ * the structure would not fulfill the previously mentioned rule to avoid the +++ * misalignment of the payload after the ethernet header. It may also lead to +++ * leakage of information when the padding it not initialized before sending. +++ */ +++#pragma pack(2) +++ +++/** +++ * struct batadv_unicast_packet - unicast packet for network payload +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @ttvn: translation table version number +++ * @dest: originator destination of the unicast packet +++ */ +++struct batadv_unicast_packet { +++ __u8 packet_type; +++ __u8 version; +++ __u8 ttl; +++ __u8 ttvn; /* destination translation table version number */ +++ __u8 dest[ETH_ALEN]; +++ /* "4 bytes boundary + 2 bytes" long to make the payload after the +++ * following ethernet header again 4 bytes boundary aligned +++ */ +++}; +++ +++/** +++ * struct batadv_unicast_4addr_packet - extended unicast packet +++ * @u: common unicast packet header +++ * @src: address of the source +++ * @subtype: packet subtype +++ * @reserved: reserved byte for alignment +++ */ +++struct batadv_unicast_4addr_packet { +++ struct batadv_unicast_packet u; +++ __u8 src[ETH_ALEN]; +++ __u8 subtype; +++ __u8 reserved; +++ /* "4 bytes boundary + 2 bytes" long to make the payload after the +++ * following ethernet header again 4 bytes boundary aligned +++ */ +++}; +++ +++/** +++ * struct batadv_frag_packet - fragmented packet +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @dest: final destination used when routing fragments +++ * @orig: originator of the fragment used when merging the packet +++ * @no: fragment number within this sequence +++ * @priority: priority of frame, from ToS IP precedence or 802.1p +++ * @reserved: reserved byte for alignment +++ * @seqno: sequence identification +++ * @total_size: size of the merged packet +++ */ +++struct batadv_frag_packet { +++ __u8 packet_type; +++ __u8 version; /* batman version field */ +++ __u8 ttl; +++#if defined(__BIG_ENDIAN_BITFIELD) +++ __u8 no:4; +++ __u8 priority:3; +++ __u8 reserved:1; +++#elif defined(__LITTLE_ENDIAN_BITFIELD) +++ __u8 reserved:1; +++ __u8 priority:3; +++ __u8 no:4; +++#else +++#error "unknown bitfield endianness" +++#endif +++ __u8 dest[ETH_ALEN]; +++ __u8 orig[ETH_ALEN]; +++ __be16 seqno; +++ __be16 total_size; +++}; +++ +++/** +++ * struct batadv_bcast_packet - broadcast packet for network payload +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @reserved: reserved byte for alignment +++ * @seqno: sequence identification +++ * @orig: originator of the broadcast packet +++ */ +++struct batadv_bcast_packet { +++ __u8 packet_type; +++ __u8 version; /* batman version field */ +++ __u8 ttl; +++ __u8 reserved; +++ __be32 seqno; +++ __u8 orig[ETH_ALEN]; +++ /* "4 bytes boundary + 2 bytes" long to make the payload after the +++ * following ethernet header again 4 bytes boundary aligned +++ */ +++}; +++ +++/** +++ * struct batadv_coded_packet - network coded packet +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @first_source: original source of first included packet +++ * @first_orig_dest: original destinal of first included packet +++ * @first_crc: checksum of first included packet +++ * @first_ttvn: tt-version number of first included packet +++ * @second_ttl: ttl of second packet +++ * @second_dest: second receiver of this coded packet +++ * @second_source: original source of second included packet +++ * @second_orig_dest: original destination of second included packet +++ * @second_crc: checksum of second included packet +++ * @second_ttvn: tt version number of second included packet +++ * @coded_len: length of network coded part of the payload +++ */ +++struct batadv_coded_packet { +++ __u8 packet_type; +++ __u8 version; /* batman version field */ +++ __u8 ttl; +++ __u8 first_ttvn; +++ /* __u8 first_dest[ETH_ALEN]; - saved in mac header destination */ +++ __u8 first_source[ETH_ALEN]; +++ __u8 first_orig_dest[ETH_ALEN]; +++ __be32 first_crc; +++ __u8 second_ttl; +++ __u8 second_ttvn; +++ __u8 second_dest[ETH_ALEN]; +++ __u8 second_source[ETH_ALEN]; +++ __u8 second_orig_dest[ETH_ALEN]; +++ __be32 second_crc; +++ __be16 coded_len; +++}; +++ +++#pragma pack() +++ +++/** +++ * struct batadv_unicast_tvlv_packet - generic unicast packet with tvlv payload +++ * @packet_type: batman-adv packet type, part of the general header +++ * @version: batman-adv protocol version, part of the genereal header +++ * @ttl: time to live for this packet, part of the genereal header +++ * @reserved: reserved field (for packet alignment) +++ * @src: address of the source +++ * @dst: address of the destination +++ * @tvlv_len: length of tvlv data following the unicast tvlv header +++ * @align: 2 bytes to align the header to a 4 byte boundary +++ */ +++struct batadv_unicast_tvlv_packet { +++ __u8 packet_type; +++ __u8 version; /* batman version field */ +++ __u8 ttl; +++ __u8 reserved; +++ __u8 dst[ETH_ALEN]; +++ __u8 src[ETH_ALEN]; +++ __be16 tvlv_len; +++ __u16 align; +++}; +++ +++/** +++ * struct batadv_tvlv_hdr - base tvlv header struct +++ * @type: tvlv container type (see batadv_tvlv_type) +++ * @version: tvlv container version +++ * @len: tvlv container length +++ */ +++struct batadv_tvlv_hdr { +++ __u8 type; +++ __u8 version; +++ __be16 len; +++}; +++ +++/** +++ * struct batadv_tvlv_gateway_data - gateway data propagated through gw tvlv +++ * container +++ * @bandwidth_down: advertised uplink download bandwidth +++ * @bandwidth_up: advertised uplink upload bandwidth +++ */ +++struct batadv_tvlv_gateway_data { +++ __be32 bandwidth_down; +++ __be32 bandwidth_up; +++}; +++ +++/** +++ * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container +++ * @flags: translation table flags (see batadv_tt_data_flags) +++ * @ttvn: translation table version number +++ * @num_vlan: number of announced VLANs. In the TVLV this struct is followed by +++ * one batadv_tvlv_tt_vlan_data object per announced vlan +++ */ +++struct batadv_tvlv_tt_data { +++ __u8 flags; +++ __u8 ttvn; +++ __be16 num_vlan; +++}; +++ +++/** +++ * struct batadv_tvlv_tt_vlan_data - vlan specific tt data propagated through +++ * the tt tvlv container +++ * @crc: crc32 checksum of the entries belonging to this vlan +++ * @vid: vlan identifier +++ * @reserved: unused, useful for alignment purposes +++ */ +++struct batadv_tvlv_tt_vlan_data { +++ __be32 crc; +++ __be16 vid; +++ __u16 reserved; +++}; +++ +++/** +++ * struct batadv_tvlv_tt_change - translation table diff data +++ * @flags: status indicators concerning the non-mesh client (see +++ * batadv_tt_client_flags) +++ * @reserved: reserved field - useful for alignment purposes only +++ * @addr: mac address of non-mesh client that triggered this tt change +++ * @vid: VLAN identifier +++ */ +++struct batadv_tvlv_tt_change { +++ __u8 flags; +++ __u8 reserved[3]; +++ __u8 addr[ETH_ALEN]; +++ __be16 vid; +++}; +++ +++/** +++ * struct batadv_tvlv_roam_adv - roaming advertisement +++ * @client: mac address of roaming client +++ * @vid: VLAN identifier +++ */ +++struct batadv_tvlv_roam_adv { +++ __u8 client[ETH_ALEN]; +++ __be16 vid; +++}; +++ +++/** +++ * struct batadv_tvlv_mcast_data - payload of a multicast tvlv +++ * @flags: multicast flags announced by the orig node +++ * @reserved: reserved field +++ */ +++struct batadv_tvlv_mcast_data { +++ __u8 flags; +++ __u8 reserved[3]; +++}; +++ +++#endif /* _UAPI_LINUX_BATADV_PACKET_H_ */ +diff --git a/target/linux/generic/backport-4.14/274-flow_dissector-Parse-batman-adv-unicast-headers.patch b/target/linux/generic/backport-4.14/274-flow_dissector-Parse-batman-adv-unicast-headers.patch +new file mode 100644 +index 0000000000..a9b2fc40a3 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/274-flow_dissector-Parse-batman-adv-unicast-headers.patch +@@ -0,0 +1,108 @@ ++From: Sven Eckelmann ++Date: Thu, 21 Dec 2017 10:17:42 +0100 ++Subject: [PATCH] flow_dissector: Parse batman-adv unicast headers ++ ++The batman-adv unicast packets contain a full layer 2 frame in encapsulated ++form. The flow dissector must therefore be able to parse the batman-adv ++unicast header to reach the layer 2+3 information. ++ ++ +--------------------+ ++ | ip(v6)hdr | ++ +--------------------+ ++ | inner ethhdr | ++ +--------------------+ ++ | batadv unicast hdr | ++ +--------------------+ ++ | outer ethhdr | ++ +--------------------+ ++ ++The obtained information from the upper layer can then be used by RPS to ++schedule the processing on separate cores. This allows better distribution ++of multiple flows from the same neighbor to different cores. ++ ++Signed-off-by: Sven Eckelmann ++Reviewed-by: Jiri Pirko ++Acked-by: Willem de Bruijn ++Signed-off-by: David S. Miller ++--- ++ ++--- a/net/core/flow_dissector.c +++++ b/net/core/flow_dissector.c ++@@ -22,6 +22,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ static void dissector_set_key(struct flow_dissector *flow_dissector, ++ enum flow_dissector_key_id key_id) ++@@ -338,6 +339,57 @@ __skb_flow_dissect_gre(const struct sk_b ++ return FLOW_DISSECT_RET_PROTO_AGAIN; ++ } ++ +++/** +++ * __skb_flow_dissect_batadv() - dissect batman-adv header +++ * @skb: sk_buff to with the batman-adv header +++ * @key_control: flow dissectors control key +++ * @data: raw buffer pointer to the packet, if NULL use skb->data +++ * @p_proto: pointer used to update the protocol to process next +++ * @p_nhoff: pointer used to update inner network header offset +++ * @hlen: packet header length +++ * @flags: any combination of FLOW_DISSECTOR_F_* +++ * +++ * ETH_P_BATMAN packets are tried to be dissected. Only +++ * &struct batadv_unicast packets are actually processed because they contain an +++ * inner ethernet header and are usually followed by actual network header. This +++ * allows the flow dissector to continue processing the packet. +++ * +++ * Return: FLOW_DISSECT_RET_PROTO_AGAIN when &struct batadv_unicast was found, +++ * FLOW_DISSECT_RET_OUT_GOOD when dissector should stop after encapsulation, +++ * otherwise FLOW_DISSECT_RET_OUT_BAD +++ */ +++static enum flow_dissect_ret +++__skb_flow_dissect_batadv(const struct sk_buff *skb, +++ struct flow_dissector_key_control *key_control, +++ void *data, __be16 *p_proto, int *p_nhoff, int hlen, +++ unsigned int flags) +++{ +++ struct { +++ struct batadv_unicast_packet batadv_unicast; +++ struct ethhdr eth; +++ } *hdr, _hdr; +++ +++ hdr = __skb_header_pointer(skb, *p_nhoff, sizeof(_hdr), data, hlen, +++ &_hdr); +++ if (!hdr) +++ return FLOW_DISSECT_RET_OUT_BAD; +++ +++ if (hdr->batadv_unicast.version != BATADV_COMPAT_VERSION) +++ return FLOW_DISSECT_RET_OUT_BAD; +++ +++ if (hdr->batadv_unicast.packet_type != BATADV_UNICAST) +++ return FLOW_DISSECT_RET_OUT_BAD; +++ +++ *p_proto = hdr->eth.h_proto; +++ *p_nhoff += sizeof(*hdr); +++ +++ key_control->flags |= FLOW_DIS_ENCAPSULATION; +++ if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP) +++ return FLOW_DISSECT_RET_OUT_GOOD; +++ +++ return FLOW_DISSECT_RET_PROTO_AGAIN; +++} +++ ++ static void ++ __skb_flow_dissect_tcp(const struct sk_buff *skb, ++ struct flow_dissector *flow_dissector, ++@@ -718,6 +770,11 @@ proto_again: ++ nhoff, hlen); ++ break; ++ +++ case htons(ETH_P_BATMAN): +++ fdret = __skb_flow_dissect_batadv(skb, key_control, data, +++ &proto, &nhoff, hlen, flags); +++ break; +++ ++ default: ++ fdret = FLOW_DISSECT_RET_OUT_BAD; ++ break; +diff --git a/target/linux/generic/backport-4.14/289-v4.16-netfilter-add-defines-for-arp-decnet-max-hooks.patch b/target/linux/generic/backport-4.14/289-v4.16-netfilter-add-defines-for-arp-decnet-max-hooks.patch +new file mode 100644 +index 0000000000..f7898d4f30 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/289-v4.16-netfilter-add-defines-for-arp-decnet-max-hooks.patch +@@ -0,0 +1,67 @@ ++From e58f33cc84bc089c430ac955f3cad6380ae98591 Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Thu, 7 Dec 2017 16:28:23 +0100 ++Subject: [PATCH] netfilter: add defines for arp/decnet max hooks ++ ++The kernel already has defines for this, but they are in uapi exposed ++headers. ++ ++Including these from netns.h causes build errors and also adds unneeded ++dependencies on heads that we don't need. ++ ++So move these defines to netfilter_defs.h and place the uapi ones ++in ifndef __KERNEL__ to keep them for userspace. ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ include/linux/netfilter_defs.h | 6 ++++++ ++ include/uapi/linux/netfilter_arp.h | 3 +++ ++ include/uapi/linux/netfilter_decnet.h | 4 +++- ++ 3 files changed, 12 insertions(+), 1 deletion(-) ++ ++--- a/include/linux/netfilter_defs.h +++++ b/include/linux/netfilter_defs.h ++@@ -7,4 +7,10 @@ ++ /* Largest hook number + 1, see uapi/linux/netfilter_decnet.h */ ++ #define NF_MAX_HOOKS 8 ++ +++/* in/out/forward only */ +++#define NF_ARP_NUMHOOKS 3 +++ +++/* max hook is NF_DN_ROUTE (6), also see uapi/linux/netfilter_decnet.h */ +++#define NF_DN_NUMHOOKS 7 +++ ++ #endif ++--- a/include/uapi/linux/netfilter_arp.h +++++ b/include/uapi/linux/netfilter_arp.h ++@@ -15,6 +15,9 @@ ++ #define NF_ARP_IN 0 ++ #define NF_ARP_OUT 1 ++ #define NF_ARP_FORWARD 2 +++ +++#ifndef __KERNEL__ ++ #define NF_ARP_NUMHOOKS 3 +++#endif ++ ++ #endif /* __LINUX_ARP_NETFILTER_H */ ++--- a/include/uapi/linux/netfilter_decnet.h +++++ b/include/uapi/linux/netfilter_decnet.h ++@@ -24,6 +24,9 @@ ++ #define NFC_DN_IF_IN 0x0004 ++ /* Output device. */ ++ #define NFC_DN_IF_OUT 0x0008 +++ +++/* kernel define is in netfilter_defs.h */ +++#define NF_DN_NUMHOOKS 7 ++ #endif /* ! __KERNEL__ */ ++ ++ /* DECnet Hooks */ ++@@ -41,7 +44,6 @@ ++ #define NF_DN_HELLO 5 ++ /* Input Routing Packets */ ++ #define NF_DN_ROUTE 6 ++-#define NF_DN_NUMHOOKS 7 ++ ++ enum nf_dn_hook_priorities { ++ NF_DN_PRI_FIRST = INT_MIN, +diff --git a/target/linux/generic/backport-4.14/290-v4.16-netfilter-core-make-nf_unregister_net_hooks-simple-w.patch b/target/linux/generic/backport-4.14/290-v4.16-netfilter-core-make-nf_unregister_net_hooks-simple-w.patch +new file mode 100644 +index 0000000000..35800c4acf +--- /dev/null ++++ b/target/linux/generic/backport-4.14/290-v4.16-netfilter-core-make-nf_unregister_net_hooks-simple-w.patch +@@ -0,0 +1,91 @@ ++From 4e645b47c4f000a503b9c90163ad905786b9bc1d Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Fri, 1 Dec 2017 00:21:02 +0100 ++Subject: [PATCH 02/11] netfilter: core: make nf_unregister_net_hooks simple ++ wrapper again ++ ++This reverts commit d3ad2c17b4047 ++("netfilter: core: batch nf_unregister_net_hooks synchronize_net calls"). ++ ++Nothing wrong with it. However, followup patch will delay freeing of hooks ++with call_rcu, so all synchronize_net() calls become obsolete and there ++is no need anymore for this batching. ++ ++This revert causes a temporary performance degradation when destroying ++network namespace, but its resolved with the upcoming call_rcu conversion. ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ net/netfilter/core.c | 59 +++------------------------------------------------- ++ 1 file changed, 3 insertions(+), 56 deletions(-) ++ ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -395,63 +395,10 @@ EXPORT_SYMBOL(nf_register_net_hooks); ++ void nf_unregister_net_hooks(struct net *net, const struct nf_hook_ops *reg, ++ unsigned int hookcount) ++ { ++- struct nf_hook_entries *to_free[16], *p; ++- struct nf_hook_entries __rcu **pp; ++- unsigned int i, j, n; +++ unsigned int i; ++ ++- mutex_lock(&nf_hook_mutex); ++- for (i = 0; i < hookcount; i++) { ++- pp = nf_hook_entry_head(net, ®[i]); ++- if (!pp) ++- continue; ++- ++- p = nf_entry_dereference(*pp); ++- if (WARN_ON_ONCE(!p)) ++- continue; ++- __nf_unregister_net_hook(p, ®[i]); ++- } ++- mutex_unlock(&nf_hook_mutex); ++- ++- do { ++- n = min_t(unsigned int, hookcount, ARRAY_SIZE(to_free)); ++- ++- mutex_lock(&nf_hook_mutex); ++- ++- for (i = 0, j = 0; i < hookcount && j < n; i++) { ++- pp = nf_hook_entry_head(net, ®[i]); ++- if (!pp) ++- continue; ++- ++- p = nf_entry_dereference(*pp); ++- if (!p) ++- continue; ++- ++- to_free[j] = __nf_hook_entries_try_shrink(pp); ++- if (to_free[j]) ++- ++j; ++- } ++- ++- mutex_unlock(&nf_hook_mutex); ++- ++- if (j) { ++- unsigned int nfq; ++- ++- synchronize_net(); ++- ++- /* need 2nd synchronize_net() if nfqueue is used, skb ++- * can get reinjected right before nf_queue_hook_drop() ++- */ ++- nfq = nf_queue_nf_hook_drop(net); ++- if (nfq) ++- synchronize_net(); ++- ++- for (i = 0; i < j; i++) ++- kvfree(to_free[i]); ++- } ++- ++- reg += n; ++- hookcount -= n; ++- } while (hookcount > 0); +++ for (i = 0; i < hookcount; i++) +++ nf_unregister_net_hook(net, ®[i]); ++ } ++ EXPORT_SYMBOL(nf_unregister_net_hooks); ++ +diff --git a/target/linux/generic/backport-4.14/291-v4.16-netfilter-core-remove-synchronize_net-call-if-nfqueu.patch b/target/linux/generic/backport-4.14/291-v4.16-netfilter-core-remove-synchronize_net-call-if-nfqueu.patch +new file mode 100644 +index 0000000000..0ac5783624 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/291-v4.16-netfilter-core-remove-synchronize_net-call-if-nfqueu.patch +@@ -0,0 +1,116 @@ ++From 26888dfd7e7454686b8d3ea9ba5045d5f236e4d7 Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Fri, 1 Dec 2017 00:21:03 +0100 ++Subject: [PATCH 03/11] netfilter: core: remove synchronize_net call if nfqueue ++ is used ++ ++since commit 960632ece6949b ("netfilter: convert hook list to an array") ++nfqueue no longer stores a pointer to the hook that caused the packet ++to be queued. Therefore no extra synchronize_net() call is needed after ++dropping the packets enqueued by the old rule blob. ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ include/net/netfilter/nf_queue.h | 2 +- ++ net/netfilter/core.c | 6 +----- ++ net/netfilter/nf_internals.h | 2 +- ++ net/netfilter/nf_queue.c | 7 ++----- ++ net/netfilter/nfnetlink_queue.c | 9 ++------- ++ 5 files changed, 7 insertions(+), 19 deletions(-) ++ ++--- a/include/net/netfilter/nf_queue.h +++++ b/include/net/netfilter/nf_queue.h ++@@ -25,7 +25,7 @@ struct nf_queue_entry { ++ struct nf_queue_handler { ++ int (*outfn)(struct nf_queue_entry *entry, ++ unsigned int queuenum); ++- unsigned int (*nf_hook_drop)(struct net *net); +++ void (*nf_hook_drop)(struct net *net); ++ }; ++ ++ void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh); ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -341,7 +341,6 @@ void nf_unregister_net_hook(struct net * ++ { ++ struct nf_hook_entries __rcu **pp; ++ struct nf_hook_entries *p; ++- unsigned int nfq; ++ ++ pp = nf_hook_entry_head(net, reg); ++ if (!pp) ++@@ -364,10 +363,7 @@ void nf_unregister_net_hook(struct net * ++ ++ synchronize_net(); ++ ++- /* other cpu might still process nfqueue verdict that used reg */ ++- nfq = nf_queue_nf_hook_drop(net); ++- if (nfq) ++- synchronize_net(); +++ nf_queue_nf_hook_drop(net); ++ kvfree(p); ++ } ++ EXPORT_SYMBOL(nf_unregister_net_hook); ++--- a/net/netfilter/nf_internals.h +++++ b/net/netfilter/nf_internals.h ++@@ -10,7 +10,7 @@ ++ int nf_queue(struct sk_buff *skb, struct nf_hook_state *state, ++ const struct nf_hook_entries *entries, unsigned int index, ++ unsigned int verdict); ++-unsigned int nf_queue_nf_hook_drop(struct net *net); +++void nf_queue_nf_hook_drop(struct net *net); ++ ++ /* nf_log.c */ ++ int __init netfilter_log_init(void); ++--- a/net/netfilter/nf_queue.c +++++ b/net/netfilter/nf_queue.c ++@@ -96,18 +96,15 @@ void nf_queue_entry_get_refs(struct nf_q ++ } ++ EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs); ++ ++-unsigned int nf_queue_nf_hook_drop(struct net *net) +++void nf_queue_nf_hook_drop(struct net *net) ++ { ++ const struct nf_queue_handler *qh; ++- unsigned int count = 0; ++ ++ rcu_read_lock(); ++ qh = rcu_dereference(net->nf.queue_handler); ++ if (qh) ++- count = qh->nf_hook_drop(net); +++ qh->nf_hook_drop(net); ++ rcu_read_unlock(); ++- ++- return count; ++ } ++ EXPORT_SYMBOL_GPL(nf_queue_nf_hook_drop); ++ ++--- a/net/netfilter/nfnetlink_queue.c +++++ b/net/netfilter/nfnetlink_queue.c ++@@ -941,23 +941,18 @@ static struct notifier_block nfqnl_dev_n ++ .notifier_call = nfqnl_rcv_dev_event, ++ }; ++ ++-static unsigned int nfqnl_nf_hook_drop(struct net *net) +++static void nfqnl_nf_hook_drop(struct net *net) ++ { ++ struct nfnl_queue_net *q = nfnl_queue_pernet(net); ++- unsigned int instances = 0; ++ int i; ++ ++ for (i = 0; i < INSTANCE_BUCKETS; i++) { ++ struct nfqnl_instance *inst; ++ struct hlist_head *head = &q->instance_table[i]; ++ ++- hlist_for_each_entry_rcu(inst, head, hlist) { +++ hlist_for_each_entry_rcu(inst, head, hlist) ++ nfqnl_flush(inst, NULL, 0); ++- instances++; ++- } ++ } ++- ++- return instances; ++ } ++ ++ static int +diff --git a/target/linux/generic/backport-4.14/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch b/target/linux/generic/backport-4.14/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch +new file mode 100644 +index 0000000000..5eca73552b +--- /dev/null ++++ b/target/linux/generic/backport-4.14/292-v4.16-netfilter-core-free-hooks-with-call_rcu.patch +@@ -0,0 +1,132 @@ ++From 8c873e2199700c2de7dbd5eedb9d90d5f109462b Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Fri, 1 Dec 2017 00:21:04 +0100 ++Subject: [PATCH 04/11] netfilter: core: free hooks with call_rcu ++ ++Giuseppe Scrivano says: ++ "SELinux, if enabled, registers for each new network namespace 6 ++ netfilter hooks." ++ ++Cost for this is high. With synchronize_net() removed: ++ "The net benefit on an SMP machine with two cores is that creating a ++ new network namespace takes -40% of the original time." ++ ++This patch replaces synchronize_net+kvfree with call_rcu(). ++We store rcu_head at the tail of a structure that has no fixed layout, ++i.e. we cannot use offsetof() to compute the start of the original ++allocation. Thus store this information right after the rcu head. ++ ++We could simplify this by just placing the rcu_head at the start ++of struct nf_hook_entries. However, this structure is used in ++packet processing hotpath, so only place what is needed for that ++at the beginning of the struct. ++ ++Reported-by: Giuseppe Scrivano ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ include/linux/netfilter.h | 19 +++++++++++++++---- ++ net/netfilter/core.c | 34 ++++++++++++++++++++++++++++------ ++ 2 files changed, 43 insertions(+), 10 deletions(-) ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -77,17 +77,28 @@ struct nf_hook_entry { ++ void *priv; ++ }; ++ +++struct nf_hook_entries_rcu_head { +++ struct rcu_head head; +++ void *allocation; +++}; +++ ++ struct nf_hook_entries { ++ u16 num_hook_entries; ++ /* padding */ ++ struct nf_hook_entry hooks[]; ++ ++- /* trailer: pointers to original orig_ops of each hook. ++- * ++- * This is not part of struct nf_hook_entry since its only ++- * needed in slow path (hook register/unregister). +++ /* trailer: pointers to original orig_ops of each hook, +++ * followed by rcu_head and scratch space used for freeing +++ * the structure via call_rcu. ++ * +++ * This is not part of struct nf_hook_entry since its only +++ * needed in slow path (hook register/unregister): ++ * const struct nf_hook_ops *orig_ops[] +++ * +++ * For the same reason, we store this at end -- its +++ * only needed when a hook is deleted, not during +++ * packet path processing: +++ * struct nf_hook_entries_rcu_head head ++ */ ++ }; ++ ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -74,7 +74,8 @@ static struct nf_hook_entries *allocate_ ++ struct nf_hook_entries *e; ++ size_t alloc = sizeof(*e) + ++ sizeof(struct nf_hook_entry) * num + ++- sizeof(struct nf_hook_ops *) * num; +++ sizeof(struct nf_hook_ops *) * num + +++ sizeof(struct nf_hook_entries_rcu_head); ++ ++ if (num == 0) ++ return NULL; ++@@ -85,6 +86,30 @@ static struct nf_hook_entries *allocate_ ++ return e; ++ } ++ +++static void __nf_hook_entries_free(struct rcu_head *h) +++{ +++ struct nf_hook_entries_rcu_head *head; +++ +++ head = container_of(h, struct nf_hook_entries_rcu_head, head); +++ kvfree(head->allocation); +++} +++ +++static void nf_hook_entries_free(struct nf_hook_entries *e) +++{ +++ struct nf_hook_entries_rcu_head *head; +++ struct nf_hook_ops **ops; +++ unsigned int num; +++ +++ if (!e) +++ return; +++ +++ num = e->num_hook_entries; +++ ops = nf_hook_entries_get_hook_ops(e); +++ head = (void *)&ops[num]; +++ head->allocation = e; +++ call_rcu(&head->head, __nf_hook_entries_free); +++} +++ ++ static unsigned int accept_all(void *priv, ++ struct sk_buff *skb, ++ const struct nf_hook_state *state) ++@@ -291,9 +316,8 @@ int nf_register_net_hook(struct net *net ++ #ifdef HAVE_JUMP_LABEL ++ static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]); ++ #endif ++- synchronize_net(); ++ BUG_ON(p == new_hooks); ++- kvfree(p); +++ nf_hook_entries_free(p); ++ return 0; ++ } ++ EXPORT_SYMBOL(nf_register_net_hook); ++@@ -361,10 +385,8 @@ void nf_unregister_net_hook(struct net * ++ if (!p) ++ return; ++ ++- synchronize_net(); ++- ++ nf_queue_nf_hook_drop(net); ++- kvfree(p); +++ nf_hook_entries_free(p); ++ } ++ EXPORT_SYMBOL(nf_unregister_net_hook); ++ +diff --git a/target/linux/generic/backport-4.14/293-v4.16-netfilter-reduce-size-of-hook-entry-point-locations.patch b/target/linux/generic/backport-4.14/293-v4.16-netfilter-reduce-size-of-hook-entry-point-locations.patch +new file mode 100644 +index 0000000000..4b889120bf +--- /dev/null ++++ b/target/linux/generic/backport-4.14/293-v4.16-netfilter-reduce-size-of-hook-entry-point-locations.patch +@@ -0,0 +1,200 @@ ++From b0f38338aef2dae5ade3c16acf713737e3b15a73 Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Sun, 3 Dec 2017 00:58:47 +0100 ++Subject: [PATCH 05/11] netfilter: reduce size of hook entry point locations ++ ++struct net contains: ++ ++struct nf_hook_entries __rcu *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; ++ ++which store the hook entry point locations for the various protocol ++families and the hooks. ++ ++Using array results in compact c code when doing accesses, i.e. ++ x = rcu_dereference(net->nf.hooks[pf][hook]); ++ ++but its also wasting a lot of memory, as most families are ++not used. ++ ++So split the array into those families that are used, which ++are only 5 (instead of 13). In most cases, the 'pf' argument is ++constant, i.e. gcc removes switch statement. ++ ++struct net before: ++ /* size: 5184, cachelines: 81, members: 46 */ ++after: ++ /* size: 4672, cachelines: 73, members: 46 */ ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ include/linux/netfilter.h | 24 ++++++++++++++++++++++-- ++ include/net/netns/netfilter.h | 6 +++++- ++ net/bridge/br_netfilter_hooks.c | 2 +- ++ net/netfilter/core.c | 38 ++++++++++++++++++++++++++++++-------- ++ net/netfilter/nf_queue.c | 21 +++++++++++++++++++-- ++ 5 files changed, 77 insertions(+), 14 deletions(-) ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -195,7 +195,7 @@ static inline int nf_hook(u_int8_t pf, u ++ struct net_device *indev, struct net_device *outdev, ++ int (*okfn)(struct net *, struct sock *, struct sk_buff *)) ++ { ++- struct nf_hook_entries *hook_head; +++ struct nf_hook_entries *hook_head = NULL; ++ int ret = 1; ++ ++ #ifdef HAVE_JUMP_LABEL ++@@ -206,7 +206,27 @@ static inline int nf_hook(u_int8_t pf, u ++ #endif ++ ++ rcu_read_lock(); ++- hook_head = rcu_dereference(net->nf.hooks[pf][hook]); +++ switch (pf) { +++ case NFPROTO_IPV4: +++ hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]); +++ break; +++ case NFPROTO_IPV6: +++ hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]); +++ break; +++ case NFPROTO_ARP: +++ hook_head = rcu_dereference(net->nf.hooks_arp[hook]); +++ break; +++ case NFPROTO_BRIDGE: +++ hook_head = rcu_dereference(net->nf.hooks_bridge[hook]); +++ break; +++ case NFPROTO_DECNET: +++ hook_head = rcu_dereference(net->nf.hooks_decnet[hook]); +++ break; +++ default: +++ WARN_ON_ONCE(1); +++ break; +++ } +++ ++ if (hook_head) { ++ struct nf_hook_state state; ++ ++--- a/include/net/netns/netfilter.h +++++ b/include/net/netns/netfilter.h ++@@ -17,7 +17,11 @@ struct netns_nf { ++ #ifdef CONFIG_SYSCTL ++ struct ctl_table_header *nf_log_dir_header; ++ #endif ++- struct nf_hook_entries __rcu *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; +++ struct nf_hook_entries __rcu *hooks_ipv4[NF_MAX_HOOKS]; +++ struct nf_hook_entries __rcu *hooks_ipv6[NF_MAX_HOOKS]; +++ struct nf_hook_entries __rcu *hooks_arp[NF_MAX_HOOKS]; +++ struct nf_hook_entries __rcu *hooks_bridge[NF_MAX_HOOKS]; +++ struct nf_hook_entries __rcu *hooks_decnet[NF_MAX_HOOKS]; ++ #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) ++ bool defrag_ipv4; ++ #endif ++--- a/net/bridge/br_netfilter_hooks.c +++++ b/net/bridge/br_netfilter_hooks.c ++@@ -991,7 +991,7 @@ int br_nf_hook_thresh(unsigned int hook, ++ unsigned int i; ++ int ret; ++ ++- e = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]); +++ e = rcu_dereference(net->nf.hooks_bridge[hook]); ++ if (!e) ++ return okfn(net, sk, skb); ++ ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -264,8 +264,23 @@ out_assign: ++ ++ static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, const struct nf_hook_ops *reg) ++ { ++- if (reg->pf != NFPROTO_NETDEV) ++- return net->nf.hooks[reg->pf]+reg->hooknum; +++ switch (reg->pf) { +++ case NFPROTO_NETDEV: +++ break; +++ case NFPROTO_ARP: +++ return net->nf.hooks_arp + reg->hooknum; +++ case NFPROTO_BRIDGE: +++ return net->nf.hooks_bridge + reg->hooknum; +++ case NFPROTO_IPV4: +++ return net->nf.hooks_ipv4 + reg->hooknum; +++ case NFPROTO_IPV6: +++ return net->nf.hooks_ipv6 + reg->hooknum; +++ case NFPROTO_DECNET: +++ return net->nf.hooks_decnet + reg->hooknum; +++ default: +++ WARN_ON_ONCE(1); +++ return NULL; +++ } ++ ++ #ifdef CONFIG_NETFILTER_INGRESS ++ if (reg->hooknum == NF_NETDEV_INGRESS) { ++@@ -534,14 +549,21 @@ void (*nf_nat_decode_session_hook)(struc ++ EXPORT_SYMBOL(nf_nat_decode_session_hook); ++ #endif ++ ++-static int __net_init netfilter_net_init(struct net *net) +++static void __net_init __netfilter_net_init(struct nf_hook_entries *e[NF_MAX_HOOKS]) ++ { ++- int i, h; +++ int h; ++ ++- for (i = 0; i < ARRAY_SIZE(net->nf.hooks); i++) { ++- for (h = 0; h < NF_MAX_HOOKS; h++) ++- RCU_INIT_POINTER(net->nf.hooks[i][h], NULL); ++- } +++ for (h = 0; h < NF_MAX_HOOKS; h++) +++ RCU_INIT_POINTER(e[h], NULL); +++} +++ +++static int __net_init netfilter_net_init(struct net *net) +++{ +++ __netfilter_net_init(net->nf.hooks_ipv4); +++ __netfilter_net_init(net->nf.hooks_ipv6); +++ __netfilter_net_init(net->nf.hooks_arp); +++ __netfilter_net_init(net->nf.hooks_bridge); +++ __netfilter_net_init(net->nf.hooks_decnet); ++ ++ #ifdef CONFIG_PROC_FS ++ net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter", ++--- a/net/netfilter/nf_queue.c +++++ b/net/netfilter/nf_queue.c ++@@ -206,6 +206,23 @@ repeat: ++ return NF_ACCEPT; ++ } ++ +++static struct nf_hook_entries *nf_hook_entries_head(const struct net *net, u8 pf, u8 hooknum) +++{ +++ switch (pf) { +++ case NFPROTO_BRIDGE: +++ return rcu_dereference(net->nf.hooks_bridge[hooknum]); +++ case NFPROTO_IPV4: +++ return rcu_dereference(net->nf.hooks_ipv4[hooknum]); +++ case NFPROTO_IPV6: +++ return rcu_dereference(net->nf.hooks_ipv6[hooknum]); +++ default: +++ WARN_ON_ONCE(1); +++ return NULL; +++ } +++ +++ return NULL; +++} +++ ++ /* Caller must hold rcu read-side lock */ ++ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) ++ { ++@@ -221,12 +238,12 @@ void nf_reinject(struct nf_queue_entry * ++ net = entry->state.net; ++ pf = entry->state.pf; ++ ++- hooks = rcu_dereference(net->nf.hooks[pf][entry->state.hook]); +++ hooks = nf_hook_entries_head(net, pf, entry->state.hook); ++ ++ nf_queue_entry_release_refs(entry); ++ ++ i = entry->hook_index; ++- if (WARN_ON_ONCE(i >= hooks->num_hook_entries)) { +++ if (WARN_ON_ONCE(!hooks || i >= hooks->num_hook_entries)) { ++ kfree_skb(skb); ++ kfree(entry); ++ return; +diff --git a/target/linux/generic/backport-4.14/294-v4.16-netfilter-reduce-hook-array-sizes-to-what-is-needed.patch b/target/linux/generic/backport-4.14/294-v4.16-netfilter-reduce-hook-array-sizes-to-what-is-needed.patch +new file mode 100644 +index 0000000000..d9009b8e1f +--- /dev/null ++++ b/target/linux/generic/backport-4.14/294-v4.16-netfilter-reduce-hook-array-sizes-to-what-is-needed.patch +@@ -0,0 +1,95 @@ ++From ef57170bbfdd6958281011332b1fd237712f69f0 Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Thu, 7 Dec 2017 16:28:24 +0100 ++Subject: [PATCH 06/11] netfilter: reduce hook array sizes to what is needed ++ ++Not all families share the same hook count, adjust sizes to what is ++needed. ++ ++struct net before: ++/* size: 6592, cachelines: 103, members: 46 */ ++after: ++/* size: 5952, cachelines: 93, members: 46 */ ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ include/net/netns/netfilter.h | 10 +++++----- ++ net/netfilter/core.c | 24 +++++++++++++++++------- ++ 2 files changed, 22 insertions(+), 12 deletions(-) ++ ++--- a/include/net/netns/netfilter.h +++++ b/include/net/netns/netfilter.h ++@@ -17,11 +17,11 @@ struct netns_nf { ++ #ifdef CONFIG_SYSCTL ++ struct ctl_table_header *nf_log_dir_header; ++ #endif ++- struct nf_hook_entries __rcu *hooks_ipv4[NF_MAX_HOOKS]; ++- struct nf_hook_entries __rcu *hooks_ipv6[NF_MAX_HOOKS]; ++- struct nf_hook_entries __rcu *hooks_arp[NF_MAX_HOOKS]; ++- struct nf_hook_entries __rcu *hooks_bridge[NF_MAX_HOOKS]; ++- struct nf_hook_entries __rcu *hooks_decnet[NF_MAX_HOOKS]; +++ struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS]; +++ struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS]; +++ struct nf_hook_entries __rcu *hooks_arp[NF_ARP_NUMHOOKS]; +++ struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS]; +++ struct nf_hook_entries __rcu *hooks_decnet[NF_DN_NUMHOOKS]; ++ #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) ++ bool defrag_ipv4; ++ #endif ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -268,14 +268,24 @@ static struct nf_hook_entries __rcu **nf ++ case NFPROTO_NETDEV: ++ break; ++ case NFPROTO_ARP: +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_arp) <= reg->hooknum)) +++ return NULL; ++ return net->nf.hooks_arp + reg->hooknum; ++ case NFPROTO_BRIDGE: +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_bridge) <= reg->hooknum)) +++ return NULL; ++ return net->nf.hooks_bridge + reg->hooknum; ++ case NFPROTO_IPV4: +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv4) <= reg->hooknum)) +++ return NULL; ++ return net->nf.hooks_ipv4 + reg->hooknum; ++ case NFPROTO_IPV6: +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv6) <= reg->hooknum)) +++ return NULL; ++ return net->nf.hooks_ipv6 + reg->hooknum; ++ case NFPROTO_DECNET: +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_decnet) <= reg->hooknum)) +++ return NULL; ++ return net->nf.hooks_decnet + reg->hooknum; ++ default: ++ WARN_ON_ONCE(1); ++@@ -549,21 +559,21 @@ void (*nf_nat_decode_session_hook)(struc ++ EXPORT_SYMBOL(nf_nat_decode_session_hook); ++ #endif ++ ++-static void __net_init __netfilter_net_init(struct nf_hook_entries *e[NF_MAX_HOOKS]) +++static void __net_init __netfilter_net_init(struct nf_hook_entries **e, int max) ++ { ++ int h; ++ ++- for (h = 0; h < NF_MAX_HOOKS; h++) +++ for (h = 0; h < max; h++) ++ RCU_INIT_POINTER(e[h], NULL); ++ } ++ ++ static int __net_init netfilter_net_init(struct net *net) ++ { ++- __netfilter_net_init(net->nf.hooks_ipv4); ++- __netfilter_net_init(net->nf.hooks_ipv6); ++- __netfilter_net_init(net->nf.hooks_arp); ++- __netfilter_net_init(net->nf.hooks_bridge); ++- __netfilter_net_init(net->nf.hooks_decnet); +++ __netfilter_net_init(net->nf.hooks_ipv4, ARRAY_SIZE(net->nf.hooks_ipv4)); +++ __netfilter_net_init(net->nf.hooks_ipv6, ARRAY_SIZE(net->nf.hooks_ipv6)); +++ __netfilter_net_init(net->nf.hooks_arp, ARRAY_SIZE(net->nf.hooks_arp)); +++ __netfilter_net_init(net->nf.hooks_bridge, ARRAY_SIZE(net->nf.hooks_bridge)); +++ __netfilter_net_init(net->nf.hooks_decnet, ARRAY_SIZE(net->nf.hooks_decnet)); ++ ++ #ifdef CONFIG_PROC_FS ++ net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter", +diff --git a/target/linux/generic/backport-4.14/295-v4.16-netfilter-don-t-allocate-space-for-decnet-hooks-unle.patch b/target/linux/generic/backport-4.14/295-v4.16-netfilter-don-t-allocate-space-for-decnet-hooks-unle.patch +new file mode 100644 +index 0000000000..26a93c40ae +--- /dev/null ++++ b/target/linux/generic/backport-4.14/295-v4.16-netfilter-don-t-allocate-space-for-decnet-hooks-unle.patch +@@ -0,0 +1,67 @@ ++From bb4badf3a3dc81190f7c1c1fa063cdefb18df45f Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Thu, 7 Dec 2017 16:28:25 +0100 ++Subject: [PATCH 07/11] netfilter: don't allocate space for decnet hooks unless ++ needed ++ ++no need to define hook points if the family isn't supported. ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ include/linux/netfilter.h | 2 ++ ++ include/net/netns/netfilter.h | 2 ++ ++ net/netfilter/core.c | 4 ++++ ++ 3 files changed, 8 insertions(+) ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -219,9 +219,11 @@ static inline int nf_hook(u_int8_t pf, u ++ case NFPROTO_BRIDGE: ++ hook_head = rcu_dereference(net->nf.hooks_bridge[hook]); ++ break; +++#if IS_ENABLED(CONFIG_DECNET) ++ case NFPROTO_DECNET: ++ hook_head = rcu_dereference(net->nf.hooks_decnet[hook]); ++ break; +++#endif ++ default: ++ WARN_ON_ONCE(1); ++ break; ++--- a/include/net/netns/netfilter.h +++++ b/include/net/netns/netfilter.h ++@@ -21,7 +21,9 @@ struct netns_nf { ++ struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS]; ++ struct nf_hook_entries __rcu *hooks_arp[NF_ARP_NUMHOOKS]; ++ struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS]; +++#if IS_ENABLED(CONFIG_DECNET) ++ struct nf_hook_entries __rcu *hooks_decnet[NF_DN_NUMHOOKS]; +++#endif ++ #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) ++ bool defrag_ipv4; ++ #endif ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -283,10 +283,12 @@ static struct nf_hook_entries __rcu **nf ++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv6) <= reg->hooknum)) ++ return NULL; ++ return net->nf.hooks_ipv6 + reg->hooknum; +++#if IS_ENABLED(CONFIG_DECNET) ++ case NFPROTO_DECNET: ++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_decnet) <= reg->hooknum)) ++ return NULL; ++ return net->nf.hooks_decnet + reg->hooknum; +++#endif ++ default: ++ WARN_ON_ONCE(1); ++ return NULL; ++@@ -573,7 +575,9 @@ static int __net_init netfilter_net_init ++ __netfilter_net_init(net->nf.hooks_ipv6, ARRAY_SIZE(net->nf.hooks_ipv6)); ++ __netfilter_net_init(net->nf.hooks_arp, ARRAY_SIZE(net->nf.hooks_arp)); ++ __netfilter_net_init(net->nf.hooks_bridge, ARRAY_SIZE(net->nf.hooks_bridge)); +++#if IS_ENABLED(CONFIG_DECNET) ++ __netfilter_net_init(net->nf.hooks_decnet, ARRAY_SIZE(net->nf.hooks_decnet)); +++#endif ++ ++ #ifdef CONFIG_PROC_FS ++ net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter", +diff --git a/target/linux/generic/backport-4.14/296-v4.16-netfilter-don-t-allocate-space-for-arp-bridge-hooks-.patch b/target/linux/generic/backport-4.14/296-v4.16-netfilter-don-t-allocate-space-for-arp-bridge-hooks-.patch +new file mode 100644 +index 0000000000..41675c3494 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/296-v4.16-netfilter-don-t-allocate-space-for-arp-bridge-hooks-.patch +@@ -0,0 +1,165 @@ ++From 2a95183a5e0375df756efb2ca37602d71e8455f9 Mon Sep 17 00:00:00 2001 ++From: Florian Westphal ++Date: Thu, 7 Dec 2017 16:28:26 +0100 ++Subject: [PATCH 08/11] netfilter: don't allocate space for arp/bridge hooks ++ unless needed ++ ++no need to define hook points if the family isn't supported. ++Because we need these hooks for either nftables, arp/ebtables ++or the 'call-iptables' hack we have in the bridge layer add two ++new dependencies, NETFILTER_FAMILY_{ARP,BRIDGE}, and have the ++users select them. ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ include/linux/netfilter.h | 4 ++++ ++ include/net/netns/netfilter.h | 4 ++++ ++ net/Kconfig | 1 + ++ net/bridge/netfilter/Kconfig | 2 ++ ++ net/ipv4/netfilter/Kconfig | 2 ++ ++ net/netfilter/Kconfig | 6 ++++++ ++ net/netfilter/core.c | 8 ++++++++ ++ net/netfilter/nf_queue.c | 2 ++ ++ 8 files changed, 29 insertions(+) ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -214,10 +214,14 @@ static inline int nf_hook(u_int8_t pf, u ++ hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]); ++ break; ++ case NFPROTO_ARP: +++#ifdef CONFIG_NETFILTER_FAMILY_ARP ++ hook_head = rcu_dereference(net->nf.hooks_arp[hook]); +++#endif ++ break; ++ case NFPROTO_BRIDGE: +++#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE ++ hook_head = rcu_dereference(net->nf.hooks_bridge[hook]); +++#endif ++ break; ++ #if IS_ENABLED(CONFIG_DECNET) ++ case NFPROTO_DECNET: ++--- a/include/net/netns/netfilter.h +++++ b/include/net/netns/netfilter.h ++@@ -19,8 +19,12 @@ struct netns_nf { ++ #endif ++ struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS]; ++ struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS]; +++#ifdef CONFIG_NETFILTER_FAMILY_ARP ++ struct nf_hook_entries __rcu *hooks_arp[NF_ARP_NUMHOOKS]; +++#endif +++#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE ++ struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS]; +++#endif ++ #if IS_ENABLED(CONFIG_DECNET) ++ struct nf_hook_entries __rcu *hooks_decnet[NF_DN_NUMHOOKS]; ++ #endif ++--- a/net/Kconfig +++++ b/net/Kconfig ++@@ -182,6 +182,7 @@ config BRIDGE_NETFILTER ++ depends on BRIDGE ++ depends on NETFILTER && INET ++ depends on NETFILTER_ADVANCED +++ select NETFILTER_FAMILY_BRIDGE ++ default m ++ ---help--- ++ Enabling this option will let arptables resp. iptables see bridged ++--- a/net/bridge/netfilter/Kconfig +++++ b/net/bridge/netfilter/Kconfig ++@@ -4,6 +4,7 @@ ++ # ++ menuconfig NF_TABLES_BRIDGE ++ depends on BRIDGE && NETFILTER && NF_TABLES +++ select NETFILTER_FAMILY_BRIDGE ++ tristate "Ethernet Bridge nf_tables support" ++ ++ if NF_TABLES_BRIDGE ++@@ -29,6 +30,7 @@ endif # NF_TABLES_BRIDGE ++ menuconfig BRIDGE_NF_EBTABLES ++ tristate "Ethernet Bridge tables (ebtables) support" ++ depends on BRIDGE && NETFILTER && NETFILTER_XTABLES +++ select NETFILTER_FAMILY_BRIDGE ++ help ++ ebtables is a general, extensible frame/packet identification ++ framework. Say 'Y' or 'M' here if you want to do Ethernet ++--- a/net/ipv4/netfilter/Kconfig +++++ b/net/ipv4/netfilter/Kconfig ++@@ -72,6 +72,7 @@ endif # NF_TABLES_IPV4 ++ ++ config NF_TABLES_ARP ++ tristate "ARP nf_tables support" +++ select NETFILTER_FAMILY_ARP ++ help ++ This option enables the ARP support for nf_tables. ++ ++@@ -392,6 +393,7 @@ endif # IP_NF_IPTABLES ++ config IP_NF_ARPTABLES ++ tristate "ARP tables support" ++ select NETFILTER_XTABLES +++ select NETFILTER_FAMILY_ARP ++ depends on NETFILTER_ADVANCED ++ help ++ arptables is a general, extensible packet identification framework. ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -12,6 +12,12 @@ config NETFILTER_INGRESS ++ config NETFILTER_NETLINK ++ tristate ++ +++config NETFILTER_FAMILY_BRIDGE +++ bool +++ +++config NETFILTER_FAMILY_ARP +++ bool +++ ++ config NETFILTER_NETLINK_ACCT ++ tristate "Netfilter NFACCT over NFNETLINK interface" ++ depends on NETFILTER_ADVANCED ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -267,14 +267,18 @@ static struct nf_hook_entries __rcu **nf ++ switch (reg->pf) { ++ case NFPROTO_NETDEV: ++ break; +++#ifdef CONFIG_NETFILTER_FAMILY_ARP ++ case NFPROTO_ARP: ++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_arp) <= reg->hooknum)) ++ return NULL; ++ return net->nf.hooks_arp + reg->hooknum; +++#endif +++#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE ++ case NFPROTO_BRIDGE: ++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_bridge) <= reg->hooknum)) ++ return NULL; ++ return net->nf.hooks_bridge + reg->hooknum; +++#endif ++ case NFPROTO_IPV4: ++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv4) <= reg->hooknum)) ++ return NULL; ++@@ -573,8 +577,12 @@ static int __net_init netfilter_net_init ++ { ++ __netfilter_net_init(net->nf.hooks_ipv4, ARRAY_SIZE(net->nf.hooks_ipv4)); ++ __netfilter_net_init(net->nf.hooks_ipv6, ARRAY_SIZE(net->nf.hooks_ipv6)); +++#ifdef CONFIG_NETFILTER_FAMILY_ARP ++ __netfilter_net_init(net->nf.hooks_arp, ARRAY_SIZE(net->nf.hooks_arp)); +++#endif +++#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE ++ __netfilter_net_init(net->nf.hooks_bridge, ARRAY_SIZE(net->nf.hooks_bridge)); +++#endif ++ #if IS_ENABLED(CONFIG_DECNET) ++ __netfilter_net_init(net->nf.hooks_decnet, ARRAY_SIZE(net->nf.hooks_decnet)); ++ #endif ++--- a/net/netfilter/nf_queue.c +++++ b/net/netfilter/nf_queue.c ++@@ -209,8 +209,10 @@ repeat: ++ static struct nf_hook_entries *nf_hook_entries_head(const struct net *net, u8 pf, u8 hooknum) ++ { ++ switch (pf) { +++#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE ++ case NFPROTO_BRIDGE: ++ return rcu_dereference(net->nf.hooks_bridge[hooknum]); +++#endif ++ case NFPROTO_IPV4: ++ return rcu_dereference(net->nf.hooks_ipv4[hooknum]); ++ case NFPROTO_IPV6: +diff --git a/target/linux/generic/backport-4.14/297-v4.16-netfilter-core-pass-hook-number-family-and-device-to.patch b/target/linux/generic/backport-4.14/297-v4.16-netfilter-core-pass-hook-number-family-and-device-to.patch +new file mode 100644 +index 0000000000..7d450f95f0 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/297-v4.16-netfilter-core-pass-hook-number-family-and-device-to.patch +@@ -0,0 +1,98 @@ ++From 62a0fe46e2aaba1812d3cbcae014a41539f9eb09 Mon Sep 17 00:00:00 2001 ++From: Pablo Neira Ayuso ++Date: Sat, 9 Dec 2017 15:23:51 +0100 ++Subject: [PATCH 09/11] netfilter: core: pass hook number, family and device to ++ nf_find_hook_list() ++ ++Instead of passing struct nf_hook_ops, this is needed by follow up ++patches to handle NFPROTO_INET from the core. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ net/netfilter/core.c | 36 +++++++++++++++++++----------------- ++ 1 file changed, 19 insertions(+), 17 deletions(-) ++ ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -262,36 +262,38 @@ out_assign: ++ return old; ++ } ++ ++-static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, const struct nf_hook_ops *reg) +++static struct nf_hook_entries __rcu ** +++nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum, +++ struct net_device *dev) ++ { ++- switch (reg->pf) { +++ switch (pf) { ++ case NFPROTO_NETDEV: ++ break; ++ #ifdef CONFIG_NETFILTER_FAMILY_ARP ++ case NFPROTO_ARP: ++- if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_arp) <= reg->hooknum)) +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_arp) <= hooknum)) ++ return NULL; ++- return net->nf.hooks_arp + reg->hooknum; +++ return net->nf.hooks_arp + hooknum; ++ #endif ++ #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE ++ case NFPROTO_BRIDGE: ++- if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_bridge) <= reg->hooknum)) +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_bridge) <= hooknum)) ++ return NULL; ++- return net->nf.hooks_bridge + reg->hooknum; +++ return net->nf.hooks_bridge + hooknum; ++ #endif ++ case NFPROTO_IPV4: ++- if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv4) <= reg->hooknum)) +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv4) <= hooknum)) ++ return NULL; ++- return net->nf.hooks_ipv4 + reg->hooknum; +++ return net->nf.hooks_ipv4 + hooknum; ++ case NFPROTO_IPV6: ++- if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv6) <= reg->hooknum)) +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv6) <= hooknum)) ++ return NULL; ++- return net->nf.hooks_ipv6 + reg->hooknum; +++ return net->nf.hooks_ipv6 + hooknum; ++ #if IS_ENABLED(CONFIG_DECNET) ++ case NFPROTO_DECNET: ++- if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_decnet) <= reg->hooknum)) +++ if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_decnet) <= hooknum)) ++ return NULL; ++- return net->nf.hooks_decnet + reg->hooknum; +++ return net->nf.hooks_decnet + hooknum; ++ #endif ++ default: ++ WARN_ON_ONCE(1); ++@@ -299,9 +301,9 @@ static struct nf_hook_entries __rcu **nf ++ } ++ ++ #ifdef CONFIG_NETFILTER_INGRESS ++- if (reg->hooknum == NF_NETDEV_INGRESS) { ++- if (reg->dev && dev_net(reg->dev) == net) ++- return ®->dev->nf_hooks_ingress; +++ if (hooknum == NF_NETDEV_INGRESS) { +++ if (dev && dev_net(dev) == net) +++ return &dev->nf_hooks_ingress; ++ } ++ #endif ++ WARN_ON_ONCE(1); ++@@ -323,7 +325,7 @@ int nf_register_net_hook(struct net *net ++ return -EINVAL; ++ } ++ ++- pp = nf_hook_entry_head(net, reg); +++ pp = nf_hook_entry_head(net, reg->pf, reg->hooknum, reg->dev); ++ if (!pp) ++ return -EINVAL; ++ ++@@ -397,7 +399,7 @@ void nf_unregister_net_hook(struct net * ++ struct nf_hook_entries __rcu **pp; ++ struct nf_hook_entries *p; ++ ++- pp = nf_hook_entry_head(net, reg); +++ pp = nf_hook_entry_head(net, reg->pf, reg->hooknum, reg->dev); ++ if (!pp) ++ return; ++ +diff --git a/target/linux/generic/backport-4.14/298-v4.16-netfilter-core-add-nf_remove_net_hook.patch b/target/linux/generic/backport-4.14/298-v4.16-netfilter-core-add-nf_remove_net_hook.patch +new file mode 100644 +index 0000000000..8fea44b359 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/298-v4.16-netfilter-core-add-nf_remove_net_hook.patch +@@ -0,0 +1,44 @@ ++From 3d3cdc38e8c265a9f9d3825e823e772872bca1b8 Mon Sep 17 00:00:00 2001 ++From: Pablo Neira Ayuso ++Date: Sat, 9 Dec 2017 15:19:14 +0100 ++Subject: [PATCH 01/11] netfilter: core: add nf_remove_net_hook ++ ++Just a cleanup, __nf_unregister_net_hook() is used by a follow up patch ++when handling NFPROTO_INET as a real family from the core. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ net/netfilter/core.c | 8 ++++---- ++ 1 file changed, 4 insertions(+), 4 deletions(-) ++ ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -356,7 +356,7 @@ int nf_register_net_hook(struct net *net ++ EXPORT_SYMBOL(nf_register_net_hook); ++ ++ /* ++- * __nf_unregister_net_hook - remove a hook from blob +++ * nf_remove_net_hook - remove a hook from blob ++ * ++ * @oldp: current address of hook blob ++ * @unreg: hook to unregister ++@@ -364,8 +364,8 @@ EXPORT_SYMBOL(nf_register_net_hook); ++ * This cannot fail, hook unregistration must always succeed. ++ * Therefore replace the to-be-removed hook with a dummy hook. ++ */ ++-static void __nf_unregister_net_hook(struct nf_hook_entries *old, ++- const struct nf_hook_ops *unreg) +++static void nf_remove_net_hook(struct nf_hook_entries *old, +++ const struct nf_hook_ops *unreg) ++ { ++ struct nf_hook_ops **orig_ops; ++ bool found = false; ++@@ -411,7 +411,7 @@ void nf_unregister_net_hook(struct net * ++ return; ++ } ++ ++- __nf_unregister_net_hook(p, reg); +++ nf_remove_net_hook(p, reg); ++ ++ p = __nf_hook_entries_try_shrink(pp); ++ mutex_unlock(&nf_hook_mutex); +diff --git a/target/linux/generic/backport-4.14/298-v4.16-netfilter-core-pass-family-as-parameter-to-nf_remove.patch b/target/linux/generic/backport-4.14/298-v4.16-netfilter-core-pass-family-as-parameter-to-nf_remove.patch +new file mode 100644 +index 0000000000..4c52635c13 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/298-v4.16-netfilter-core-pass-family-as-parameter-to-nf_remove.patch +@@ -0,0 +1,51 @@ ++From 30259408118f550f5969fda19c0d67020d21eda8 Mon Sep 17 00:00:00 2001 ++From: Pablo Neira Ayuso ++Date: Sat, 9 Dec 2017 15:26:37 +0100 ++Subject: [PATCH 10/11] netfilter: core: pass family as parameter to ++ nf_remove_net_hook() ++ ++So static_key_slow_dec applies to the family behind NFPROTO_INET. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ net/netfilter/core.c | 10 +++++----- ++ 1 file changed, 5 insertions(+), 5 deletions(-) ++ ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -365,7 +365,7 @@ EXPORT_SYMBOL(nf_register_net_hook); ++ * Therefore replace the to-be-removed hook with a dummy hook. ++ */ ++ static void nf_remove_net_hook(struct nf_hook_entries *old, ++- const struct nf_hook_ops *unreg) +++ const struct nf_hook_ops *unreg, int pf) ++ { ++ struct nf_hook_ops **orig_ops; ++ bool found = false; ++@@ -383,14 +383,14 @@ static void nf_remove_net_hook(struct nf ++ ++ if (found) { ++ #ifdef CONFIG_NETFILTER_INGRESS ++- if (unreg->pf == NFPROTO_NETDEV && unreg->hooknum == NF_NETDEV_INGRESS) +++ if (pf == NFPROTO_NETDEV && unreg->hooknum == NF_NETDEV_INGRESS) ++ net_dec_ingress_queue(); ++ #endif ++ #ifdef HAVE_JUMP_LABEL ++- static_key_slow_dec(&nf_hooks_needed[unreg->pf][unreg->hooknum]); +++ static_key_slow_dec(&nf_hooks_needed[pf][unreg->hooknum]); ++ #endif ++ } else { ++- WARN_ONCE(1, "hook not found, pf %d num %d", unreg->pf, unreg->hooknum); +++ WARN_ONCE(1, "hook not found, pf %d num %d", pf, unreg->hooknum); ++ } ++ } ++ ++@@ -411,7 +411,7 @@ void nf_unregister_net_hook(struct net * ++ return; ++ } ++ ++- nf_remove_net_hook(p, reg); +++ nf_remove_net_hook(p, reg, reg->pf); ++ ++ p = __nf_hook_entries_try_shrink(pp); ++ mutex_unlock(&nf_hook_mutex); +diff --git a/target/linux/generic/backport-4.14/299-v4.16-netfilter-core-support-for-NFPROTO_INET-hook-registr.patch b/target/linux/generic/backport-4.14/299-v4.16-netfilter-core-support-for-NFPROTO_INET-hook-registr.patch +new file mode 100644 +index 0000000000..b112855132 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/299-v4.16-netfilter-core-support-for-NFPROTO_INET-hook-registr.patch +@@ -0,0 +1,129 @@ ++From cb7ccd835ebb333669e400f99c650e4f3abf11c0 Mon Sep 17 00:00:00 2001 ++From: Pablo Neira Ayuso ++Date: Sat, 9 Dec 2017 15:30:26 +0100 ++Subject: [PATCH 11/11] netfilter: core: support for NFPROTO_INET hook ++ registration ++ ++Expand NFPROTO_INET in two hook registrations, one for NFPROTO_IPV4 and ++another for NFPROTO_IPV6. Hence, we handle NFPROTO_INET from the core. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ net/netfilter/core.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------- ++ 1 file changed, 44 insertions(+), 9 deletions(-) ++ ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -310,12 +310,13 @@ nf_hook_entry_head(struct net *net, int ++ return NULL; ++ } ++ ++-int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg) +++static int __nf_register_net_hook(struct net *net, int pf, +++ const struct nf_hook_ops *reg) ++ { ++ struct nf_hook_entries *p, *new_hooks; ++ struct nf_hook_entries __rcu **pp; ++ ++- if (reg->pf == NFPROTO_NETDEV) { +++ if (pf == NFPROTO_NETDEV) { ++ #ifndef CONFIG_NETFILTER_INGRESS ++ if (reg->hooknum == NF_NETDEV_INGRESS) ++ return -EOPNOTSUPP; ++@@ -325,7 +326,7 @@ int nf_register_net_hook(struct net *net ++ return -EINVAL; ++ } ++ ++- pp = nf_hook_entry_head(net, reg->pf, reg->hooknum, reg->dev); +++ pp = nf_hook_entry_head(net, pf, reg->hooknum, reg->dev); ++ if (!pp) ++ return -EINVAL; ++ ++@@ -343,17 +344,16 @@ int nf_register_net_hook(struct net *net ++ ++ hooks_validate(new_hooks); ++ #ifdef CONFIG_NETFILTER_INGRESS ++- if (reg->pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS) +++ if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS) ++ net_inc_ingress_queue(); ++ #endif ++ #ifdef HAVE_JUMP_LABEL ++- static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]); +++ static_key_slow_inc(&nf_hooks_needed[pf][reg->hooknum]); ++ #endif ++ BUG_ON(p == new_hooks); ++ nf_hook_entries_free(p); ++ return 0; ++ } ++-EXPORT_SYMBOL(nf_register_net_hook); ++ ++ /* ++ * nf_remove_net_hook - remove a hook from blob ++@@ -394,12 +394,13 @@ static void nf_remove_net_hook(struct nf ++ } ++ } ++ ++-void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) +++void __nf_unregister_net_hook(struct net *net, int pf, +++ const struct nf_hook_ops *reg) ++ { ++ struct nf_hook_entries __rcu **pp; ++ struct nf_hook_entries *p; ++ ++- pp = nf_hook_entry_head(net, reg->pf, reg->hooknum, reg->dev); +++ pp = nf_hook_entry_head(net, pf, reg->hooknum, reg->dev); ++ if (!pp) ++ return; ++ ++@@ -411,7 +412,7 @@ void nf_unregister_net_hook(struct net * ++ return; ++ } ++ ++- nf_remove_net_hook(p, reg, reg->pf); +++ nf_remove_net_hook(p, reg, pf); ++ ++ p = __nf_hook_entries_try_shrink(pp); ++ mutex_unlock(&nf_hook_mutex); ++@@ -421,8 +422,42 @@ void nf_unregister_net_hook(struct net * ++ nf_queue_nf_hook_drop(net); ++ nf_hook_entries_free(p); ++ } +++ +++void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) +++{ +++ if (reg->pf == NFPROTO_INET) { +++ __nf_unregister_net_hook(net, NFPROTO_IPV4, reg); +++ __nf_unregister_net_hook(net, NFPROTO_IPV6, reg); +++ } else { +++ __nf_unregister_net_hook(net, reg->pf, reg); +++ } +++} ++ EXPORT_SYMBOL(nf_unregister_net_hook); ++ +++int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg) +++{ +++ int err; +++ +++ if (reg->pf == NFPROTO_INET) { +++ err = __nf_register_net_hook(net, NFPROTO_IPV4, reg); +++ if (err < 0) +++ return err; +++ +++ err = __nf_register_net_hook(net, NFPROTO_IPV6, reg); +++ if (err < 0) { +++ __nf_unregister_net_hook(net, NFPROTO_IPV4, reg); +++ return err; +++ } +++ } else { +++ err = __nf_register_net_hook(net, reg->pf, reg); +++ if (err < 0) +++ return err; +++ } +++ +++ return 0; +++} +++EXPORT_SYMBOL(nf_register_net_hook); +++ ++ int nf_register_net_hooks(struct net *net, const struct nf_hook_ops *reg, ++ unsigned int n) ++ { +diff --git a/target/linux/generic/backport-4.14/300-v4.16-netfilter-nf_tables-explicit-nft_set_pktinfo-call-fr.patch b/target/linux/generic/backport-4.14/300-v4.16-netfilter-nf_tables-explicit-nft_set_pktinfo-call-fr.patch +new file mode 100644 +index 0000000000..c0cb5bbeba +--- /dev/null ++++ b/target/linux/generic/backport-4.14/300-v4.16-netfilter-nf_tables-explicit-nft_set_pktinfo-call-fr.patch +@@ -0,0 +1,291 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 10 Dec 2017 01:43:14 +0100 ++Subject: [PATCH] netfilter: nf_tables: explicit nft_set_pktinfo() call from ++ hook path ++ ++Instead of calling this function from the family specific variant, this ++reduces the code size in the fast path for the netdev, bridge and inet ++families. After this change, we must call nft_set_pktinfo() upfront from ++the chain hook indirection. ++ ++Before: ++ ++ text data bss dec hex filename ++ 2145 208 0 2353 931 net/netfilter/nf_tables_netdev.o ++ ++After: ++ ++ text data bss dec hex filename ++ 2125 208 0 2333 91d net/netfilter/nf_tables_netdev.o ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -54,8 +54,8 @@ static inline void nft_set_pktinfo(struc ++ pkt->xt.state = state; ++ } ++ ++-static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt, ++- struct sk_buff *skb) +++static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt, +++ struct sk_buff *skb) ++ { ++ pkt->tprot_set = false; ++ pkt->tprot = 0; ++@@ -63,14 +63,6 @@ static inline void nft_set_pktinfo_proto ++ pkt->xt.fragoff = 0; ++ } ++ ++-static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) ++-{ ++- nft_set_pktinfo(pkt, skb, state); ++- nft_set_pktinfo_proto_unspec(pkt, skb); ++-} ++- ++ /** ++ * struct nft_verdict - nf_tables verdict ++ * ++--- a/include/net/netfilter/nf_tables_ipv4.h +++++ b/include/net/netfilter/nf_tables_ipv4.h ++@@ -5,15 +5,11 @@ ++ #include ++ #include ++ ++-static inline void ++-nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) +++static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, +++ struct sk_buff *skb) ++ { ++ struct iphdr *ip; ++ ++- nft_set_pktinfo(pkt, skb, state); ++- ++ ip = ip_hdr(pkt->skb); ++ pkt->tprot_set = true; ++ pkt->tprot = ip->protocol; ++@@ -21,10 +17,8 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo ++ pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET; ++ } ++ ++-static inline int ++-__nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) +++static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, +++ struct sk_buff *skb) ++ { ++ struct iphdr *iph, _iph; ++ u32 len, thoff; ++@@ -52,14 +46,11 @@ __nft_set_pktinfo_ipv4_validate(struct n ++ return 0; ++ } ++ ++-static inline void ++-nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) +++static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, +++ struct sk_buff *skb) ++ { ++- nft_set_pktinfo(pkt, skb, state); ++- if (__nft_set_pktinfo_ipv4_validate(pkt, skb, state) < 0) ++- nft_set_pktinfo_proto_unspec(pkt, skb); +++ if (__nft_set_pktinfo_ipv4_validate(pkt, skb) < 0) +++ nft_set_pktinfo_unspec(pkt, skb); ++ } ++ ++ extern struct nft_af_info nft_af_ipv4; ++--- a/include/net/netfilter/nf_tables_ipv6.h +++++ b/include/net/netfilter/nf_tables_ipv6.h ++@@ -5,20 +5,16 @@ ++ #include ++ #include ++ ++-static inline void ++-nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) +++static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, +++ struct sk_buff *skb) ++ { ++ unsigned int flags = IP6_FH_F_AUTH; ++ int protohdr, thoff = 0; ++ unsigned short frag_off; ++ ++- nft_set_pktinfo(pkt, skb, state); ++- ++ protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags); ++ if (protohdr < 0) { ++- nft_set_pktinfo_proto_unspec(pkt, skb); +++ nft_set_pktinfo_unspec(pkt, skb); ++ return; ++ } ++ ++@@ -28,10 +24,8 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo ++ pkt->xt.fragoff = frag_off; ++ } ++ ++-static inline int ++-__nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) +++static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, +++ struct sk_buff *skb) ++ { ++ #if IS_ENABLED(CONFIG_IPV6) ++ unsigned int flags = IP6_FH_F_AUTH; ++@@ -68,14 +62,11 @@ __nft_set_pktinfo_ipv6_validate(struct n ++ #endif ++ } ++ ++-static inline void ++-nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) +++static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, +++ struct sk_buff *skb) ++ { ++- nft_set_pktinfo(pkt, skb, state); ++- if (__nft_set_pktinfo_ipv6_validate(pkt, skb, state) < 0) ++- nft_set_pktinfo_proto_unspec(pkt, skb); +++ if (__nft_set_pktinfo_ipv6_validate(pkt, skb) < 0) +++ nft_set_pktinfo_unspec(pkt, skb); ++ } ++ ++ extern struct nft_af_info nft_af_ipv6; ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -25,15 +25,17 @@ nft_do_chain_bridge(void *priv, ++ { ++ struct nft_pktinfo pkt; ++ +++ nft_set_pktinfo(&pkt, skb, state); +++ ++ switch (eth_hdr(skb)->h_proto) { ++ case htons(ETH_P_IP): ++- nft_set_pktinfo_ipv4_validate(&pkt, skb, state); +++ nft_set_pktinfo_ipv4_validate(&pkt, skb); ++ break; ++ case htons(ETH_P_IPV6): ++- nft_set_pktinfo_ipv6_validate(&pkt, skb, state); +++ nft_set_pktinfo_ipv6_validate(&pkt, skb); ++ break; ++ default: ++- nft_set_pktinfo_unspec(&pkt, skb, state); +++ nft_set_pktinfo_unspec(&pkt, skb); ++ break; ++ } ++ ++--- a/net/ipv4/netfilter/nf_tables_arp.c +++++ b/net/ipv4/netfilter/nf_tables_arp.c ++@@ -21,7 +21,8 @@ nft_do_chain_arp(void *priv, ++ { ++ struct nft_pktinfo pkt; ++ ++- nft_set_pktinfo_unspec(&pkt, skb, state); +++ nft_set_pktinfo(&pkt, skb, state); +++ nft_set_pktinfo_unspec(&pkt, skb); ++ ++ return nft_do_chain(&pkt, priv); ++ } ++--- a/net/ipv4/netfilter/nf_tables_ipv4.c +++++ b/net/ipv4/netfilter/nf_tables_ipv4.c ++@@ -24,7 +24,8 @@ static unsigned int nft_do_chain_ipv4(vo ++ { ++ struct nft_pktinfo pkt; ++ ++- nft_set_pktinfo_ipv4(&pkt, skb, state); +++ nft_set_pktinfo(&pkt, skb, state); +++ nft_set_pktinfo_ipv4(&pkt, skb); ++ ++ return nft_do_chain(&pkt, priv); ++ } ++--- a/net/ipv4/netfilter/nft_chain_nat_ipv4.c +++++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c ++@@ -33,7 +33,8 @@ static unsigned int nft_nat_do_chain(voi ++ { ++ struct nft_pktinfo pkt; ++ ++- nft_set_pktinfo_ipv4(&pkt, skb, state); +++ nft_set_pktinfo(&pkt, skb, state); +++ nft_set_pktinfo_ipv4(&pkt, skb); ++ ++ return nft_do_chain(&pkt, priv); ++ } ++--- a/net/ipv4/netfilter/nft_chain_route_ipv4.c +++++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c ++@@ -38,7 +38,8 @@ static unsigned int nf_route_table_hook( ++ ip_hdrlen(skb) < sizeof(struct iphdr)) ++ return NF_ACCEPT; ++ ++- nft_set_pktinfo_ipv4(&pkt, skb, state); +++ nft_set_pktinfo(&pkt, skb, state); +++ nft_set_pktinfo_ipv4(&pkt, skb); ++ ++ mark = skb->mark; ++ iph = ip_hdr(skb); ++--- a/net/ipv6/netfilter/nf_tables_ipv6.c +++++ b/net/ipv6/netfilter/nf_tables_ipv6.c ++@@ -22,7 +22,8 @@ static unsigned int nft_do_chain_ipv6(vo ++ { ++ struct nft_pktinfo pkt; ++ ++- nft_set_pktinfo_ipv6(&pkt, skb, state); +++ nft_set_pktinfo(&pkt, skb, state); +++ nft_set_pktinfo_ipv6(&pkt, skb); ++ ++ return nft_do_chain(&pkt, priv); ++ } ++--- a/net/ipv6/netfilter/nft_chain_nat_ipv6.c +++++ b/net/ipv6/netfilter/nft_chain_nat_ipv6.c ++@@ -31,7 +31,8 @@ static unsigned int nft_nat_do_chain(voi ++ { ++ struct nft_pktinfo pkt; ++ ++- nft_set_pktinfo_ipv6(&pkt, skb, state); +++ nft_set_pktinfo(&pkt, skb, state); +++ nft_set_pktinfo_ipv6(&pkt, skb); ++ ++ return nft_do_chain(&pkt, priv); ++ } ++--- a/net/ipv6/netfilter/nft_chain_route_ipv6.c +++++ b/net/ipv6/netfilter/nft_chain_route_ipv6.c ++@@ -33,7 +33,8 @@ static unsigned int nf_route_table_hook( ++ u32 mark, flowlabel; ++ int err; ++ ++- nft_set_pktinfo_ipv6(&pkt, skb, state); +++ nft_set_pktinfo(&pkt, skb, state); +++ nft_set_pktinfo_ipv6(&pkt, skb); ++ ++ /* save source/dest address, mark, hoplimit, flowlabel, priority */ ++ memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); ++--- a/net/netfilter/nf_tables_netdev.c +++++ b/net/netfilter/nf_tables_netdev.c ++@@ -21,15 +21,17 @@ nft_do_chain_netdev(void *priv, struct s ++ { ++ struct nft_pktinfo pkt; ++ +++ nft_set_pktinfo(&pkt, skb, state); +++ ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++- nft_set_pktinfo_ipv4_validate(&pkt, skb, state); +++ nft_set_pktinfo_ipv4_validate(&pkt, skb); ++ break; ++ case htons(ETH_P_IPV6): ++- nft_set_pktinfo_ipv6_validate(&pkt, skb, state); +++ nft_set_pktinfo_ipv6_validate(&pkt, skb); ++ break; ++ default: ++- nft_set_pktinfo_unspec(&pkt, skb, state); +++ nft_set_pktinfo_unspec(&pkt, skb); ++ break; ++ } ++ +diff --git a/target/linux/generic/backport-4.14/301-v4.16-netfilter-core-only-allow-one-nat-hook-per-hook-poin.patch b/target/linux/generic/backport-4.14/301-v4.16-netfilter-core-only-allow-one-nat-hook-per-hook-poin.patch +new file mode 100644 +index 0000000000..80fd3678af +--- /dev/null ++++ b/target/linux/generic/backport-4.14/301-v4.16-netfilter-core-only-allow-one-nat-hook-per-hook-poin.patch +@@ -0,0 +1,146 @@ ++From: Florian Westphal ++Date: Fri, 8 Dec 2017 17:01:54 +0100 ++Subject: [PATCH] netfilter: core: only allow one nat hook per hook point ++ ++The netfilter NAT core cannot deal with more than one NAT hook per hook ++location (prerouting, input ...), because the NAT hooks install a NAT null ++binding in case the iptables nat table (iptable_nat hooks) or the ++corresponding nftables chain (nft nat hooks) doesn't specify a nat ++transformation. ++ ++Null bindings are needed to detect port collsisions between NAT-ed and ++non-NAT-ed connections. ++ ++This causes nftables NAT rules to not work when iptable_nat module is ++loaded, and vice versa because nat binding has already been attached ++when the second nat hook is consulted. ++ ++The netfilter core is not really the correct location to handle this ++(hooks are just hooks, the core has no notion of what kinds of side ++ effects a hook implements), but its the only place where we can check ++for conflicts between both iptables hooks and nftables hooks without ++adding dependencies. ++ ++So add nat annotation to hook_ops to describe those hooks that will ++add NAT bindings and then make core reject if such a hook already exists. ++The annotation fills a padding hole, in case further restrictions appar ++we might change this to a 'u8 type' instead of bool. ++ ++iptables error if nft nat hook active: ++iptables -t nat -A POSTROUTING -j MASQUERADE ++iptables v1.4.21: can't initialize iptables table `nat': File exists ++Perhaps iptables or your kernel needs to be upgraded. ++ ++nftables error if iptables nat table present: ++nft -f /etc/nftables/ipv4-nat ++/usr/etc/nftables/ipv4-nat:3:1-2: Error: Could not process rule: File exists ++table nat { ++^^ ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -67,6 +67,7 @@ struct nf_hook_ops { ++ struct net_device *dev; ++ void *priv; ++ u_int8_t pf; +++ bool nat_hook; ++ unsigned int hooknum; ++ /* Hooks are ordered in ascending priority. */ ++ int priority; ++--- a/net/ipv4/netfilter/iptable_nat.c +++++ b/net/ipv4/netfilter/iptable_nat.c ++@@ -72,6 +72,7 @@ static const struct nf_hook_ops nf_nat_i ++ { ++ .hook = iptable_nat_ipv4_in, ++ .pf = NFPROTO_IPV4, +++ .nat_hook = true, ++ .hooknum = NF_INET_PRE_ROUTING, ++ .priority = NF_IP_PRI_NAT_DST, ++ }, ++@@ -79,6 +80,7 @@ static const struct nf_hook_ops nf_nat_i ++ { ++ .hook = iptable_nat_ipv4_out, ++ .pf = NFPROTO_IPV4, +++ .nat_hook = true, ++ .hooknum = NF_INET_POST_ROUTING, ++ .priority = NF_IP_PRI_NAT_SRC, ++ }, ++@@ -86,6 +88,7 @@ static const struct nf_hook_ops nf_nat_i ++ { ++ .hook = iptable_nat_ipv4_local_fn, ++ .pf = NFPROTO_IPV4, +++ .nat_hook = true, ++ .hooknum = NF_INET_LOCAL_OUT, ++ .priority = NF_IP_PRI_NAT_DST, ++ }, ++@@ -93,6 +96,7 @@ static const struct nf_hook_ops nf_nat_i ++ { ++ .hook = iptable_nat_ipv4_fn, ++ .pf = NFPROTO_IPV4, +++ .nat_hook = true, ++ .hooknum = NF_INET_LOCAL_IN, ++ .priority = NF_IP_PRI_NAT_SRC, ++ }, ++--- a/net/ipv6/netfilter/ip6table_nat.c +++++ b/net/ipv6/netfilter/ip6table_nat.c ++@@ -74,6 +74,7 @@ static const struct nf_hook_ops nf_nat_i ++ { ++ .hook = ip6table_nat_in, ++ .pf = NFPROTO_IPV6, +++ .nat_hook = true, ++ .hooknum = NF_INET_PRE_ROUTING, ++ .priority = NF_IP6_PRI_NAT_DST, ++ }, ++@@ -81,6 +82,7 @@ static const struct nf_hook_ops nf_nat_i ++ { ++ .hook = ip6table_nat_out, ++ .pf = NFPROTO_IPV6, +++ .nat_hook = true, ++ .hooknum = NF_INET_POST_ROUTING, ++ .priority = NF_IP6_PRI_NAT_SRC, ++ }, ++@@ -88,12 +90,14 @@ static const struct nf_hook_ops nf_nat_i ++ { ++ .hook = ip6table_nat_local_fn, ++ .pf = NFPROTO_IPV6, +++ .nat_hook = true, ++ .hooknum = NF_INET_LOCAL_OUT, ++ .priority = NF_IP6_PRI_NAT_DST, ++ }, ++ /* After packet filtering, change source */ ++ { ++ .hook = ip6table_nat_fn, +++ .nat_hook = true, ++ .pf = NFPROTO_IPV6, ++ .hooknum = NF_INET_LOCAL_IN, ++ .priority = NF_IP6_PRI_NAT_SRC, ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -160,6 +160,12 @@ nf_hook_entries_grow(const struct nf_hoo ++ ++i; ++ continue; ++ } +++ +++ if (reg->nat_hook && orig_ops[i]->nat_hook) { +++ kvfree(new); +++ return ERR_PTR(-EEXIST); +++ } +++ ++ if (inserted || reg->priority > orig_ops[i]->priority) { ++ new_ops[nhooks] = (void *)orig_ops[i]; ++ new->hooks[nhooks] = old->hooks[i]; ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -1446,6 +1446,8 @@ static int nf_tables_addchain(struct nft ++ ops->hook = hookfn; ++ if (afi->hook_ops_init) ++ afi->hook_ops_init(ops, i); +++ if (basechain->type->type == NFT_CHAIN_T_NAT) +++ ops->nat_hook = true; ++ } ++ ++ chain->flags |= NFT_BASE_CHAIN; +diff --git a/target/linux/generic/backport-4.14/302-v4.16-netfilter-nf_tables_inet-don-t-use-multihook-infrast.patch b/target/linux/generic/backport-4.14/302-v4.16-netfilter-nf_tables_inet-don-t-use-multihook-infrast.patch +new file mode 100644 +index 0000000000..17d8b21a0f +--- /dev/null ++++ b/target/linux/generic/backport-4.14/302-v4.16-netfilter-nf_tables_inet-don-t-use-multihook-infrast.patch +@@ -0,0 +1,161 @@ ++From: Pablo Neira Ayuso ++Date: Sat, 9 Dec 2017 15:36:24 +0100 ++Subject: [PATCH] netfilter: nf_tables_inet: don't use multihook infrastructure ++ anymore ++ ++Use new native NFPROTO_INET support in netfilter core, this gets rid of ++ad-hoc code in the nf_tables API codebase. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables_ipv4.h +++++ b/include/net/netfilter/nf_tables_ipv4.h ++@@ -53,6 +53,4 @@ static inline void nft_set_pktinfo_ipv4_ ++ nft_set_pktinfo_unspec(pkt, skb); ++ } ++ ++-extern struct nft_af_info nft_af_ipv4; ++- ++ #endif ++--- a/include/net/netfilter/nf_tables_ipv6.h +++++ b/include/net/netfilter/nf_tables_ipv6.h ++@@ -69,6 +69,4 @@ static inline void nft_set_pktinfo_ipv6_ ++ nft_set_pktinfo_unspec(pkt, skb); ++ } ++ ++-extern struct nft_af_info nft_af_ipv6; ++- ++ #endif ++--- a/net/ipv4/netfilter/nf_tables_ipv4.c +++++ b/net/ipv4/netfilter/nf_tables_ipv4.c ++@@ -45,7 +45,7 @@ static unsigned int nft_ipv4_output(void ++ return nft_do_chain_ipv4(priv, skb, state); ++ } ++ ++-struct nft_af_info nft_af_ipv4 __read_mostly = { +++static struct nft_af_info nft_af_ipv4 __read_mostly = { ++ .family = NFPROTO_IPV4, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++@@ -58,7 +58,6 @@ struct nft_af_info nft_af_ipv4 __read_mo ++ [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, ++ }, ++ }; ++-EXPORT_SYMBOL_GPL(nft_af_ipv4); ++ ++ static int nf_tables_ipv4_init_net(struct net *net) ++ { ++--- a/net/ipv6/netfilter/nf_tables_ipv6.c +++++ b/net/ipv6/netfilter/nf_tables_ipv6.c ++@@ -42,7 +42,7 @@ static unsigned int nft_ipv6_output(void ++ return nft_do_chain_ipv6(priv, skb, state); ++ } ++ ++-struct nft_af_info nft_af_ipv6 __read_mostly = { +++static struct nft_af_info nft_af_ipv6 __read_mostly = { ++ .family = NFPROTO_IPV6, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++@@ -55,7 +55,6 @@ struct nft_af_info nft_af_ipv6 __read_mo ++ [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, ++ }, ++ }; ++-EXPORT_SYMBOL_GPL(nft_af_ipv6); ++ ++ static int nf_tables_ipv6_init_net(struct net *net) ++ { ++--- a/net/netfilter/nf_tables_inet.c +++++ b/net/netfilter/nf_tables_inet.c ++@@ -9,6 +9,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -16,26 +17,71 @@ ++ #include ++ #include ++ ++-static void nft_inet_hook_ops_init(struct nf_hook_ops *ops, unsigned int n) +++static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state) ++ { ++- struct nft_af_info *afi; +++ struct nft_pktinfo pkt; ++ ++- if (n == 1) ++- afi = &nft_af_ipv4; ++- else ++- afi = &nft_af_ipv6; ++- ++- ops->pf = afi->family; ++- if (afi->hooks[ops->hooknum]) ++- ops->hook = afi->hooks[ops->hooknum]; +++ nft_set_pktinfo(&pkt, skb, state); +++ +++ switch (state->pf) { +++ case NFPROTO_IPV4: +++ nft_set_pktinfo_ipv4(&pkt, skb); +++ break; +++ case NFPROTO_IPV6: +++ nft_set_pktinfo_ipv6(&pkt, skb); +++ break; +++ default: +++ break; +++ } +++ +++ return nft_do_chain(&pkt, priv); +++} +++ +++static unsigned int nft_inet_output(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ struct nft_pktinfo pkt; +++ +++ nft_set_pktinfo(&pkt, skb, state); +++ +++ switch (state->pf) { +++ case NFPROTO_IPV4: +++ if (unlikely(skb->len < sizeof(struct iphdr) || +++ ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { +++ if (net_ratelimit()) +++ pr_info("ignoring short SOCK_RAW packet\n"); +++ return NF_ACCEPT; +++ } +++ nft_set_pktinfo_ipv4(&pkt, skb); +++ break; +++ case NFPROTO_IPV6: +++ if (unlikely(skb->len < sizeof(struct ipv6hdr))) { +++ if (net_ratelimit()) +++ pr_info("ignoring short SOCK_RAW packet\n"); +++ return NF_ACCEPT; +++ } +++ nft_set_pktinfo_ipv6(&pkt, skb); +++ break; +++ default: +++ break; +++ } +++ +++ return nft_do_chain(&pkt, priv); ++ } ++ ++ static struct nft_af_info nft_af_inet __read_mostly = { ++ .family = NFPROTO_INET, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .nops = 2, ++- .hook_ops_init = nft_inet_hook_ops_init, +++ .nops = 1, +++ .hooks = { +++ [NF_INET_LOCAL_IN] = nft_do_chain_inet, +++ [NF_INET_LOCAL_OUT] = nft_inet_output, +++ [NF_INET_FORWARD] = nft_do_chain_inet, +++ [NF_INET_PRE_ROUTING] = nft_do_chain_inet, +++ [NF_INET_POST_ROUTING] = nft_do_chain_inet, +++ }, ++ }; ++ ++ static int __net_init nf_tables_inet_init_net(struct net *net) +diff --git a/target/linux/generic/backport-4.14/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch b/target/linux/generic/backport-4.14/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch +new file mode 100644 +index 0000000000..f43456a99e +--- /dev/null ++++ b/target/linux/generic/backport-4.14/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch +@@ -0,0 +1,390 @@ ++From: Pablo Neira Ayuso ++Date: Sat, 9 Dec 2017 15:40:25 +0100 ++Subject: [PATCH] netfilter: nf_tables: remove multihook chains and families ++ ++Since NFPROTO_INET is handled from the core, we don't need to maintain ++extra infrastructure in nf_tables to handle the double hook ++registration, one for IPv4 and another for IPv6. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -898,8 +898,6 @@ struct nft_stats { ++ struct u64_stats_sync syncp; ++ }; ++ ++-#define NFT_HOOK_OPS_MAX 2 ++- ++ /** ++ * struct nft_base_chain - nf_tables base chain ++ * ++@@ -911,7 +909,7 @@ struct nft_stats { ++ * @dev_name: device name that this base chain is attached to (if any) ++ */ ++ struct nft_base_chain { ++- struct nf_hook_ops ops[NFT_HOOK_OPS_MAX]; +++ struct nf_hook_ops ops; ++ const struct nf_chain_type *type; ++ u8 policy; ++ u8 flags; ++@@ -972,8 +970,6 @@ enum nft_af_flags { ++ * @owner: module owner ++ * @tables: used internally ++ * @flags: family flags ++- * @nops: number of hook ops in this family ++- * @hook_ops_init: initialization function for chain hook ops ++ * @hooks: hookfn overrides for packet validation ++ */ ++ struct nft_af_info { ++@@ -983,9 +979,6 @@ struct nft_af_info { ++ struct module *owner; ++ struct list_head tables; ++ u32 flags; ++- unsigned int nops; ++- void (*hook_ops_init)(struct nf_hook_ops *, ++- unsigned int); ++ nf_hookfn *hooks[NF_MAX_HOOKS]; ++ }; ++ ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_bridge ++ .family = NFPROTO_BRIDGE, ++ .nhooks = NF_BR_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .nops = 1, ++ .hooks = { ++ [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, ++ [NF_BR_LOCAL_IN] = nft_do_chain_bridge, ++--- a/net/ipv4/netfilter/nf_tables_arp.c +++++ b/net/ipv4/netfilter/nf_tables_arp.c ++@@ -31,7 +31,6 @@ static struct nft_af_info nft_af_arp __r ++ .family = NFPROTO_ARP, ++ .nhooks = NF_ARP_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .nops = 1, ++ .hooks = { ++ [NF_ARP_IN] = nft_do_chain_arp, ++ [NF_ARP_OUT] = nft_do_chain_arp, ++--- a/net/ipv4/netfilter/nf_tables_ipv4.c +++++ b/net/ipv4/netfilter/nf_tables_ipv4.c ++@@ -49,7 +49,6 @@ static struct nft_af_info nft_af_ipv4 __ ++ .family = NFPROTO_IPV4, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .nops = 1, ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, ++ [NF_INET_LOCAL_OUT] = nft_ipv4_output, ++--- a/net/ipv6/netfilter/nf_tables_ipv6.c +++++ b/net/ipv6/netfilter/nf_tables_ipv6.c ++@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_ipv6 __ ++ .family = NFPROTO_IPV6, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .nops = 1, ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, ++ [NF_INET_LOCAL_OUT] = nft_ipv6_output, ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -139,29 +139,26 @@ static void nft_trans_destroy(struct nft ++ kfree(trans); ++ } ++ ++-static int nf_tables_register_hooks(struct net *net, ++- const struct nft_table *table, ++- struct nft_chain *chain, ++- unsigned int hook_nops) +++static int nf_tables_register_hook(struct net *net, +++ const struct nft_table *table, +++ struct nft_chain *chain) ++ { ++ if (table->flags & NFT_TABLE_F_DORMANT || ++ !nft_is_base_chain(chain)) ++ return 0; ++ ++- return nf_register_net_hooks(net, nft_base_chain(chain)->ops, ++- hook_nops); +++ return nf_register_net_hook(net, &nft_base_chain(chain)->ops); ++ } ++ ++-static void nf_tables_unregister_hooks(struct net *net, ++- const struct nft_table *table, ++- struct nft_chain *chain, ++- unsigned int hook_nops) +++static void nf_tables_unregister_hook(struct net *net, +++ const struct nft_table *table, +++ struct nft_chain *chain) ++ { ++ if (table->flags & NFT_TABLE_F_DORMANT || ++ !nft_is_base_chain(chain)) ++ return; ++ ++- nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, hook_nops); +++ nf_unregister_net_hook(net, &nft_base_chain(chain)->ops); ++ } ++ ++ static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) ++@@ -639,8 +636,7 @@ static void _nf_tables_table_disable(str ++ if (cnt && i++ == cnt) ++ break; ++ ++- nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, ++- afi->nops); +++ nf_unregister_net_hook(net, &nft_base_chain(chain)->ops); ++ } ++ } ++ ++@@ -657,8 +653,7 @@ static int nf_tables_table_enable(struct ++ if (!nft_is_base_chain(chain)) ++ continue; ++ ++- err = nf_register_net_hooks(net, nft_base_chain(chain)->ops, ++- afi->nops); +++ err = nf_register_net_hook(net, &nft_base_chain(chain)->ops); ++ if (err < 0) ++ goto err; ++ ++@@ -1070,7 +1065,7 @@ static int nf_tables_fill_chain_info(str ++ ++ if (nft_is_base_chain(chain)) { ++ const struct nft_base_chain *basechain = nft_base_chain(chain); ++- const struct nf_hook_ops *ops = &basechain->ops[0]; +++ const struct nf_hook_ops *ops = &basechain->ops; ++ struct nlattr *nest; ++ ++ nest = nla_nest_start(skb, NFTA_CHAIN_HOOK); ++@@ -1298,8 +1293,8 @@ static void nf_tables_chain_destroy(stru ++ free_percpu(basechain->stats); ++ if (basechain->stats) ++ static_branch_dec(&nft_counters_enabled); ++- if (basechain->ops[0].dev != NULL) ++- dev_put(basechain->ops[0].dev); +++ if (basechain->ops.dev != NULL) +++ dev_put(basechain->ops.dev); ++ kfree(chain->name); ++ kfree(basechain); ++ } else { ++@@ -1395,7 +1390,6 @@ static int nf_tables_addchain(struct nft ++ struct nft_stats __percpu *stats; ++ struct net *net = ctx->net; ++ struct nft_chain *chain; ++- unsigned int i; ++ int err; ++ ++ if (table->use == UINT_MAX) ++@@ -1434,21 +1428,18 @@ static int nf_tables_addchain(struct nft ++ basechain->type = hook.type; ++ chain = &basechain->chain; ++ ++- for (i = 0; i < afi->nops; i++) { ++- ops = &basechain->ops[i]; ++- ops->pf = family; ++- ops->hooknum = hook.num; ++- ops->priority = hook.priority; ++- ops->priv = chain; ++- ops->hook = afi->hooks[ops->hooknum]; ++- ops->dev = hook.dev; ++- if (hookfn) ++- ops->hook = hookfn; ++- if (afi->hook_ops_init) ++- afi->hook_ops_init(ops, i); ++- if (basechain->type->type == NFT_CHAIN_T_NAT) ++- ops->nat_hook = true; ++- } +++ ops = &basechain->ops; +++ ops->pf = family; +++ ops->hooknum = hook.num; +++ ops->priority = hook.priority; +++ ops->priv = chain; +++ ops->hook = afi->hooks[ops->hooknum]; +++ ops->dev = hook.dev; +++ if (hookfn) +++ ops->hook = hookfn; +++ +++ if (basechain->type->type == NFT_CHAIN_T_NAT) +++ ops->nat_hook = true; ++ ++ chain->flags |= NFT_BASE_CHAIN; ++ basechain->policy = policy; ++@@ -1466,7 +1457,7 @@ static int nf_tables_addchain(struct nft ++ goto err1; ++ } ++ ++- err = nf_tables_register_hooks(net, table, chain, afi->nops); +++ err = nf_tables_register_hook(net, table, chain); ++ if (err < 0) ++ goto err1; ++ ++@@ -1480,7 +1471,7 @@ static int nf_tables_addchain(struct nft ++ ++ return 0; ++ err2: ++- nf_tables_unregister_hooks(net, table, chain, afi->nops); +++ nf_tables_unregister_hook(net, table, chain); ++ err1: ++ nf_tables_chain_destroy(chain); ++ ++@@ -1493,13 +1484,12 @@ static int nf_tables_updchain(struct nft ++ const struct nlattr * const *nla = ctx->nla; ++ struct nft_table *table = ctx->table; ++ struct nft_chain *chain = ctx->chain; ++- struct nft_af_info *afi = ctx->afi; ++ struct nft_base_chain *basechain; ++ struct nft_stats *stats = NULL; ++ struct nft_chain_hook hook; ++ struct nf_hook_ops *ops; ++ struct nft_trans *trans; ++- int err, i; +++ int err; ++ ++ if (nla[NFTA_CHAIN_HOOK]) { ++ if (!nft_is_base_chain(chain)) ++@@ -1516,14 +1506,12 @@ static int nf_tables_updchain(struct nft ++ return -EBUSY; ++ } ++ ++- for (i = 0; i < afi->nops; i++) { ++- ops = &basechain->ops[i]; ++- if (ops->hooknum != hook.num || ++- ops->priority != hook.priority || ++- ops->dev != hook.dev) { ++- nft_chain_release_hook(&hook); ++- return -EBUSY; ++- } +++ ops = &basechain->ops; +++ if (ops->hooknum != hook.num || +++ ops->priority != hook.priority || +++ ops->dev != hook.dev) { +++ nft_chain_release_hook(&hook); +++ return -EBUSY; ++ } ++ nft_chain_release_hook(&hook); ++ } ++@@ -5162,10 +5150,9 @@ static int nf_tables_commit(struct net * ++ case NFT_MSG_DELCHAIN: ++ list_del_rcu(&trans->ctx.chain->list); ++ nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN); ++- nf_tables_unregister_hooks(trans->ctx.net, ++- trans->ctx.table, ++- trans->ctx.chain, ++- trans->ctx.afi->nops); +++ nf_tables_unregister_hook(trans->ctx.net, +++ trans->ctx.table, +++ trans->ctx.chain); ++ break; ++ case NFT_MSG_NEWRULE: ++ nft_clear(trans->ctx.net, nft_trans_rule(trans)); ++@@ -5302,10 +5289,9 @@ static int nf_tables_abort(struct net *n ++ } else { ++ trans->ctx.table->use--; ++ list_del_rcu(&trans->ctx.chain->list); ++- nf_tables_unregister_hooks(trans->ctx.net, ++- trans->ctx.table, ++- trans->ctx.chain, ++- trans->ctx.afi->nops); +++ nf_tables_unregister_hook(trans->ctx.net, +++ trans->ctx.table, +++ trans->ctx.chain); ++ } ++ break; ++ case NFT_MSG_DELCHAIN: ++@@ -5408,7 +5394,7 @@ int nft_chain_validate_hooks(const struc ++ if (nft_is_base_chain(chain)) { ++ basechain = nft_base_chain(chain); ++ ++- if ((1 << basechain->ops[0].hooknum) & hook_flags) +++ if ((1 << basechain->ops.hooknum) & hook_flags) ++ return 0; ++ ++ return -EOPNOTSUPP; ++@@ -5890,8 +5876,7 @@ int __nft_release_basechain(struct nft_c ++ ++ BUG_ON(!nft_is_base_chain(ctx->chain)); ++ ++- nf_tables_unregister_hooks(ctx->net, ctx->chain->table, ctx->chain, ++- ctx->afi->nops); +++ nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain); ++ list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { ++ list_del(&rule->list); ++ ctx->chain->use--; ++@@ -5920,8 +5905,7 @@ static void __nft_release_afinfo(struct ++ ++ list_for_each_entry_safe(table, nt, &afi->tables, list) { ++ list_for_each_entry(chain, &table->chains, list) ++- nf_tables_unregister_hooks(net, table, chain, ++- afi->nops); +++ nf_tables_unregister_hook(net, table, chain); ++ /* No packets are walking on these chains anymore. */ ++ ctx.table = table; ++ list_for_each_entry(chain, &table->chains, list) { ++--- a/net/netfilter/nf_tables_inet.c +++++ b/net/netfilter/nf_tables_inet.c ++@@ -74,7 +74,6 @@ static struct nft_af_info nft_af_inet __ ++ .family = NFPROTO_INET, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .nops = 1, ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_inet, ++ [NF_INET_LOCAL_OUT] = nft_inet_output, ++--- a/net/netfilter/nf_tables_netdev.c +++++ b/net/netfilter/nf_tables_netdev.c ++@@ -43,7 +43,6 @@ static struct nft_af_info nft_af_netdev ++ .nhooks = NF_NETDEV_NUMHOOKS, ++ .owner = THIS_MODULE, ++ .flags = NFT_AF_NEEDS_DEV, ++- .nops = 1, ++ .hooks = { ++ [NF_NETDEV_INGRESS] = nft_do_chain_netdev, ++ }, ++@@ -98,7 +97,7 @@ static void nft_netdev_event(unsigned lo ++ __nft_release_basechain(ctx); ++ break; ++ case NETDEV_CHANGENAME: ++- if (dev->ifindex != basechain->ops[0].dev->ifindex) +++ if (dev->ifindex != basechain->ops.dev->ifindex) ++ return; ++ ++ strncpy(basechain->dev_name, dev->name, IFNAMSIZ); ++--- a/net/netfilter/nft_compat.c +++++ b/net/netfilter/nft_compat.c ++@@ -186,7 +186,7 @@ nft_target_set_tgchk_param(struct xt_tgc ++ if (nft_is_base_chain(ctx->chain)) { ++ const struct nft_base_chain *basechain = ++ nft_base_chain(ctx->chain); ++- const struct nf_hook_ops *ops = &basechain->ops[0]; +++ const struct nf_hook_ops *ops = &basechain->ops; ++ ++ par->hook_mask = 1 << ops->hooknum; ++ } else { ++@@ -337,7 +337,7 @@ static int nft_target_validate(const str ++ if (nft_is_base_chain(ctx->chain)) { ++ const struct nft_base_chain *basechain = ++ nft_base_chain(ctx->chain); ++- const struct nf_hook_ops *ops = &basechain->ops[0]; +++ const struct nf_hook_ops *ops = &basechain->ops; ++ ++ hook_mask = 1 << ops->hooknum; ++ if (target->hooks && !(hook_mask & target->hooks)) ++@@ -434,7 +434,7 @@ nft_match_set_mtchk_param(struct xt_mtch ++ if (nft_is_base_chain(ctx->chain)) { ++ const struct nft_base_chain *basechain = ++ nft_base_chain(ctx->chain); ++- const struct nf_hook_ops *ops = &basechain->ops[0]; +++ const struct nf_hook_ops *ops = &basechain->ops; ++ ++ par->hook_mask = 1 << ops->hooknum; ++ } else { ++@@ -586,7 +586,7 @@ static int nft_match_validate(const stru ++ if (nft_is_base_chain(ctx->chain)) { ++ const struct nft_base_chain *basechain = ++ nft_base_chain(ctx->chain); ++- const struct nf_hook_ops *ops = &basechain->ops[0]; +++ const struct nf_hook_ops *ops = &basechain->ops; ++ ++ hook_mask = 1 << ops->hooknum; ++ if (match->hooks && !(hook_mask & match->hooks)) +diff --git a/target/linux/generic/backport-4.14/304-v4.16-netfilter-move-checksum-indirection-to-struct-nf_ipv.patch b/target/linux/generic/backport-4.14/304-v4.16-netfilter-move-checksum-indirection-to-struct-nf_ipv.patch +new file mode 100644 +index 0000000000..07202fe591 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/304-v4.16-netfilter-move-checksum-indirection-to-struct-nf_ipv.patch +@@ -0,0 +1,171 @@ ++From: Pablo Neira Ayuso ++Date: Mon, 27 Nov 2017 21:55:14 +0100 ++Subject: [PATCH] netfilter: move checksum indirection to struct nf_ipv6_ops ++ ++We cannot make a direct call to nf_ip6_checksum() because that would ++result in autoloading the 'ipv6' module because of symbol dependencies. ++Therefore, define checksum indirection in nf_ipv6_ops where this really ++belongs to. ++ ++For IPv4, we can indeed make a direct function call, which is faster, ++given IPv4 is built-in in the networking code by default. Still, ++CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline ++stub for IPv4 in such case. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ create mode 100644 net/netfilter/utils.c ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -311,8 +311,6 @@ struct nf_queue_entry; ++ ++ struct nf_afinfo { ++ unsigned short family; ++- __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, ++- unsigned int dataoff, u_int8_t protocol); ++ __sum16 (*checksum_partial)(struct sk_buff *skb, ++ unsigned int hook, ++ unsigned int dataoff, ++@@ -333,20 +331,9 @@ static inline const struct nf_afinfo *nf ++ return rcu_dereference(nf_afinfo[family]); ++ } ++ ++-static inline __sum16 ++-nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, ++- u_int8_t protocol, unsigned short family) ++-{ ++- const struct nf_afinfo *afinfo; ++- __sum16 csum = 0; ++- ++- rcu_read_lock(); ++- afinfo = nf_get_afinfo(family); ++- if (afinfo) ++- csum = afinfo->checksum(skb, hook, dataoff, protocol); ++- rcu_read_unlock(); ++- return csum; ++-} +++__sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, u_int8_t protocol, +++ unsigned short family); ++ ++ static inline __sum16 ++ nf_checksum_partial(struct sk_buff *skb, unsigned int hook, ++--- a/include/linux/netfilter_ipv4.h +++++ b/include/linux/netfilter_ipv4.h ++@@ -7,6 +7,16 @@ ++ #include ++ ++ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type); +++ +++#ifdef CONFIG_INET ++ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol); +++#else +++static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, u_int8_t protocol) +++{ +++ return 0; +++} +++#endif /* CONFIG_INET */ +++ ++ #endif /*__LINUX_IP_NETFILTER_H*/ ++--- a/include/linux/netfilter_ipv6.h +++++ b/include/linux/netfilter_ipv6.h ++@@ -19,6 +19,8 @@ struct nf_ipv6_ops { ++ void (*route_input)(struct sk_buff *skb); ++ int (*fragment)(struct net *net, struct sock *sk, struct sk_buff *skb, ++ int (*output)(struct net *, struct sock *, struct sk_buff *)); +++ __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, u_int8_t protocol); ++ }; ++ ++ #ifdef CONFIG_NETFILTER ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -106,12 +106,6 @@ static int nf_br_reroute(struct net *net ++ return 0; ++ } ++ ++-static __sum16 nf_br_checksum(struct sk_buff *skb, unsigned int hook, ++- unsigned int dataoff, u_int8_t protocol) ++-{ ++- return 0; ++-} ++- ++ static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol) ++@@ -127,7 +121,6 @@ static int nf_br_route(struct net *net, ++ ++ static const struct nf_afinfo nf_br_afinfo = { ++ .family = AF_BRIDGE, ++- .checksum = nf_br_checksum, ++ .checksum_partial = nf_br_checksum_partial, ++ .route = nf_br_route, ++ .saveroute = nf_br_saveroute, ++--- a/net/ipv4/netfilter.c +++++ b/net/ipv4/netfilter.c ++@@ -188,7 +188,6 @@ static int nf_ip_route(struct net *net, ++ ++ static const struct nf_afinfo nf_ip_afinfo = { ++ .family = AF_INET, ++- .checksum = nf_ip_checksum, ++ .checksum_partial = nf_ip_checksum_partial, ++ .route = nf_ip_route, ++ .saveroute = nf_ip_saveroute, ++--- a/net/ipv6/netfilter.c +++++ b/net/ipv6/netfilter.c ++@@ -196,12 +196,12 @@ static __sum16 nf_ip6_checksum_partial(s ++ static const struct nf_ipv6_ops ipv6ops = { ++ .chk_addr = ipv6_chk_addr, ++ .route_input = ip6_route_input, ++- .fragment = ip6_fragment +++ .fragment = ip6_fragment, +++ .checksum = nf_ip6_checksum, ++ }; ++ ++ static const struct nf_afinfo nf_ip6_afinfo = { ++ .family = AF_INET6, ++- .checksum = nf_ip6_checksum, ++ .checksum_partial = nf_ip6_checksum_partial, ++ .route = nf_ip6_route, ++ .saveroute = nf_ip6_saveroute, ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -1,5 +1,5 @@ ++ # SPDX-License-Identifier: GPL-2.0 ++-netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o +++netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o ++ ++ nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o ++ nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o ++--- /dev/null +++++ b/net/netfilter/utils.c ++@@ -0,0 +1,26 @@ +++#include +++#include +++#include +++#include +++ +++__sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, u_int8_t protocol, +++ unsigned short family) +++{ +++ const struct nf_ipv6_ops *v6ops; +++ __sum16 csum = 0; +++ +++ switch (family) { +++ case AF_INET: +++ csum = nf_ip_checksum(skb, hook, dataoff, protocol); +++ break; +++ case AF_INET6: +++ v6ops = rcu_dereference(nf_ipv6_ops); +++ if (v6ops) +++ csum = v6ops->checksum(skb, hook, dataoff, protocol); +++ break; +++ } +++ +++ return csum; +++} +++EXPORT_SYMBOL_GPL(nf_checksum); +diff --git a/target/linux/generic/backport-4.14/305-v4.16-netfilter-move-checksum_partial-indirection-to-struc.patch b/target/linux/generic/backport-4.14/305-v4.16-netfilter-move-checksum_partial-indirection-to-struc.patch +new file mode 100644 +index 0000000000..39f5564404 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/305-v4.16-netfilter-move-checksum_partial-indirection-to-struc.patch +@@ -0,0 +1,204 @@ ++From: Pablo Neira Ayuso ++Date: Wed, 20 Dec 2017 16:04:18 +0100 ++Subject: [PATCH] netfilter: move checksum_partial indirection to struct ++ nf_ipv6_ops ++ ++We cannot make a direct call to nf_ip6_checksum_partial() because that ++would result in autoloading the 'ipv6' module because of symbol ++dependencies. Therefore, define checksum_partial indirection in ++nf_ipv6_ops where this really belongs to. ++ ++For IPv4, we can indeed make a direct function call, which is faster, ++given IPv4 is built-in in the networking code by default. Still, ++CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline ++stub for IPv4 in such case. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -311,11 +311,6 @@ struct nf_queue_entry; ++ ++ struct nf_afinfo { ++ unsigned short family; ++- __sum16 (*checksum_partial)(struct sk_buff *skb, ++- unsigned int hook, ++- unsigned int dataoff, ++- unsigned int len, ++- u_int8_t protocol); ++ int (*route)(struct net *net, struct dst_entry **dst, ++ struct flowi *fl, bool strict); ++ void (*saveroute)(const struct sk_buff *skb, ++@@ -335,22 +330,9 @@ __sum16 nf_checksum(struct sk_buff *skb, ++ unsigned int dataoff, u_int8_t protocol, ++ unsigned short family); ++ ++-static inline __sum16 ++-nf_checksum_partial(struct sk_buff *skb, unsigned int hook, ++- unsigned int dataoff, unsigned int len, ++- u_int8_t protocol, unsigned short family) ++-{ ++- const struct nf_afinfo *afinfo; ++- __sum16 csum = 0; ++- ++- rcu_read_lock(); ++- afinfo = nf_get_afinfo(family); ++- if (afinfo) ++- csum = afinfo->checksum_partial(skb, hook, dataoff, len, ++- protocol); ++- rcu_read_unlock(); ++- return csum; ++-} +++__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, unsigned int len, +++ u_int8_t protocol, unsigned short family); ++ ++ int nf_register_afinfo(const struct nf_afinfo *afinfo); ++ void nf_unregister_afinfo(const struct nf_afinfo *afinfo); ++--- a/include/linux/netfilter_ipv4.h +++++ b/include/linux/netfilter_ipv4.h ++@@ -11,12 +11,23 @@ int ip_route_me_harder(struct net *net, ++ #ifdef CONFIG_INET ++ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol); +++__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, unsigned int len, +++ u_int8_t protocol); ++ #else ++ static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol) ++ { ++ return 0; ++ } +++static inline __sum16 nf_ip_checksum_partial(struct sk_buff *skb, +++ unsigned int hook, +++ unsigned int dataoff, +++ unsigned int len, +++ u_int8_t protocol) +++{ +++ return 0; +++} ++ #endif /* CONFIG_INET */ ++ ++ #endif /*__LINUX_IP_NETFILTER_H*/ ++--- a/include/linux/netfilter_ipv6.h +++++ b/include/linux/netfilter_ipv6.h ++@@ -21,6 +21,9 @@ struct nf_ipv6_ops { ++ int (*output)(struct net *, struct sock *, struct sk_buff *)); ++ __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol); +++ __sum16 (*checksum_partial)(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, unsigned int len, +++ u_int8_t protocol); ++ }; ++ ++ #ifdef CONFIG_NETFILTER ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -106,13 +106,6 @@ static int nf_br_reroute(struct net *net ++ return 0; ++ } ++ ++-static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook, ++- unsigned int dataoff, unsigned int len, ++- u_int8_t protocol) ++-{ ++- return 0; ++-} ++- ++ static int nf_br_route(struct net *net, struct dst_entry **dst, ++ struct flowi *fl, bool strict __always_unused) ++ { ++@@ -121,7 +114,6 @@ static int nf_br_route(struct net *net, ++ ++ static const struct nf_afinfo nf_br_afinfo = { ++ .family = AF_BRIDGE, ++- .checksum_partial = nf_br_checksum_partial, ++ .route = nf_br_route, ++ .saveroute = nf_br_saveroute, ++ .reroute = nf_br_reroute, ++--- a/net/ipv4/netfilter.c +++++ b/net/ipv4/netfilter.c ++@@ -155,9 +155,9 @@ __sum16 nf_ip_checksum(struct sk_buff *s ++ } ++ EXPORT_SYMBOL(nf_ip_checksum); ++ ++-static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, ++- unsigned int dataoff, unsigned int len, ++- u_int8_t protocol) +++__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, unsigned int len, +++ u_int8_t protocol) ++ { ++ const struct iphdr *iph = ip_hdr(skb); ++ __sum16 csum = 0; ++@@ -175,6 +175,7 @@ static __sum16 nf_ip_checksum_partial(st ++ } ++ return csum; ++ } +++EXPORT_SYMBOL_GPL(nf_ip_checksum_partial); ++ ++ static int nf_ip_route(struct net *net, struct dst_entry **dst, ++ struct flowi *fl, bool strict __always_unused) ++@@ -188,7 +189,6 @@ static int nf_ip_route(struct net *net, ++ ++ static const struct nf_afinfo nf_ip_afinfo = { ++ .family = AF_INET, ++- .checksum_partial = nf_ip_checksum_partial, ++ .route = nf_ip_route, ++ .saveroute = nf_ip_saveroute, ++ .reroute = nf_ip_reroute, ++--- a/net/ipv6/netfilter.c +++++ b/net/ipv6/netfilter.c ++@@ -194,15 +194,15 @@ static __sum16 nf_ip6_checksum_partial(s ++ }; ++ ++ static const struct nf_ipv6_ops ipv6ops = { ++- .chk_addr = ipv6_chk_addr, ++- .route_input = ip6_route_input, ++- .fragment = ip6_fragment, ++- .checksum = nf_ip6_checksum, +++ .chk_addr = ipv6_chk_addr, +++ .route_input = ip6_route_input, +++ .fragment = ip6_fragment, +++ .checksum = nf_ip6_checksum, +++ .checksum_partial = nf_ip6_checksum_partial, ++ }; ++ ++ static const struct nf_afinfo nf_ip6_afinfo = { ++ .family = AF_INET6, ++- .checksum_partial = nf_ip6_checksum_partial, ++ .route = nf_ip6_route, ++ .saveroute = nf_ip6_saveroute, ++ .reroute = nf_ip6_reroute, ++--- a/net/netfilter/utils.c +++++ b/net/netfilter/utils.c ++@@ -24,3 +24,27 @@ __sum16 nf_checksum(struct sk_buff *skb, ++ return csum; ++ } ++ EXPORT_SYMBOL_GPL(nf_checksum); +++ +++__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook, +++ unsigned int dataoff, unsigned int len, +++ u_int8_t protocol, unsigned short family) +++{ +++ const struct nf_ipv6_ops *v6ops; +++ __sum16 csum = 0; +++ +++ switch (family) { +++ case AF_INET: +++ csum = nf_ip_checksum_partial(skb, hook, dataoff, len, +++ protocol); +++ break; +++ case AF_INET6: +++ v6ops = rcu_dereference(nf_ipv6_ops); +++ if (v6ops) +++ csum = v6ops->checksum_partial(skb, hook, dataoff, len, +++ protocol); +++ break; +++ } +++ +++ return csum; +++} +++EXPORT_SYMBOL_GPL(nf_checksum_partial); +diff --git a/target/linux/generic/backport-4.14/306-v4.16-netfilter-remove-saveroute-indirection-in-struct-nf_.patch b/target/linux/generic/backport-4.14/306-v4.16-netfilter-remove-saveroute-indirection-in-struct-nf_.patch +new file mode 100644 +index 0000000000..943b3eed30 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/306-v4.16-netfilter-remove-saveroute-indirection-in-struct-nf_.patch +@@ -0,0 +1,232 @@ ++From: Pablo Neira Ayuso ++Date: Wed, 20 Dec 2017 16:12:55 +0100 ++Subject: [PATCH] netfilter: remove saveroute indirection in struct nf_afinfo ++ ++This is only used by nf_queue.c and this function comes with no symbol ++dependencies with IPv6, it just refers to structure layouts. Therefore, ++we can replace it by a direct function call from where it belongs. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -313,8 +313,6 @@ struct nf_afinfo { ++ unsigned short family; ++ int (*route)(struct net *net, struct dst_entry **dst, ++ struct flowi *fl, bool strict); ++- void (*saveroute)(const struct sk_buff *skb, ++- struct nf_queue_entry *entry); ++ int (*reroute)(struct net *net, struct sk_buff *skb, ++ const struct nf_queue_entry *entry); ++ int route_key_size; ++--- a/include/linux/netfilter_ipv4.h +++++ b/include/linux/netfilter_ipv4.h ++@@ -6,6 +6,16 @@ ++ ++ #include ++ +++/* Extra routing may needed on local out, as the QUEUE target never returns +++ * control to the table. +++ */ +++struct ip_rt_info { +++ __be32 daddr; +++ __be32 saddr; +++ u_int8_t tos; +++ u_int32_t mark; +++}; +++ ++ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type); ++ ++ #ifdef CONFIG_INET ++--- a/include/linux/netfilter_ipv6.h +++++ b/include/linux/netfilter_ipv6.h ++@@ -9,6 +9,15 @@ ++ ++ #include ++ +++/* Extra routing may needed on local out, as the QUEUE target never returns +++ * control to the table. +++ */ +++struct ip6_rt_info { +++ struct in6_addr daddr; +++ struct in6_addr saddr; +++ u_int32_t mark; +++}; +++ ++ /* ++ * Hook functions for ipv6 to allow xt_* modules to be built-in even ++ * if IPv6 is a module. ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -95,11 +95,6 @@ static const struct nf_chain_type filter ++ (1 << NF_BR_POST_ROUTING), ++ }; ++ ++-static void nf_br_saveroute(const struct sk_buff *skb, ++- struct nf_queue_entry *entry) ++-{ ++-} ++- ++ static int nf_br_reroute(struct net *net, struct sk_buff *skb, ++ const struct nf_queue_entry *entry) ++ { ++@@ -115,7 +110,6 @@ static int nf_br_route(struct net *net, ++ static const struct nf_afinfo nf_br_afinfo = { ++ .family = AF_BRIDGE, ++ .route = nf_br_route, ++- .saveroute = nf_br_saveroute, ++ .reroute = nf_br_reroute, ++ .route_key_size = 0, ++ }; ++--- a/net/ipv4/netfilter.c +++++ b/net/ipv4/netfilter.c ++@@ -80,33 +80,6 @@ int ip_route_me_harder(struct net *net, ++ } ++ EXPORT_SYMBOL(ip_route_me_harder); ++ ++-/* ++- * Extra routing may needed on local out, as the QUEUE target never ++- * returns control to the table. ++- */ ++- ++-struct ip_rt_info { ++- __be32 daddr; ++- __be32 saddr; ++- u_int8_t tos; ++- u_int32_t mark; ++-}; ++- ++-static void nf_ip_saveroute(const struct sk_buff *skb, ++- struct nf_queue_entry *entry) ++-{ ++- struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); ++- ++- if (entry->state.hook == NF_INET_LOCAL_OUT) { ++- const struct iphdr *iph = ip_hdr(skb); ++- ++- rt_info->tos = iph->tos; ++- rt_info->daddr = iph->daddr; ++- rt_info->saddr = iph->saddr; ++- rt_info->mark = skb->mark; ++- } ++-} ++- ++ static int nf_ip_reroute(struct net *net, struct sk_buff *skb, ++ const struct nf_queue_entry *entry) ++ { ++@@ -190,7 +163,6 @@ static int nf_ip_route(struct net *net, ++ static const struct nf_afinfo nf_ip_afinfo = { ++ .family = AF_INET, ++ .route = nf_ip_route, ++- .saveroute = nf_ip_saveroute, ++ .reroute = nf_ip_reroute, ++ .route_key_size = sizeof(struct ip_rt_info), ++ }; ++--- a/net/ipv6/netfilter.c +++++ b/net/ipv6/netfilter.c ++@@ -72,31 +72,6 @@ int ip6_route_me_harder(struct net *net, ++ } ++ EXPORT_SYMBOL(ip6_route_me_harder); ++ ++-/* ++- * Extra routing may needed on local out, as the QUEUE target never ++- * returns control to the table. ++- */ ++- ++-struct ip6_rt_info { ++- struct in6_addr daddr; ++- struct in6_addr saddr; ++- u_int32_t mark; ++-}; ++- ++-static void nf_ip6_saveroute(const struct sk_buff *skb, ++- struct nf_queue_entry *entry) ++-{ ++- struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); ++- ++- if (entry->state.hook == NF_INET_LOCAL_OUT) { ++- const struct ipv6hdr *iph = ipv6_hdr(skb); ++- ++- rt_info->daddr = iph->daddr; ++- rt_info->saddr = iph->saddr; ++- rt_info->mark = skb->mark; ++- } ++-} ++- ++ static int nf_ip6_reroute(struct net *net, struct sk_buff *skb, ++ const struct nf_queue_entry *entry) ++ { ++@@ -204,7 +179,6 @@ static const struct nf_ipv6_ops ipv6ops ++ static const struct nf_afinfo nf_ip6_afinfo = { ++ .family = AF_INET6, ++ .route = nf_ip6_route, ++- .saveroute = nf_ip6_saveroute, ++ .reroute = nf_ip6_reroute, ++ .route_key_size = sizeof(struct ip6_rt_info), ++ }; ++--- a/net/netfilter/nf_queue.c +++++ b/net/netfilter/nf_queue.c ++@@ -10,6 +10,8 @@ ++ #include ++ #include ++ #include +++#include +++#include ++ #include ++ #include ++ #include ++@@ -108,6 +110,35 @@ void nf_queue_nf_hook_drop(struct net *n ++ } ++ EXPORT_SYMBOL_GPL(nf_queue_nf_hook_drop); ++ +++static void nf_ip_saveroute(const struct sk_buff *skb, +++ struct nf_queue_entry *entry) +++{ +++ struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); +++ +++ if (entry->state.hook == NF_INET_LOCAL_OUT) { +++ const struct iphdr *iph = ip_hdr(skb); +++ +++ rt_info->tos = iph->tos; +++ rt_info->daddr = iph->daddr; +++ rt_info->saddr = iph->saddr; +++ rt_info->mark = skb->mark; +++ } +++} +++ +++static void nf_ip6_saveroute(const struct sk_buff *skb, +++ struct nf_queue_entry *entry) +++{ +++ struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); +++ +++ if (entry->state.hook == NF_INET_LOCAL_OUT) { +++ const struct ipv6hdr *iph = ipv6_hdr(skb); +++ +++ rt_info->daddr = iph->daddr; +++ rt_info->saddr = iph->saddr; +++ rt_info->mark = skb->mark; +++ } +++} +++ ++ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, ++ const struct nf_hook_entries *entries, ++ unsigned int index, unsigned int queuenum) ++@@ -148,7 +179,16 @@ static int __nf_queue(struct sk_buff *sk ++ }; ++ ++ nf_queue_entry_get_refs(entry); ++- afinfo->saveroute(skb, entry); +++ +++ switch (entry->state.pf) { +++ case AF_INET: +++ nf_ip_saveroute(skb, entry); +++ break; +++ case AF_INET6: +++ nf_ip6_saveroute(skb, entry); +++ break; +++ } +++ ++ status = qh->outfn(entry, queuenum); ++ ++ if (status < 0) { +diff --git a/target/linux/generic/backport-4.14/307-v4.16-netfilter-move-route-indirection-to-struct-nf_ipv6_o.patch b/target/linux/generic/backport-4.14/307-v4.16-netfilter-move-route-indirection-to-struct-nf_ipv6_o.patch +new file mode 100644 +index 0000000000..a594f87cd9 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/307-v4.16-netfilter-move-route-indirection-to-struct-nf_ipv6_o.patch +@@ -0,0 +1,349 @@ ++From: Pablo Neira Ayuso ++Date: Mon, 27 Nov 2017 22:29:52 +0100 ++Subject: [PATCH] netfilter: move route indirection to struct nf_ipv6_ops ++ ++We cannot make a direct call to nf_ip6_route() because that would result ++in autoloading the 'ipv6' module because of symbol dependencies. ++Therefore, define route indirection in nf_ipv6_ops where this really ++belongs to. ++ ++For IPv4, we can indeed make a direct function call, which is faster, ++given IPv4 is built-in in the networking code by default. Still, ++CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline ++stub for IPv4 in such case. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -311,8 +311,6 @@ struct nf_queue_entry; ++ ++ struct nf_afinfo { ++ unsigned short family; ++- int (*route)(struct net *net, struct dst_entry **dst, ++- struct flowi *fl, bool strict); ++ int (*reroute)(struct net *net, struct sk_buff *skb, ++ const struct nf_queue_entry *entry); ++ int route_key_size; ++@@ -331,6 +329,8 @@ __sum16 nf_checksum(struct sk_buff *skb, ++ __sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol, unsigned short family); +++int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, +++ bool strict, unsigned short family); ++ ++ int nf_register_afinfo(const struct nf_afinfo *afinfo); ++ void nf_unregister_afinfo(const struct nf_afinfo *afinfo); ++--- a/include/linux/netfilter_ipv4.h +++++ b/include/linux/netfilter_ipv4.h ++@@ -24,6 +24,8 @@ __sum16 nf_ip_checksum(struct sk_buff *s ++ __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol); +++int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl, +++ bool strict); ++ #else ++ static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol) ++@@ -38,6 +40,11 @@ static inline __sum16 nf_ip_checksum_par ++ { ++ return 0; ++ } +++static inline int nf_ip_route(struct net *net, struct dst_entry **dst, +++ struct flowi *fl, bool strict) +++{ +++ return -EOPNOTSUPP; +++} ++ #endif /* CONFIG_INET */ ++ ++ #endif /*__LINUX_IP_NETFILTER_H*/ ++--- a/include/linux/netfilter_ipv6.h +++++ b/include/linux/netfilter_ipv6.h ++@@ -33,6 +33,8 @@ struct nf_ipv6_ops { ++ __sum16 (*checksum_partial)(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol); +++ int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl, +++ bool strict); ++ }; ++ ++ #ifdef CONFIG_NETFILTER ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -101,15 +101,8 @@ static int nf_br_reroute(struct net *net ++ return 0; ++ } ++ ++-static int nf_br_route(struct net *net, struct dst_entry **dst, ++- struct flowi *fl, bool strict __always_unused) ++-{ ++- return 0; ++-} ++- ++ static const struct nf_afinfo nf_br_afinfo = { ++ .family = AF_BRIDGE, ++- .route = nf_br_route, ++ .reroute = nf_br_reroute, ++ .route_key_size = 0, ++ }; ++--- a/net/ipv4/netfilter.c +++++ b/net/ipv4/netfilter.c ++@@ -150,8 +150,8 @@ __sum16 nf_ip_checksum_partial(struct sk ++ } ++ EXPORT_SYMBOL_GPL(nf_ip_checksum_partial); ++ ++-static int nf_ip_route(struct net *net, struct dst_entry **dst, ++- struct flowi *fl, bool strict __always_unused) +++int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl, +++ bool strict __always_unused) ++ { ++ struct rtable *rt = ip_route_output_key(net, &fl->u.ip4); ++ if (IS_ERR(rt)) ++@@ -159,10 +159,10 @@ static int nf_ip_route(struct net *net, ++ *dst = &rt->dst; ++ return 0; ++ } +++EXPORT_SYMBOL_GPL(nf_ip_route); ++ ++ static const struct nf_afinfo nf_ip_afinfo = { ++ .family = AF_INET, ++- .route = nf_ip_route, ++ .reroute = nf_ip_reroute, ++ .route_key_size = sizeof(struct ip_rt_info), ++ }; ++--- a/net/ipv6/netfilter.c +++++ b/net/ipv6/netfilter.c ++@@ -174,11 +174,11 @@ static const struct nf_ipv6_ops ipv6ops ++ .fragment = ip6_fragment, ++ .checksum = nf_ip6_checksum, ++ .checksum_partial = nf_ip6_checksum_partial, +++ .route = nf_ip6_route, ++ }; ++ ++ static const struct nf_afinfo nf_ip6_afinfo = { ++ .family = AF_INET6, ++- .route = nf_ip6_route, ++ .reroute = nf_ip6_reroute, ++ .route_key_size = sizeof(struct ip6_rt_info), ++ }; ++--- a/net/ipv6/netfilter/nft_fib_ipv6.c +++++ b/net/ipv6/netfilter/nft_fib_ipv6.c ++@@ -60,7 +60,6 @@ static u32 __nft_fib6_eval_type(const st ++ { ++ const struct net_device *dev = NULL; ++ const struct nf_ipv6_ops *v6ops; ++- const struct nf_afinfo *afinfo; ++ int route_err, addrtype; ++ struct rt6_info *rt; ++ struct flowi6 fl6 = { ++@@ -69,8 +68,8 @@ static u32 __nft_fib6_eval_type(const st ++ }; ++ u32 ret = 0; ++ ++- afinfo = nf_get_afinfo(NFPROTO_IPV6); ++- if (!afinfo) +++ v6ops = nf_get_ipv6_ops(); +++ if (!v6ops) ++ return RTN_UNREACHABLE; ++ ++ if (priv->flags & NFTA_FIB_F_IIF) ++@@ -80,12 +79,11 @@ static u32 __nft_fib6_eval_type(const st ++ ++ nft_fib6_flowi_init(&fl6, priv, pkt, dev, iph); ++ ++- v6ops = nf_get_ipv6_ops(); ++- if (dev && v6ops && v6ops->chk_addr(nft_net(pkt), &fl6.daddr, dev, true)) +++ if (dev && v6ops->chk_addr(nft_net(pkt), &fl6.daddr, dev, true)) ++ ret = RTN_LOCAL; ++ ++- route_err = afinfo->route(nft_net(pkt), (struct dst_entry **)&rt, ++- flowi6_to_flowi(&fl6), false); +++ route_err = v6ops->route(nft_net(pkt), (struct dst_entry **)&rt, +++ flowi6_to_flowi(&fl6), false); ++ if (route_err) ++ goto err; ++ ++--- a/net/netfilter/nf_conntrack_h323_main.c +++++ b/net/netfilter/nf_conntrack_h323_main.c ++@@ -24,6 +24,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include ++ #include ++@@ -732,14 +733,8 @@ static int callforward_do_filter(struct ++ const union nf_inet_addr *dst, ++ u_int8_t family) ++ { ++- const struct nf_afinfo *afinfo; ++ int ret = 0; ++ ++- /* rcu_read_lock()ed by nf_hook_thresh */ ++- afinfo = nf_get_afinfo(family); ++- if (!afinfo) ++- return 0; ++- ++ switch (family) { ++ case AF_INET: { ++ struct flowi4 fl1, fl2; ++@@ -750,10 +745,10 @@ static int callforward_do_filter(struct ++ ++ memset(&fl2, 0, sizeof(fl2)); ++ fl2.daddr = dst->ip; ++- if (!afinfo->route(net, (struct dst_entry **)&rt1, ++- flowi4_to_flowi(&fl1), false)) { ++- if (!afinfo->route(net, (struct dst_entry **)&rt2, ++- flowi4_to_flowi(&fl2), false)) { +++ if (!nf_ip_route(net, (struct dst_entry **)&rt1, +++ flowi4_to_flowi(&fl1), false)) { +++ if (!nf_ip_route(net, (struct dst_entry **)&rt2, +++ flowi4_to_flowi(&fl2), false)) { ++ if (rt_nexthop(rt1, fl1.daddr) == ++ rt_nexthop(rt2, fl2.daddr) && ++ rt1->dst.dev == rt2->dst.dev) ++@@ -766,18 +761,23 @@ static int callforward_do_filter(struct ++ } ++ #if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) ++ case AF_INET6: { ++- struct flowi6 fl1, fl2; +++ const struct nf_ipv6_ops *v6ops; ++ struct rt6_info *rt1, *rt2; +++ struct flowi6 fl1, fl2; +++ +++ v6ops = nf_get_ipv6_ops(); +++ if (!v6ops) +++ return 0; ++ ++ memset(&fl1, 0, sizeof(fl1)); ++ fl1.daddr = src->in6; ++ ++ memset(&fl2, 0, sizeof(fl2)); ++ fl2.daddr = dst->in6; ++- if (!afinfo->route(net, (struct dst_entry **)&rt1, ++- flowi6_to_flowi(&fl1), false)) { ++- if (!afinfo->route(net, (struct dst_entry **)&rt2, ++- flowi6_to_flowi(&fl2), false)) { +++ if (!v6ops->route(net, (struct dst_entry **)&rt1, +++ flowi6_to_flowi(&fl1), false)) { +++ if (!v6ops->route(net, (struct dst_entry **)&rt2, +++ flowi6_to_flowi(&fl2), false)) { ++ if (ipv6_addr_equal(rt6_nexthop(rt1, &fl1.daddr), ++ rt6_nexthop(rt2, &fl2.daddr)) && ++ rt1->dst.dev == rt2->dst.dev) ++--- a/net/netfilter/nft_rt.c +++++ b/net/netfilter/nft_rt.c ++@@ -27,7 +27,7 @@ static u16 get_tcpmss(const struct nft_p ++ { ++ u32 minlen = sizeof(struct ipv6hdr), mtu = dst_mtu(skbdst); ++ const struct sk_buff *skb = pkt->skb; ++- const struct nf_afinfo *ai; +++ struct dst_entry *dst = NULL; ++ struct flowi fl; ++ ++ memset(&fl, 0, sizeof(fl)); ++@@ -43,15 +43,10 @@ static u16 get_tcpmss(const struct nft_p ++ break; ++ } ++ ++- ai = nf_get_afinfo(nft_pf(pkt)); ++- if (ai) { ++- struct dst_entry *dst = NULL; ++- ++- ai->route(nft_net(pkt), &dst, &fl, false); ++- if (dst) { ++- mtu = min(mtu, dst_mtu(dst)); ++- dst_release(dst); ++- } +++ nf_route(nft_net(pkt), &dst, &fl, false, nft_pf(pkt)); +++ if (dst) { +++ mtu = min(mtu, dst_mtu(dst)); +++ dst_release(dst); ++ } ++ ++ if (mtu <= minlen || mtu > 0xffff) ++--- a/net/netfilter/utils.c +++++ b/net/netfilter/utils.c ++@@ -48,3 +48,24 @@ __sum16 nf_checksum_partial(struct sk_bu ++ return csum; ++ } ++ EXPORT_SYMBOL_GPL(nf_checksum_partial); +++ +++int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, +++ bool strict, unsigned short family) +++{ +++ const struct nf_ipv6_ops *v6ops; +++ int ret = 0; +++ +++ switch (family) { +++ case AF_INET: +++ ret = nf_ip_route(net, dst, fl, strict); +++ break; +++ case AF_INET6: +++ v6ops = rcu_dereference(nf_ipv6_ops); +++ if (v6ops) +++ ret = v6ops->route(net, dst, fl, strict); +++ break; +++ } +++ +++ return ret; +++} +++EXPORT_SYMBOL_GPL(nf_route); ++--- a/net/netfilter/xt_TCPMSS.c +++++ b/net/netfilter/xt_TCPMSS.c ++@@ -48,7 +48,6 @@ static u_int32_t tcpmss_reverse_mtu(stru ++ unsigned int family) ++ { ++ struct flowi fl; ++- const struct nf_afinfo *ai; ++ struct rtable *rt = NULL; ++ u_int32_t mtu = ~0U; ++ ++@@ -62,10 +61,8 @@ static u_int32_t tcpmss_reverse_mtu(stru ++ memset(fl6, 0, sizeof(*fl6)); ++ fl6->daddr = ipv6_hdr(skb)->saddr; ++ } ++- ai = nf_get_afinfo(family); ++- if (ai != NULL) ++- ai->route(net, (struct dst_entry **)&rt, &fl, false); ++ +++ nf_route(net, (struct dst_entry **)&rt, &fl, false, family); ++ if (rt != NULL) { ++ mtu = dst_mtu(&rt->dst); ++ dst_release(&rt->dst); ++--- a/net/netfilter/xt_addrtype.c +++++ b/net/netfilter/xt_addrtype.c ++@@ -36,7 +36,7 @@ MODULE_ALIAS("ip6t_addrtype"); ++ static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, ++ const struct in6_addr *addr, u16 mask) ++ { ++- const struct nf_afinfo *afinfo; +++ const struct nf_ipv6_ops *v6ops; ++ struct flowi6 flow; ++ struct rt6_info *rt; ++ u32 ret = 0; ++@@ -47,17 +47,14 @@ static u32 match_lookup_rt6(struct net * ++ if (dev) ++ flow.flowi6_oif = dev->ifindex; ++ ++- afinfo = nf_get_afinfo(NFPROTO_IPV6); ++- if (afinfo != NULL) { ++- const struct nf_ipv6_ops *v6ops; ++- +++ v6ops = nf_get_ipv6_ops(); +++ if (v6ops) { ++ if (dev && (mask & XT_ADDRTYPE_LOCAL)) { ++- v6ops = nf_get_ipv6_ops(); ++- if (v6ops && v6ops->chk_addr(net, addr, dev, true)) +++ if (v6ops->chk_addr(net, addr, dev, true)) ++ ret = XT_ADDRTYPE_LOCAL; ++ } ++- route_err = afinfo->route(net, (struct dst_entry **)&rt, ++- flowi6_to_flowi(&flow), false); +++ route_err = v6ops->route(net, (struct dst_entry **)&rt, +++ flowi6_to_flowi(&flow), false); ++ } else { ++ route_err = 1; ++ } +diff --git a/target/linux/generic/backport-4.14/308-v4.16-netfilter-move-reroute-indirection-to-struct-nf_ipv6.patch b/target/linux/generic/backport-4.14/308-v4.16-netfilter-move-reroute-indirection-to-struct-nf_ipv6.patch +new file mode 100644 +index 0000000000..810f57ca19 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/308-v4.16-netfilter-move-reroute-indirection-to-struct-nf_ipv6.patch +@@ -0,0 +1,223 @@ ++From: Pablo Neira Ayuso ++Date: Mon, 27 Nov 2017 22:50:26 +0100 ++Subject: [PATCH] netfilter: move reroute indirection to struct nf_ipv6_ops ++ ++We cannot make a direct call to nf_ip6_reroute() because that would result ++in autoloading the 'ipv6' module because of symbol dependencies. ++Therefore, define reroute indirection in nf_ipv6_ops where this really ++belongs to. ++ ++For IPv4, we can indeed make a direct function call, which is faster, ++given IPv4 is built-in in the networking code by default. Still, ++CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline ++stub for IPv4 in such case. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -311,8 +311,6 @@ struct nf_queue_entry; ++ ++ struct nf_afinfo { ++ unsigned short family; ++- int (*reroute)(struct net *net, struct sk_buff *skb, ++- const struct nf_queue_entry *entry); ++ int route_key_size; ++ }; ++ ++@@ -331,6 +329,7 @@ __sum16 nf_checksum_partial(struct sk_bu ++ u_int8_t protocol, unsigned short family); ++ int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, ++ bool strict, unsigned short family); +++int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry); ++ ++ int nf_register_afinfo(const struct nf_afinfo *afinfo); ++ void nf_unregister_afinfo(const struct nf_afinfo *afinfo); ++--- a/include/linux/netfilter_ipv4.h +++++ b/include/linux/netfilter_ipv4.h ++@@ -18,6 +18,8 @@ struct ip_rt_info { ++ ++ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type); ++ +++struct nf_queue_entry; +++ ++ #ifdef CONFIG_INET ++ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol); ++@@ -26,6 +28,7 @@ __sum16 nf_ip_checksum_partial(struct sk ++ u_int8_t protocol); ++ int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl, ++ bool strict); +++int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry); ++ #else ++ static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol) ++@@ -45,6 +48,11 @@ static inline int nf_ip_route(struct net ++ { ++ return -EOPNOTSUPP; ++ } +++static inline int nf_ip_reroute(struct sk_buff *skb, +++ const struct nf_queue_entry *entry) +++{ +++ return -EOPNOTSUPP; +++} ++ #endif /* CONFIG_INET */ ++ ++ #endif /*__LINUX_IP_NETFILTER_H*/ ++--- a/include/linux/netfilter_ipv6.h +++++ b/include/linux/netfilter_ipv6.h ++@@ -18,6 +18,8 @@ struct ip6_rt_info { ++ u_int32_t mark; ++ }; ++ +++struct nf_queue_entry; +++ ++ /* ++ * Hook functions for ipv6 to allow xt_* modules to be built-in even ++ * if IPv6 is a module. ++@@ -35,6 +37,7 @@ struct nf_ipv6_ops { ++ u_int8_t protocol); ++ int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl, ++ bool strict); +++ int (*reroute)(struct sk_buff *skb, const struct nf_queue_entry *entry); ++ }; ++ ++ #ifdef CONFIG_NETFILTER ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -95,15 +95,8 @@ static const struct nf_chain_type filter ++ (1 << NF_BR_POST_ROUTING), ++ }; ++ ++-static int nf_br_reroute(struct net *net, struct sk_buff *skb, ++- const struct nf_queue_entry *entry) ++-{ ++- return 0; ++-} ++- ++ static const struct nf_afinfo nf_br_afinfo = { ++ .family = AF_BRIDGE, ++- .reroute = nf_br_reroute, ++ .route_key_size = 0, ++ }; ++ ++--- a/net/ipv4/netfilter.c +++++ b/net/ipv4/netfilter.c ++@@ -80,8 +80,7 @@ int ip_route_me_harder(struct net *net, ++ } ++ EXPORT_SYMBOL(ip_route_me_harder); ++ ++-static int nf_ip_reroute(struct net *net, struct sk_buff *skb, ++- const struct nf_queue_entry *entry) +++int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry) ++ { ++ const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); ++ ++@@ -92,10 +91,12 @@ static int nf_ip_reroute(struct net *net ++ skb->mark == rt_info->mark && ++ iph->daddr == rt_info->daddr && ++ iph->saddr == rt_info->saddr)) ++- return ip_route_me_harder(net, skb, RTN_UNSPEC); +++ return ip_route_me_harder(entry->state.net, skb, +++ RTN_UNSPEC); ++ } ++ return 0; ++ } +++EXPORT_SYMBOL_GPL(nf_ip_reroute); ++ ++ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol) ++@@ -163,7 +164,6 @@ EXPORT_SYMBOL_GPL(nf_ip_route); ++ ++ static const struct nf_afinfo nf_ip_afinfo = { ++ .family = AF_INET, ++- .reroute = nf_ip_reroute, ++ .route_key_size = sizeof(struct ip_rt_info), ++ }; ++ ++--- a/net/ipv6/netfilter.c +++++ b/net/ipv6/netfilter.c ++@@ -72,7 +72,7 @@ int ip6_route_me_harder(struct net *net, ++ } ++ EXPORT_SYMBOL(ip6_route_me_harder); ++ ++-static int nf_ip6_reroute(struct net *net, struct sk_buff *skb, +++static int nf_ip6_reroute(struct sk_buff *skb, ++ const struct nf_queue_entry *entry) ++ { ++ struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); ++@@ -82,7 +82,7 @@ static int nf_ip6_reroute(struct net *ne ++ if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || ++ !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) || ++ skb->mark != rt_info->mark) ++- return ip6_route_me_harder(net, skb); +++ return ip6_route_me_harder(entry->state.net, skb); ++ } ++ return 0; ++ } ++@@ -175,11 +175,11 @@ static const struct nf_ipv6_ops ipv6ops ++ .checksum = nf_ip6_checksum, ++ .checksum_partial = nf_ip6_checksum_partial, ++ .route = nf_ip6_route, +++ .reroute = nf_ip6_reroute, ++ }; ++ ++ static const struct nf_afinfo nf_ip6_afinfo = { ++ .family = AF_INET6, ++- .reroute = nf_ip6_reroute, ++ .route_key_size = sizeof(struct ip6_rt_info), ++ }; ++ ++--- a/net/netfilter/nf_queue.c +++++ b/net/netfilter/nf_queue.c ++@@ -271,7 +271,6 @@ void nf_reinject(struct nf_queue_entry * ++ const struct nf_hook_entry *hook_entry; ++ const struct nf_hook_entries *hooks; ++ struct sk_buff *skb = entry->skb; ++- const struct nf_afinfo *afinfo; ++ const struct net *net; ++ unsigned int i; ++ int err; ++@@ -298,8 +297,7 @@ void nf_reinject(struct nf_queue_entry * ++ verdict = nf_hook_entry_hookfn(hook_entry, skb, &entry->state); ++ ++ if (verdict == NF_ACCEPT) { ++- afinfo = nf_get_afinfo(entry->state.pf); ++- if (!afinfo || afinfo->reroute(entry->state.net, skb, entry) < 0) +++ if (nf_reroute(skb, entry) < 0) ++ verdict = NF_DROP; ++ } ++ ++--- a/net/netfilter/utils.c +++++ b/net/netfilter/utils.c ++@@ -2,6 +2,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol, ++@@ -69,3 +70,21 @@ int nf_route(struct net *net, struct dst ++ return ret; ++ } ++ EXPORT_SYMBOL_GPL(nf_route); +++ +++int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry) +++{ +++ const struct nf_ipv6_ops *v6ops; +++ int ret = 0; +++ +++ switch (entry->state.pf) { +++ case AF_INET: +++ ret = nf_ip_reroute(skb, entry); +++ break; +++ case AF_INET6: +++ v6ops = rcu_dereference(nf_ipv6_ops); +++ if (v6ops) +++ ret = v6ops->reroute(skb, entry); +++ break; +++ } +++ return ret; +++} +diff --git a/target/linux/generic/backport-4.14/309-v4.16-netfilter-remove-route_key_size-field-in-struct-nf_a.patch b/target/linux/generic/backport-4.14/309-v4.16-netfilter-remove-route_key_size-field-in-struct-nf_a.patch +new file mode 100644 +index 0000000000..20820e40ca +--- /dev/null ++++ b/target/linux/generic/backport-4.14/309-v4.16-netfilter-remove-route_key_size-field-in-struct-nf_a.patch +@@ -0,0 +1,94 @@ ++From: Pablo Neira Ayuso ++Date: Mon, 27 Nov 2017 22:58:37 +0100 ++Subject: [PATCH] netfilter: remove route_key_size field in struct nf_afinfo ++ ++This is only needed by nf_queue, place this code where it belongs. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -311,7 +311,6 @@ struct nf_queue_entry; ++ ++ struct nf_afinfo { ++ unsigned short family; ++- int route_key_size; ++ }; ++ ++ extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO]; ++--- a/net/ipv4/netfilter.c +++++ b/net/ipv4/netfilter.c ++@@ -164,7 +164,6 @@ EXPORT_SYMBOL_GPL(nf_ip_route); ++ ++ static const struct nf_afinfo nf_ip_afinfo = { ++ .family = AF_INET, ++- .route_key_size = sizeof(struct ip_rt_info), ++ }; ++ ++ static int __init ipv4_netfilter_init(void) ++--- a/net/ipv6/netfilter.c +++++ b/net/ipv6/netfilter.c ++@@ -180,7 +180,6 @@ static const struct nf_ipv6_ops ipv6ops ++ ++ static const struct nf_afinfo nf_ip6_afinfo = { ++ .family = AF_INET6, ++- .route_key_size = sizeof(struct ip6_rt_info), ++ }; ++ ++ int __init ipv6_netfilter_init(void) ++--- a/net/netfilter/nf_queue.c +++++ b/net/netfilter/nf_queue.c ++@@ -15,6 +15,8 @@ ++ #include ++ #include ++ #include +++#include +++#include ++ #include ++ #include ++ #include ++@@ -145,9 +147,9 @@ static int __nf_queue(struct sk_buff *sk ++ { ++ int status = -ENOENT; ++ struct nf_queue_entry *entry = NULL; ++- const struct nf_afinfo *afinfo; ++ const struct nf_queue_handler *qh; ++ struct net *net = state->net; +++ unsigned int route_key_size; ++ ++ /* QUEUE == DROP if no one is waiting, to be safe. */ ++ qh = rcu_dereference(net->nf.queue_handler); ++@@ -156,11 +158,19 @@ static int __nf_queue(struct sk_buff *sk ++ goto err; ++ } ++ ++- afinfo = nf_get_afinfo(state->pf); ++- if (!afinfo) ++- goto err; +++ switch (state->pf) { +++ case AF_INET: +++ route_key_size = sizeof(struct ip_rt_info); +++ break; +++ case AF_INET6: +++ route_key_size = sizeof(struct ip6_rt_info); +++ break; +++ default: +++ route_key_size = 0; +++ break; +++ } ++ ++- entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC); +++ entry = kmalloc(sizeof(*entry) + route_key_size, GFP_ATOMIC); ++ if (!entry) { ++ status = -ENOMEM; ++ goto err; ++@@ -175,7 +185,7 @@ static int __nf_queue(struct sk_buff *sk ++ .skb = skb, ++ .state = *state, ++ .hook_index = index, ++- .size = sizeof(*entry) + afinfo->route_key_size, +++ .size = sizeof(*entry) + route_key_size, ++ }; ++ ++ nf_queue_entry_get_refs(entry); +diff --git a/target/linux/generic/backport-4.14/310-v4.16-netfilter-remove-struct-nf_afinfo-and-its-helper-fun.patch b/target/linux/generic/backport-4.14/310-v4.16-netfilter-remove-struct-nf_afinfo-and-its-helper-fun.patch +new file mode 100644 +index 0000000000..be3f7336bd +--- /dev/null ++++ b/target/linux/generic/backport-4.14/310-v4.16-netfilter-remove-struct-nf_afinfo-and-its-helper-fun.patch +@@ -0,0 +1,173 @@ ++From: Pablo Neira Ayuso ++Date: Sat, 9 Dec 2017 17:05:53 +0100 ++Subject: [PATCH] netfilter: remove struct nf_afinfo and its helper functions ++ ++This abstraction has no clients anymore, remove it. ++ ++This is what remains from previous authors, so correct copyright ++statement after recent modifications and code removal. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/linux/netfilter.h +++++ b/include/linux/netfilter.h ++@@ -309,16 +309,6 @@ int skb_make_writable(struct sk_buff *sk ++ struct flowi; ++ struct nf_queue_entry; ++ ++-struct nf_afinfo { ++- unsigned short family; ++-}; ++- ++-extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO]; ++-static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family) ++-{ ++- return rcu_dereference(nf_afinfo[family]); ++-} ++- ++ __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol, ++ unsigned short family); ++@@ -330,9 +320,6 @@ int nf_route(struct net *net, struct dst ++ bool strict, unsigned short family); ++ int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry); ++ ++-int nf_register_afinfo(const struct nf_afinfo *afinfo); ++-void nf_unregister_afinfo(const struct nf_afinfo *afinfo); ++- ++ #include ++ extern void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); ++ ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -95,30 +95,23 @@ static const struct nf_chain_type filter ++ (1 << NF_BR_POST_ROUTING), ++ }; ++ ++-static const struct nf_afinfo nf_br_afinfo = { ++- .family = AF_BRIDGE, ++- .route_key_size = 0, ++-}; ++- ++ static int __init nf_tables_bridge_init(void) ++ { ++ int ret; ++ ++- nf_register_afinfo(&nf_br_afinfo); ++ ret = nft_register_chain_type(&filter_bridge); ++ if (ret < 0) ++- goto err1; +++ return ret; ++ ++ ret = register_pernet_subsys(&nf_tables_bridge_net_ops); ++ if (ret < 0) ++- goto err2; +++ goto err_register_subsys; ++ ++ return ret; ++ ++-err2: +++err_register_subsys: ++ nft_unregister_chain_type(&filter_bridge); ++-err1: ++- nf_unregister_afinfo(&nf_br_afinfo); +++ ++ return ret; ++ } ++ ++@@ -126,7 +119,6 @@ static void __exit nf_tables_bridge_exit ++ { ++ unregister_pernet_subsys(&nf_tables_bridge_net_ops); ++ nft_unregister_chain_type(&filter_bridge); ++- nf_unregister_afinfo(&nf_br_afinfo); ++ } ++ ++ module_init(nf_tables_bridge_init); ++--- a/net/ipv4/netfilter.c +++++ b/net/ipv4/netfilter.c ++@@ -161,13 +161,3 @@ int nf_ip_route(struct net *net, struct ++ return 0; ++ } ++ EXPORT_SYMBOL_GPL(nf_ip_route); ++- ++-static const struct nf_afinfo nf_ip_afinfo = { ++- .family = AF_INET, ++-}; ++- ++-static int __init ipv4_netfilter_init(void) ++-{ ++- return nf_register_afinfo(&nf_ip_afinfo); ++-} ++-subsys_initcall(ipv4_netfilter_init); ++--- a/net/ipv6/netfilter.c +++++ b/net/ipv6/netfilter.c ++@@ -178,14 +178,10 @@ static const struct nf_ipv6_ops ipv6ops ++ .reroute = nf_ip6_reroute, ++ }; ++ ++-static const struct nf_afinfo nf_ip6_afinfo = { ++- .family = AF_INET6, ++-}; ++- ++ int __init ipv6_netfilter_init(void) ++ { ++ RCU_INIT_POINTER(nf_ipv6_ops, &ipv6ops); ++- return nf_register_afinfo(&nf_ip6_afinfo); +++ return 0; ++ } ++ ++ /* This can be called from inet6_init() on errors, so it cannot ++@@ -194,5 +190,4 @@ int __init ipv6_netfilter_init(void) ++ void ipv6_netfilter_fini(void) ++ { ++ RCU_INIT_POINTER(nf_ipv6_ops, NULL); ++- nf_unregister_afinfo(&nf_ip6_afinfo); ++ } ++--- a/net/netfilter/core.c +++++ b/net/netfilter/core.c ++@@ -4,8 +4,7 @@ ++ * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any ++ * way. ++ * ++- * Rusty Russell (C)2000 -- This code is GPL. ++- * Patrick McHardy (c) 2006-2012 +++ * This code is GPL. ++ */ ++ #include ++ #include ++@@ -28,34 +27,12 @@ ++ ++ #include "nf_internals.h" ++ ++-static DEFINE_MUTEX(afinfo_mutex); ++- ++-const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly; ++-EXPORT_SYMBOL(nf_afinfo); ++ const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly; ++ EXPORT_SYMBOL_GPL(nf_ipv6_ops); ++ ++ DEFINE_PER_CPU(bool, nf_skb_duplicated); ++ EXPORT_SYMBOL_GPL(nf_skb_duplicated); ++ ++-int nf_register_afinfo(const struct nf_afinfo *afinfo) ++-{ ++- mutex_lock(&afinfo_mutex); ++- RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo); ++- mutex_unlock(&afinfo_mutex); ++- return 0; ++-} ++-EXPORT_SYMBOL_GPL(nf_register_afinfo); ++- ++-void nf_unregister_afinfo(const struct nf_afinfo *afinfo) ++-{ ++- mutex_lock(&afinfo_mutex); ++- RCU_INIT_POINTER(nf_afinfo[afinfo->family], NULL); ++- mutex_unlock(&afinfo_mutex); ++- synchronize_rcu(); ++-} ++-EXPORT_SYMBOL_GPL(nf_unregister_afinfo); ++- ++ #ifdef HAVE_JUMP_LABEL ++ struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; ++ EXPORT_SYMBOL(nf_hooks_needed); +diff --git a/target/linux/generic/backport-4.14/311-v4.16-netfilter-nf_tables_arp-don-t-set-forward-chain.patch b/target/linux/generic/backport-4.14/311-v4.16-netfilter-nf_tables_arp-don-t-set-forward-chain.patch +new file mode 100644 +index 0000000000..10ce26dc8e +--- /dev/null ++++ b/target/linux/generic/backport-4.14/311-v4.16-netfilter-nf_tables_arp-don-t-set-forward-chain.patch +@@ -0,0 +1,20 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 10 Dec 2017 01:42:58 +0100 ++Subject: [PATCH] netfilter: nf_tables_arp: don't set forward chain ++ ++46928a0b49f3 ("netfilter: nf_tables: remove multihook chains and ++families") already removed this, this is a leftover. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/ipv4/netfilter/nf_tables_arp.c +++++ b/net/ipv4/netfilter/nf_tables_arp.c ++@@ -34,7 +34,6 @@ static struct nft_af_info nft_af_arp __r ++ .hooks = { ++ [NF_ARP_IN] = nft_do_chain_arp, ++ [NF_ARP_OUT] = nft_do_chain_arp, ++- [NF_ARP_FORWARD] = nft_do_chain_arp, ++ }, ++ }; ++ +diff --git a/target/linux/generic/backport-4.14/312-v4.16-netfilter-nf_tables-remove-hooks-from-family-definit.patch b/target/linux/generic/backport-4.14/312-v4.16-netfilter-nf_tables-remove-hooks-from-family-definit.patch +new file mode 100644 +index 0000000000..a12679db43 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/312-v4.16-netfilter-nf_tables-remove-hooks-from-family-definit.patch +@@ -0,0 +1,233 @@ ++From: Pablo Neira Ayuso ++Date: Sat, 9 Dec 2017 15:43:17 +0100 ++Subject: [PATCH] netfilter: nf_tables: remove hooks from family definition ++ ++They don't belong to the family definition, move them to the filter ++chain type definition instead. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -876,7 +876,7 @@ enum nft_chain_type { ++ * @family: address family ++ * @owner: module owner ++ * @hook_mask: mask of valid hooks ++- * @hooks: hookfn overrides +++ * @hooks: array of hook functions ++ */ ++ struct nf_chain_type { ++ const char *name; ++@@ -970,7 +970,6 @@ enum nft_af_flags { ++ * @owner: module owner ++ * @tables: used internally ++ * @flags: family flags ++- * @hooks: hookfn overrides for packet validation ++ */ ++ struct nft_af_info { ++ struct list_head list; ++@@ -979,7 +978,6 @@ struct nft_af_info { ++ struct module *owner; ++ struct list_head tables; ++ u32 flags; ++- nf_hookfn *hooks[NF_MAX_HOOKS]; ++ }; ++ ++ int nft_register_afinfo(struct net *, struct nft_af_info *); ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -46,13 +46,6 @@ static struct nft_af_info nft_af_bridge ++ .family = NFPROTO_BRIDGE, ++ .nhooks = NF_BR_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .hooks = { ++- [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, ++- [NF_BR_LOCAL_IN] = nft_do_chain_bridge, ++- [NF_BR_FORWARD] = nft_do_chain_bridge, ++- [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, ++- [NF_BR_POST_ROUTING] = nft_do_chain_bridge, ++- }, ++ }; ++ ++ static int nf_tables_bridge_init_net(struct net *net) ++@@ -93,6 +86,13 @@ static const struct nf_chain_type filter ++ (1 << NF_BR_FORWARD) | ++ (1 << NF_BR_LOCAL_OUT) | ++ (1 << NF_BR_POST_ROUTING), +++ .hooks = { +++ [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, +++ [NF_BR_LOCAL_IN] = nft_do_chain_bridge, +++ [NF_BR_FORWARD] = nft_do_chain_bridge, +++ [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, +++ [NF_BR_POST_ROUTING] = nft_do_chain_bridge, +++ }, ++ }; ++ ++ static int __init nf_tables_bridge_init(void) ++--- a/net/ipv4/netfilter/nf_tables_arp.c +++++ b/net/ipv4/netfilter/nf_tables_arp.c ++@@ -31,10 +31,6 @@ static struct nft_af_info nft_af_arp __r ++ .family = NFPROTO_ARP, ++ .nhooks = NF_ARP_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .hooks = { ++- [NF_ARP_IN] = nft_do_chain_arp, ++- [NF_ARP_OUT] = nft_do_chain_arp, ++- }, ++ }; ++ ++ static int nf_tables_arp_init_net(struct net *net) ++@@ -72,6 +68,10 @@ static const struct nf_chain_type filter ++ .owner = THIS_MODULE, ++ .hook_mask = (1 << NF_ARP_IN) | ++ (1 << NF_ARP_OUT), +++ .hooks = { +++ [NF_ARP_IN] = nft_do_chain_arp, +++ [NF_ARP_OUT] = nft_do_chain_arp, +++ }, ++ }; ++ ++ static int __init nf_tables_arp_init(void) ++--- a/net/ipv4/netfilter/nf_tables_ipv4.c +++++ b/net/ipv4/netfilter/nf_tables_ipv4.c ++@@ -49,13 +49,6 @@ static struct nft_af_info nft_af_ipv4 __ ++ .family = NFPROTO_IPV4, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .hooks = { ++- [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, ++- [NF_INET_LOCAL_OUT] = nft_ipv4_output, ++- [NF_INET_FORWARD] = nft_do_chain_ipv4, ++- [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, ++- [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, ++- }, ++ }; ++ ++ static int nf_tables_ipv4_init_net(struct net *net) ++@@ -96,6 +89,13 @@ static const struct nf_chain_type filter ++ (1 << NF_INET_FORWARD) | ++ (1 << NF_INET_PRE_ROUTING) | ++ (1 << NF_INET_POST_ROUTING), +++ .hooks = { +++ [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, +++ [NF_INET_LOCAL_OUT] = nft_ipv4_output, +++ [NF_INET_FORWARD] = nft_do_chain_ipv4, +++ [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, +++ [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, +++ }, ++ }; ++ ++ static int __init nf_tables_ipv4_init(void) ++--- a/net/ipv6/netfilter/nf_tables_ipv6.c +++++ b/net/ipv6/netfilter/nf_tables_ipv6.c ++@@ -46,13 +46,6 @@ static struct nft_af_info nft_af_ipv6 __ ++ .family = NFPROTO_IPV6, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .hooks = { ++- [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, ++- [NF_INET_LOCAL_OUT] = nft_ipv6_output, ++- [NF_INET_FORWARD] = nft_do_chain_ipv6, ++- [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, ++- [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, ++- }, ++ }; ++ ++ static int nf_tables_ipv6_init_net(struct net *net) ++@@ -93,6 +86,13 @@ static const struct nf_chain_type filter ++ (1 << NF_INET_FORWARD) | ++ (1 << NF_INET_PRE_ROUTING) | ++ (1 << NF_INET_POST_ROUTING), +++ .hooks = { +++ [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, +++ [NF_INET_LOCAL_OUT] = nft_ipv6_output, +++ [NF_INET_FORWARD] = nft_do_chain_ipv6, +++ [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, +++ [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, +++ }, ++ }; ++ ++ static int __init nf_tables_ipv6_init(void) ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -1398,7 +1398,6 @@ static int nf_tables_addchain(struct nft ++ if (nla[NFTA_CHAIN_HOOK]) { ++ struct nft_chain_hook hook; ++ struct nf_hook_ops *ops; ++- nf_hookfn *hookfn; ++ ++ err = nft_chain_parse_hook(net, nla, afi, &hook, create); ++ if (err < 0) ++@@ -1424,7 +1423,6 @@ static int nf_tables_addchain(struct nft ++ static_branch_inc(&nft_counters_enabled); ++ } ++ ++- hookfn = hook.type->hooks[hook.num]; ++ basechain->type = hook.type; ++ chain = &basechain->chain; ++ ++@@ -1433,10 +1431,8 @@ static int nf_tables_addchain(struct nft ++ ops->hooknum = hook.num; ++ ops->priority = hook.priority; ++ ops->priv = chain; ++- ops->hook = afi->hooks[ops->hooknum]; +++ ops->hook = hook.type->hooks[ops->hooknum]; ++ ops->dev = hook.dev; ++- if (hookfn) ++- ops->hook = hookfn; ++ ++ if (basechain->type->type == NFT_CHAIN_T_NAT) ++ ops->nat_hook = true; ++--- a/net/netfilter/nf_tables_inet.c +++++ b/net/netfilter/nf_tables_inet.c ++@@ -74,13 +74,6 @@ static struct nft_af_info nft_af_inet __ ++ .family = NFPROTO_INET, ++ .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++- .hooks = { ++- [NF_INET_LOCAL_IN] = nft_do_chain_inet, ++- [NF_INET_LOCAL_OUT] = nft_inet_output, ++- [NF_INET_FORWARD] = nft_do_chain_inet, ++- [NF_INET_PRE_ROUTING] = nft_do_chain_inet, ++- [NF_INET_POST_ROUTING] = nft_do_chain_inet, ++- }, ++ }; ++ ++ static int __net_init nf_tables_inet_init_net(struct net *net) ++@@ -121,6 +114,13 @@ static const struct nf_chain_type filter ++ (1 << NF_INET_FORWARD) | ++ (1 << NF_INET_PRE_ROUTING) | ++ (1 << NF_INET_POST_ROUTING), +++ .hooks = { +++ [NF_INET_LOCAL_IN] = nft_do_chain_inet, +++ [NF_INET_LOCAL_OUT] = nft_inet_output, +++ [NF_INET_FORWARD] = nft_do_chain_inet, +++ [NF_INET_PRE_ROUTING] = nft_do_chain_inet, +++ [NF_INET_POST_ROUTING] = nft_do_chain_inet, +++ }, ++ }; ++ ++ static int __init nf_tables_inet_init(void) ++--- a/net/netfilter/nf_tables_netdev.c +++++ b/net/netfilter/nf_tables_netdev.c ++@@ -43,9 +43,6 @@ static struct nft_af_info nft_af_netdev ++ .nhooks = NF_NETDEV_NUMHOOKS, ++ .owner = THIS_MODULE, ++ .flags = NFT_AF_NEEDS_DEV, ++- .hooks = { ++- [NF_NETDEV_INGRESS] = nft_do_chain_netdev, ++- }, ++ }; ++ ++ static int nf_tables_netdev_init_net(struct net *net) ++@@ -82,6 +79,9 @@ static const struct nf_chain_type nft_fi ++ .family = NFPROTO_NETDEV, ++ .owner = THIS_MODULE, ++ .hook_mask = (1 << NF_NETDEV_INGRESS), +++ .hooks = { +++ [NF_NETDEV_INGRESS] = nft_do_chain_netdev, +++ }, ++ }; ++ ++ static void nft_netdev_event(unsigned long event, struct net_device *dev, +diff --git a/target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch b/target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch +new file mode 100644 +index 0000000000..5e56d0dc49 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch +@@ -0,0 +1,302 @@ ++From: Pablo Neira Ayuso ++Date: Sat, 30 Dec 2017 22:41:46 +0100 ++Subject: [PATCH] netfilter: remove defensive check on malformed packets from ++ raw sockets ++ ++Users cannot forge malformed IPv4/IPv6 headers via raw sockets that they ++can inject into the stack. Specifically, not for IPv4 since 55888dfb6ba7 ++("AF_RAW: Augment raw_send_hdrinc to expand skb to fit iphdr->ihl ++(v2)"). IPv6 raw sockets also ensure that packets have a well-formed ++IPv6 header available in the skbuff. ++ ++At quick glance, br_netfilter also validates layer 3 headers and it ++drops malformed both IPv4 and IPv6 packets. ++ ++Therefore, let's remove this defensive check all over the place. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/ipv4/netfilter/iptable_filter.c +++++ b/net/ipv4/netfilter/iptable_filter.c ++@@ -38,12 +38,6 @@ static unsigned int ++ iptable_filter_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++ { ++- if (state->hook == NF_INET_LOCAL_OUT && ++- (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr))) ++- /* root is playing with raw sockets. */ ++- return NF_ACCEPT; ++- ++ return ipt_do_table(skb, state, state->net->ipv4.iptable_filter); ++ } ++ ++--- a/net/ipv4/netfilter/iptable_mangle.c +++++ b/net/ipv4/netfilter/iptable_mangle.c ++@@ -49,11 +49,6 @@ ipt_mangle_out(struct sk_buff *skb, cons ++ u_int32_t mark; ++ int err; ++ ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr)) ++- return NF_ACCEPT; ++- ++ /* Save things which could affect route */ ++ mark = skb->mark; ++ iph = ip_hdr(skb); ++--- a/net/ipv4/netfilter/iptable_raw.c +++++ b/net/ipv4/netfilter/iptable_raw.c ++@@ -26,12 +26,6 @@ static unsigned int ++ iptable_raw_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++ { ++- if (state->hook == NF_INET_LOCAL_OUT && ++- (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr))) ++- /* root is playing with raw sockets. */ ++- return NF_ACCEPT; ++- ++ return ipt_do_table(skb, state, state->net->ipv4.iptable_raw); ++ } ++ ++--- a/net/ipv4/netfilter/iptable_security.c +++++ b/net/ipv4/netfilter/iptable_security.c ++@@ -43,12 +43,6 @@ static unsigned int ++ iptable_security_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++ { ++- if (state->hook == NF_INET_LOCAL_OUT && ++- (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr))) ++- /* Somebody is playing with raw sockets. */ ++- return NF_ACCEPT; ++- ++ return ipt_do_table(skb, state, state->net->ipv4.iptable_security); ++ } ++ ++--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c ++@@ -154,11 +154,6 @@ static unsigned int ipv4_conntrack_local ++ struct sk_buff *skb, ++ const struct nf_hook_state *state) ++ { ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr)) ++- return NF_ACCEPT; ++- ++ if (ip_is_fragment(ip_hdr(skb))) { /* IP_NODEFRAG setsockopt set */ ++ enum ip_conntrack_info ctinfo; ++ struct nf_conn *tmpl; ++--- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c ++@@ -355,11 +355,6 @@ nf_nat_ipv4_out(void *priv, struct sk_bu ++ #endif ++ unsigned int ret; ++ ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr)) ++- return NF_ACCEPT; ++- ++ ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); ++ #ifdef CONFIG_XFRM ++ if (ret != NF_DROP && ret != NF_STOLEN && ++@@ -395,11 +390,6 @@ nf_nat_ipv4_local_fn(void *priv, struct ++ unsigned int ret; ++ int err; ++ ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr)) ++- return NF_ACCEPT; ++- ++ ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); ++ if (ret != NF_DROP && ret != NF_STOLEN && ++ (ct = nf_ct_get(skb, &ctinfo)) != NULL) { ++--- a/net/ipv4/netfilter/nf_tables_ipv4.c +++++ b/net/ipv4/netfilter/nf_tables_ipv4.c ++@@ -30,21 +30,6 @@ static unsigned int nft_do_chain_ipv4(vo ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static unsigned int nft_ipv4_output(void *priv, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) ++-{ ++- if (unlikely(skb->len < sizeof(struct iphdr) || ++- ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { ++- if (net_ratelimit()) ++- pr_info("nf_tables_ipv4: ignoring short SOCK_RAW " ++- "packet\n"); ++- return NF_ACCEPT; ++- } ++- ++- return nft_do_chain_ipv4(priv, skb, state); ++-} ++- ++ static struct nft_af_info nft_af_ipv4 __read_mostly = { ++ .family = NFPROTO_IPV4, ++ .nhooks = NF_INET_NUMHOOKS, ++@@ -91,7 +76,7 @@ static const struct nf_chain_type filter ++ (1 << NF_INET_POST_ROUTING), ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, ++- [NF_INET_LOCAL_OUT] = nft_ipv4_output, +++ [NF_INET_LOCAL_OUT] = nft_do_chain_ipv4, ++ [NF_INET_FORWARD] = nft_do_chain_ipv4, ++ [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, ++ [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, ++--- a/net/ipv4/netfilter/nft_chain_route_ipv4.c +++++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c ++@@ -33,11 +33,6 @@ static unsigned int nf_route_table_hook( ++ const struct iphdr *iph; ++ int err; ++ ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr)) ++- return NF_ACCEPT; ++- ++ nft_set_pktinfo(&pkt, skb, state); ++ nft_set_pktinfo_ipv4(&pkt, skb); ++ ++--- a/net/ipv6/netfilter/ip6table_mangle.c +++++ b/net/ipv6/netfilter/ip6table_mangle.c ++@@ -42,14 +42,6 @@ ip6t_mangle_out(struct sk_buff *skb, con ++ u_int8_t hop_limit; ++ u_int32_t flowlabel, mark; ++ int err; ++-#if 0 ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct iphdr) || ++- ip_hdrlen(skb) < sizeof(struct iphdr)) { ++- net_warn_ratelimited("ip6t_hook: happy cracking\n"); ++- return NF_ACCEPT; ++- } ++-#endif ++ ++ /* save source/dest address, mark, hoplimit, flowlabel, priority, */ ++ memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); ++--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c ++@@ -176,11 +176,6 @@ static unsigned int ipv6_conntrack_local ++ struct sk_buff *skb, ++ const struct nf_hook_state *state) ++ { ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct ipv6hdr)) { ++- net_notice_ratelimited("ipv6_conntrack_local: packet too short\n"); ++- return NF_ACCEPT; ++- } ++ return nf_conntrack_in(state->net, PF_INET6, state->hook, skb); ++ } ++ ++--- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c ++@@ -372,10 +372,6 @@ nf_nat_ipv6_out(void *priv, struct sk_bu ++ #endif ++ unsigned int ret; ++ ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct ipv6hdr)) ++- return NF_ACCEPT; ++- ++ ret = nf_nat_ipv6_fn(priv, skb, state, do_chain); ++ #ifdef CONFIG_XFRM ++ if (ret != NF_DROP && ret != NF_STOLEN && ++@@ -411,10 +407,6 @@ nf_nat_ipv6_local_fn(void *priv, struct ++ unsigned int ret; ++ int err; ++ ++- /* root is playing with raw sockets. */ ++- if (skb->len < sizeof(struct ipv6hdr)) ++- return NF_ACCEPT; ++- ++ ret = nf_nat_ipv6_fn(priv, skb, state, do_chain); ++ if (ret != NF_DROP && ret != NF_STOLEN && ++ (ct = nf_ct_get(skb, &ctinfo)) != NULL) { ++--- a/net/ipv6/netfilter/nf_tables_ipv6.c +++++ b/net/ipv6/netfilter/nf_tables_ipv6.c ++@@ -28,20 +28,6 @@ static unsigned int nft_do_chain_ipv6(vo ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static unsigned int nft_ipv6_output(void *priv, ++- struct sk_buff *skb, ++- const struct nf_hook_state *state) ++-{ ++- if (unlikely(skb->len < sizeof(struct ipv6hdr))) { ++- if (net_ratelimit()) ++- pr_info("nf_tables_ipv6: ignoring short SOCK_RAW " ++- "packet\n"); ++- return NF_ACCEPT; ++- } ++- ++- return nft_do_chain_ipv6(priv, skb, state); ++-} ++- ++ static struct nft_af_info nft_af_ipv6 __read_mostly = { ++ .family = NFPROTO_IPV6, ++ .nhooks = NF_INET_NUMHOOKS, ++@@ -88,7 +74,7 @@ static const struct nf_chain_type filter ++ (1 << NF_INET_POST_ROUTING), ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, ++- [NF_INET_LOCAL_OUT] = nft_ipv6_output, +++ [NF_INET_LOCAL_OUT] = nft_do_chain_ipv6, ++ [NF_INET_FORWARD] = nft_do_chain_ipv6, ++ [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, ++ [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, ++--- a/net/netfilter/nf_tables_inet.c +++++ b/net/netfilter/nf_tables_inet.c ++@@ -38,38 +38,6 @@ static unsigned int nft_do_chain_inet(vo ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static unsigned int nft_inet_output(void *priv, struct sk_buff *skb, ++- const struct nf_hook_state *state) ++-{ ++- struct nft_pktinfo pkt; ++- ++- nft_set_pktinfo(&pkt, skb, state); ++- ++- switch (state->pf) { ++- case NFPROTO_IPV4: ++- if (unlikely(skb->len < sizeof(struct iphdr) || ++- ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { ++- if (net_ratelimit()) ++- pr_info("ignoring short SOCK_RAW packet\n"); ++- return NF_ACCEPT; ++- } ++- nft_set_pktinfo_ipv4(&pkt, skb); ++- break; ++- case NFPROTO_IPV6: ++- if (unlikely(skb->len < sizeof(struct ipv6hdr))) { ++- if (net_ratelimit()) ++- pr_info("ignoring short SOCK_RAW packet\n"); ++- return NF_ACCEPT; ++- } ++- nft_set_pktinfo_ipv6(&pkt, skb); ++- break; ++- default: ++- break; ++- } ++- ++- return nft_do_chain(&pkt, priv); ++-} ++- ++ static struct nft_af_info nft_af_inet __read_mostly = { ++ .family = NFPROTO_INET, ++ .nhooks = NF_INET_NUMHOOKS, ++@@ -116,7 +84,7 @@ static const struct nf_chain_type filter ++ (1 << NF_INET_POST_ROUTING), ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_inet, ++- [NF_INET_LOCAL_OUT] = nft_inet_output, +++ [NF_INET_LOCAL_OUT] = nft_do_chain_inet, ++ [NF_INET_FORWARD] = nft_do_chain_inet, ++ [NF_INET_PRE_ROUTING] = nft_do_chain_inet, ++ [NF_INET_POST_ROUTING] = nft_do_chain_inet, +diff --git a/target/linux/generic/backport-4.14/314-v4.16-netfilter-meta-secpath-support.patch b/target/linux/generic/backport-4.14/314-v4.16-netfilter-meta-secpath-support.patch +new file mode 100644 +index 0000000000..7aab67fc2c +--- /dev/null ++++ b/target/linux/generic/backport-4.14/314-v4.16-netfilter-meta-secpath-support.patch +@@ -0,0 +1,101 @@ ++From: Florian Westphal ++Date: Wed, 6 Dec 2017 16:18:16 +0100 ++Subject: [PATCH] netfilter: meta: secpath support ++ ++replacement for iptables "-m policy --dir in --policy {ipsec,none}". ++ ++Signed-off-by: Florian Westphal ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/uapi/linux/netfilter/nf_tables.h +++++ b/include/uapi/linux/netfilter/nf_tables.h ++@@ -777,6 +777,7 @@ enum nft_exthdr_attributes { ++ * @NFT_META_OIFGROUP: packet output interface group ++ * @NFT_META_CGROUP: socket control group (skb->sk->sk_classid) ++ * @NFT_META_PRANDOM: a 32bit pseudo-random number +++ * @NFT_META_SECPATH: boolean, secpath_exists (!!skb->sp) ++ */ ++ enum nft_meta_keys { ++ NFT_META_LEN, ++@@ -804,6 +805,7 @@ enum nft_meta_keys { ++ NFT_META_OIFGROUP, ++ NFT_META_CGROUP, ++ NFT_META_PRANDOM, +++ NFT_META_SECPATH, ++ }; ++ ++ /** ++--- a/net/netfilter/nft_meta.c +++++ b/net/netfilter/nft_meta.c ++@@ -210,6 +210,11 @@ void nft_meta_get_eval(const struct nft_ ++ *dest = prandom_u32_state(state); ++ break; ++ } +++#ifdef CONFIG_XFRM +++ case NFT_META_SECPATH: +++ nft_reg_store8(dest, !!skb->sp); +++ break; +++#endif ++ default: ++ WARN_ON(1); ++ goto err; ++@@ -310,6 +315,11 @@ int nft_meta_get_init(const struct nft_c ++ prandom_init_once(&nft_prandom_state); ++ len = sizeof(u32); ++ break; +++#ifdef CONFIG_XFRM +++ case NFT_META_SECPATH: +++ len = sizeof(u8); +++ break; +++#endif ++ default: ++ return -EOPNOTSUPP; ++ } ++@@ -320,6 +330,38 @@ int nft_meta_get_init(const struct nft_c ++ } ++ EXPORT_SYMBOL_GPL(nft_meta_get_init); ++ +++static int nft_meta_get_validate(const struct nft_ctx *ctx, +++ const struct nft_expr *expr, +++ const struct nft_data **data) +++{ +++#ifdef CONFIG_XFRM +++ const struct nft_meta *priv = nft_expr_priv(expr); +++ unsigned int hooks; +++ +++ if (priv->key != NFT_META_SECPATH) +++ return 0; +++ +++ switch (ctx->afi->family) { +++ case NFPROTO_NETDEV: +++ hooks = 1 << NF_NETDEV_INGRESS; +++ break; +++ case NFPROTO_IPV4: +++ case NFPROTO_IPV6: +++ case NFPROTO_INET: +++ hooks = (1 << NF_INET_PRE_ROUTING) | +++ (1 << NF_INET_LOCAL_IN) | +++ (1 << NF_INET_FORWARD); +++ break; +++ default: +++ return -EOPNOTSUPP; +++ } +++ +++ return nft_chain_validate_hooks(ctx->chain, hooks); +++#else +++ return 0; +++#endif +++} +++ ++ int nft_meta_set_validate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr, ++ const struct nft_data **data) ++@@ -436,6 +478,7 @@ static const struct nft_expr_ops nft_met ++ .eval = nft_meta_get_eval, ++ .init = nft_meta_get_init, ++ .dump = nft_meta_get_dump, +++ .validate = nft_meta_get_validate, ++ }; ++ ++ static const struct nft_expr_ops nft_meta_set_ops = { +diff --git a/target/linux/generic/backport-4.14/315-v4.15-netfilter-conntrack-move-nf_ct_netns_-get-put-to-cor.patch b/target/linux/generic/backport-4.14/315-v4.15-netfilter-conntrack-move-nf_ct_netns_-get-put-to-cor.patch +new file mode 100644 +index 0000000000..7f6e90470a +--- /dev/null ++++ b/target/linux/generic/backport-4.14/315-v4.15-netfilter-conntrack-move-nf_ct_netns_-get-put-to-cor.patch +@@ -0,0 +1,142 @@ ++From: Pablo Neira Ayuso ++Date: Fri, 3 Nov 2017 16:26:32 +0100 ++Subject: [PATCH] netfilter: conntrack: move nf_ct_netns_{get,put}() to core ++ ++So we can call this from other expression that need conntrack in place ++to work. ++ ++Signed-off-by: Pablo Neira Ayuso ++Acked-by: Florian Westphal ++--- ++ ++--- a/net/netfilter/nf_conntrack_proto.c +++++ b/net/netfilter/nf_conntrack_proto.c ++@@ -125,7 +125,7 @@ void nf_ct_l3proto_module_put(unsigned s ++ } ++ EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); ++ ++-int nf_ct_netns_get(struct net *net, u8 nfproto) +++static int nf_ct_netns_do_get(struct net *net, u8 nfproto) ++ { ++ const struct nf_conntrack_l3proto *l3proto; ++ int ret; ++@@ -150,9 +150,33 @@ int nf_ct_netns_get(struct net *net, u8 ++ ++ return ret; ++ } +++ +++int nf_ct_netns_get(struct net *net, u8 nfproto) +++{ +++ int err; +++ +++ if (nfproto == NFPROTO_INET) { +++ err = nf_ct_netns_do_get(net, NFPROTO_IPV4); +++ if (err < 0) +++ goto err1; +++ err = nf_ct_netns_do_get(net, NFPROTO_IPV6); +++ if (err < 0) +++ goto err2; +++ } else { +++ err = nf_ct_netns_do_get(net, nfproto); +++ if (err < 0) +++ goto err1; +++ } +++ return 0; +++ +++err2: +++ nf_ct_netns_put(net, NFPROTO_IPV4); +++err1: +++ return err; +++} ++ EXPORT_SYMBOL_GPL(nf_ct_netns_get); ++ ++-void nf_ct_netns_put(struct net *net, u8 nfproto) +++static void nf_ct_netns_do_put(struct net *net, u8 nfproto) ++ { ++ const struct nf_conntrack_l3proto *l3proto; ++ ++@@ -171,6 +195,15 @@ void nf_ct_netns_put(struct net *net, u8 ++ ++ nf_ct_l3proto_module_put(nfproto); ++ } +++ +++void nf_ct_netns_put(struct net *net, uint8_t nfproto) +++{ +++ if (nfproto == NFPROTO_INET) { +++ nf_ct_netns_do_put(net, NFPROTO_IPV4); +++ nf_ct_netns_do_put(net, NFPROTO_IPV6); +++ } else +++ nf_ct_netns_do_put(net, nfproto); +++} ++ EXPORT_SYMBOL_GPL(nf_ct_netns_put); ++ ++ const struct nf_conntrack_l4proto * ++--- a/net/netfilter/nft_ct.c +++++ b/net/netfilter/nft_ct.c ++@@ -312,39 +312,6 @@ static const struct nla_policy nft_ct_po ++ [NFTA_CT_SREG] = { .type = NLA_U32 }, ++ }; ++ ++-static int nft_ct_netns_get(struct net *net, uint8_t family) ++-{ ++- int err; ++- ++- if (family == NFPROTO_INET) { ++- err = nf_ct_netns_get(net, NFPROTO_IPV4); ++- if (err < 0) ++- goto err1; ++- err = nf_ct_netns_get(net, NFPROTO_IPV6); ++- if (err < 0) ++- goto err2; ++- } else { ++- err = nf_ct_netns_get(net, family); ++- if (err < 0) ++- goto err1; ++- } ++- return 0; ++- ++-err2: ++- nf_ct_netns_put(net, NFPROTO_IPV4); ++-err1: ++- return err; ++-} ++- ++-static void nft_ct_netns_put(struct net *net, uint8_t family) ++-{ ++- if (family == NFPROTO_INET) { ++- nf_ct_netns_put(net, NFPROTO_IPV4); ++- nf_ct_netns_put(net, NFPROTO_IPV6); ++- } else ++- nf_ct_netns_put(net, family); ++-} ++- ++ #ifdef CONFIG_NF_CONNTRACK_ZONES ++ static void nft_ct_tmpl_put_pcpu(void) ++ { ++@@ -489,7 +456,7 @@ static int nft_ct_get_init(const struct ++ if (err < 0) ++ return err; ++ ++- err = nft_ct_netns_get(ctx->net, ctx->afi->family); +++ err = nf_ct_netns_get(ctx->net, ctx->afi->family); ++ if (err < 0) ++ return err; ++ ++@@ -583,7 +550,7 @@ static int nft_ct_set_init(const struct ++ if (err < 0) ++ goto err1; ++ ++- err = nft_ct_netns_get(ctx->net, ctx->afi->family); +++ err = nf_ct_netns_get(ctx->net, ctx->afi->family); ++ if (err < 0) ++ goto err1; ++ ++@@ -606,7 +573,7 @@ static void nft_ct_set_destroy(const str ++ struct nft_ct *priv = nft_expr_priv(expr); ++ ++ __nft_ct_set_destroy(ctx, priv); ++- nft_ct_netns_put(ctx->net, ctx->afi->family); +++ nf_ct_netns_put(ctx->net, ctx->afi->family); ++ } ++ ++ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) +diff --git a/target/linux/generic/backport-4.14/320-v4.16-netfilter-nf_conntrack-add-IPS_OFFLOAD-status-bit.patch b/target/linux/generic/backport-4.14/320-v4.16-netfilter-nf_conntrack-add-IPS_OFFLOAD-status-bit.patch +new file mode 100644 +index 0000000000..885d632d22 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/320-v4.16-netfilter-nf_conntrack-add-IPS_OFFLOAD-status-bit.patch +@@ -0,0 +1,169 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 7 Jan 2018 01:03:56 +0100 ++Subject: [PATCH] netfilter: nf_conntrack: add IPS_OFFLOAD status bit ++ ++This new bit tells us that the conntrack entry is owned by the flow ++table offload infrastructure. ++ ++ # cat /proc/net/nf_conntrack ++ ipv4 2 tcp 6 src=10.141.10.2 dst=147.75.205.195 sport=36392 dport=443 src=147.75.205.195 dst=192.168.2.195 sport=443 dport=36392 [OFFLOAD] mark=0 zone=0 use=2 ++ ++Note the [OFFLOAD] tag in the listing. ++ ++The timer of such conntrack entries look like stopped from userspace. ++In practise, to make sure the conntrack entry does not go away, the ++conntrack timer is periodically set to an arbitrary large value that ++gets refreshed on every iteration from the garbage collector, so it ++never expires- and they display no internal state in the case of TCP ++flows. This allows us to save a bitcheck from the packet path via ++nf_ct_is_expired(). ++ ++Conntrack entries that have been offloaded to the flow table ++infrastructure cannot be deleted/flushed via ctnetlink. The flow table ++infrastructure is also responsible for releasing this conntrack entry. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/uapi/linux/netfilter/nf_conntrack_common.h +++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h ++@@ -101,12 +101,16 @@ enum ip_conntrack_status { ++ IPS_HELPER_BIT = 13, ++ IPS_HELPER = (1 << IPS_HELPER_BIT), ++ +++ /* Conntrack has been offloaded to flow table. */ +++ IPS_OFFLOAD_BIT = 14, +++ IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT), +++ ++ /* Be careful here, modifying these bits can make things messy, ++ * so don't let users modify them directly. ++ */ ++ IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK | ++ IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | ++- IPS_SEQ_ADJUST | IPS_TEMPLATE), +++ IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD), ++ ++ __IPS_MAX_BIT = 14, ++ }; ++--- a/net/netfilter/nf_conntrack_core.c +++++ b/net/netfilter/nf_conntrack_core.c ++@@ -974,6 +974,9 @@ static unsigned int early_drop_list(stru ++ hlist_nulls_for_each_entry_rcu(h, n, head, hnnode) { ++ tmp = nf_ct_tuplehash_to_ctrack(h); ++ +++ if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) +++ continue; +++ ++ if (nf_ct_is_expired(tmp)) { ++ nf_ct_gc_expired(tmp); ++ continue; ++@@ -1051,6 +1054,18 @@ static bool gc_worker_can_early_drop(con ++ return false; ++ } ++ +++#define DAY (86400 * HZ) +++ +++/* Set an arbitrary timeout large enough not to ever expire, this save +++ * us a check for the IPS_OFFLOAD_BIT from the packet path via +++ * nf_ct_is_expired(). +++ */ +++static void nf_ct_offload_timeout(struct nf_conn *ct) +++{ +++ if (nf_ct_expires(ct) < DAY / 2) +++ ct->timeout = nfct_time_stamp + DAY; +++} +++ ++ static void gc_worker(struct work_struct *work) ++ { ++ unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u); ++@@ -1087,6 +1102,11 @@ static void gc_worker(struct work_struct ++ tmp = nf_ct_tuplehash_to_ctrack(h); ++ ++ scanned++; +++ if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) { +++ nf_ct_offload_timeout(tmp); +++ continue; +++ } +++ ++ if (nf_ct_is_expired(tmp)) { ++ nf_ct_gc_expired(tmp); ++ expired_count++; ++--- a/net/netfilter/nf_conntrack_netlink.c +++++ b/net/netfilter/nf_conntrack_netlink.c ++@@ -1123,6 +1123,14 @@ static const struct nla_policy ct_nla_po ++ .len = NF_CT_LABELS_MAX_SIZE }, ++ }; ++ +++static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data) +++{ +++ if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) +++ return 0; +++ +++ return ctnetlink_filter_match(ct, data); +++} +++ ++ static int ctnetlink_flush_conntrack(struct net *net, ++ const struct nlattr * const cda[], ++ u32 portid, int report) ++@@ -1135,7 +1143,7 @@ static int ctnetlink_flush_conntrack(str ++ return PTR_ERR(filter); ++ } ++ ++- nf_ct_iterate_cleanup_net(net, ctnetlink_filter_match, filter, +++ nf_ct_iterate_cleanup_net(net, ctnetlink_flush_iterate, filter, ++ portid, report); ++ kfree(filter); ++ ++@@ -1181,6 +1189,11 @@ static int ctnetlink_del_conntrack(struc ++ ++ ct = nf_ct_tuplehash_to_ctrack(h); ++ +++ if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) { +++ nf_ct_put(ct); +++ return -EBUSY; +++ } +++ ++ if (cda[CTA_ID]) { ++ __be32 id = nla_get_be32(cda[CTA_ID]); ++ ++--- a/net/netfilter/nf_conntrack_proto_tcp.c +++++ b/net/netfilter/nf_conntrack_proto_tcp.c ++@@ -305,6 +305,9 @@ static bool tcp_invert_tuple(struct nf_c ++ /* Print out the private part of the conntrack. */ ++ static void tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct) ++ { +++ if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) +++ return; +++ ++ seq_printf(s, "%s ", tcp_conntrack_names[ct->proto.tcp.state]); ++ } ++ #endif ++--- a/net/netfilter/nf_conntrack_standalone.c +++++ b/net/netfilter/nf_conntrack_standalone.c ++@@ -309,10 +309,12 @@ static int ct_seq_show(struct seq_file * ++ WARN_ON(!l4proto); ++ ++ ret = -ENOSPC; ++- seq_printf(s, "%-8s %u %-8s %u %ld ", +++ seq_printf(s, "%-8s %u %-8s %u ", ++ l3proto_name(l3proto->l3proto), nf_ct_l3num(ct), ++- l4proto_name(l4proto->l4proto), nf_ct_protonum(ct), ++- nf_ct_expires(ct) / HZ); +++ l4proto_name(l4proto->l4proto), nf_ct_protonum(ct)); +++ +++ if (!test_bit(IPS_OFFLOAD_BIT, &ct->status)) +++ seq_printf(s, "%ld ", nf_ct_expires(ct) / HZ); ++ ++ if (l4proto->print_conntrack) ++ l4proto->print_conntrack(s, ct); ++@@ -339,7 +341,9 @@ static int ct_seq_show(struct seq_file * ++ if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) ++ goto release; ++ ++- if (test_bit(IPS_ASSURED_BIT, &ct->status)) +++ if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) +++ seq_puts(s, "[OFFLOAD] "); +++ else if (test_bit(IPS_ASSURED_BIT, &ct->status)) ++ seq_puts(s, "[ASSURED] "); ++ ++ if (seq_has_overflowed(s)) +diff --git a/target/linux/generic/backport-4.14/321-v4.16-netfilter-nf_tables-add-flow-table-netlink-frontend.patch b/target/linux/generic/backport-4.14/321-v4.16-netfilter-nf_tables-add-flow-table-netlink-frontend.patch +new file mode 100644 +index 0000000000..f0109e4823 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/321-v4.16-netfilter-nf_tables-add-flow-table-netlink-frontend.patch +@@ -0,0 +1,1079 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 7 Jan 2018 01:04:07 +0100 ++Subject: [PATCH] netfilter: nf_tables: add flow table netlink frontend ++ ++This patch introduces a netlink control plane to create, delete and dump ++flow tables. Flow tables are identified by name, this name is used from ++rules to refer to an specific flow table. Flow tables use the rhashtable ++class and a generic garbage collector to remove expired entries. ++ ++This also adds the infrastructure to add different flow table types, so ++we can add one for each layer 3 protocol family. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ create mode 100644 include/net/netfilter/nf_flow_table.h ++ ++--- /dev/null +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -0,0 +1,23 @@ +++#ifndef _NF_FLOW_TABLE_H +++#define _NF_FLOW_TABLE_H +++ +++#include +++ +++struct nf_flowtable; +++ +++struct nf_flowtable_type { +++ struct list_head list; +++ int family; +++ void (*gc)(struct work_struct *work); +++ const struct rhashtable_params *params; +++ nf_hookfn *hook; +++ struct module *owner; +++}; +++ +++struct nf_flowtable { +++ struct rhashtable rhashtable; +++ const struct nf_flowtable_type *type; +++ struct delayed_work gc_work; +++}; +++ +++#endif /* _FLOW_OFFLOAD_H */ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -9,6 +9,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #define NFT_JUMP_STACK_SIZE 16 ++@@ -939,6 +940,7 @@ unsigned int nft_do_chain(struct nft_pkt ++ * @chains: chains in the table ++ * @sets: sets in the table ++ * @objects: stateful objects in the table +++ * @flowtables: flow tables in the table ++ * @hgenerator: handle generator state ++ * @use: number of chain references to this table ++ * @flags: table flag (see enum nft_table_flags) ++@@ -950,6 +952,7 @@ struct nft_table { ++ struct list_head chains; ++ struct list_head sets; ++ struct list_head objects; +++ struct list_head flowtables; ++ u64 hgenerator; ++ u32 use; ++ u16 flags:14, ++@@ -1081,6 +1084,44 @@ int nft_register_obj(struct nft_object_t ++ void nft_unregister_obj(struct nft_object_type *obj_type); ++ ++ /** +++ * struct nft_flowtable - nf_tables flow table +++ * +++ * @list: flow table list node in table list +++ * @table: the table the flow table is contained in +++ * @name: name of this flow table +++ * @hooknum: hook number +++ * @priority: hook priority +++ * @ops_len: number of hooks in array +++ * @genmask: generation mask +++ * @use: number of references to this flow table +++ * @data: rhashtable and garbage collector +++ * @ops: array of hooks +++ */ +++struct nft_flowtable { +++ struct list_head list; +++ struct nft_table *table; +++ char *name; +++ int hooknum; +++ int priority; +++ int ops_len; +++ u32 genmask:2, +++ use:30; +++ /* runtime data below here */ +++ struct nf_hook_ops *ops ____cacheline_aligned; +++ struct nf_flowtable data; +++}; +++ +++struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, +++ const struct nlattr *nla, +++ u8 genmask); +++void nft_flow_table_iterate(struct net *net, +++ void (*iter)(struct nf_flowtable *flowtable, void *data), +++ void *data); +++ +++void nft_register_flowtable_type(struct nf_flowtable_type *type); +++void nft_unregister_flowtable_type(struct nf_flowtable_type *type); +++ +++/** ++ * struct nft_traceinfo - nft tracing information and state ++ * ++ * @pkt: pktinfo currently processed ++@@ -1316,4 +1357,11 @@ struct nft_trans_obj { ++ #define nft_trans_obj(trans) \ ++ (((struct nft_trans_obj *)trans->data)->obj) ++ +++struct nft_trans_flowtable { +++ struct nft_flowtable *flowtable; +++}; +++ +++#define nft_trans_flowtable(trans) \ +++ (((struct nft_trans_flowtable *)trans->data)->flowtable) +++ ++ #endif /* _NET_NF_TABLES_H */ ++--- a/include/uapi/linux/netfilter/nf_tables.h +++++ b/include/uapi/linux/netfilter/nf_tables.h ++@@ -92,6 +92,9 @@ enum nft_verdicts { ++ * @NFT_MSG_GETOBJ: get a stateful object (enum nft_obj_attributes) ++ * @NFT_MSG_DELOBJ: delete a stateful object (enum nft_obj_attributes) ++ * @NFT_MSG_GETOBJ_RESET: get and reset a stateful object (enum nft_obj_attributes) +++ * @NFT_MSG_NEWFLOWTABLE: add new flow table (enum nft_flowtable_attributes) +++ * @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes) +++ * @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes) ++ */ ++ enum nf_tables_msg_types { ++ NFT_MSG_NEWTABLE, ++@@ -116,6 +119,9 @@ enum nf_tables_msg_types { ++ NFT_MSG_GETOBJ, ++ NFT_MSG_DELOBJ, ++ NFT_MSG_GETOBJ_RESET, +++ NFT_MSG_NEWFLOWTABLE, +++ NFT_MSG_GETFLOWTABLE, +++ NFT_MSG_DELFLOWTABLE, ++ NFT_MSG_MAX, ++ }; ++ ++@@ -1310,6 +1316,53 @@ enum nft_object_attributes { ++ #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) ++ ++ /** +++ * enum nft_flowtable_attributes - nf_tables flow table netlink attributes +++ * +++ * @NFTA_FLOWTABLE_TABLE: name of the table containing the expression (NLA_STRING) +++ * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) +++ * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) +++ * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) +++ */ +++enum nft_flowtable_attributes { +++ NFTA_FLOWTABLE_UNSPEC, +++ NFTA_FLOWTABLE_TABLE, +++ NFTA_FLOWTABLE_NAME, +++ NFTA_FLOWTABLE_HOOK, +++ NFTA_FLOWTABLE_USE, +++ __NFTA_FLOWTABLE_MAX +++}; +++#define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) +++ +++/** +++ * enum nft_flowtable_hook_attributes - nf_tables flow table hook netlink attributes +++ * +++ * @NFTA_FLOWTABLE_HOOK_NUM: netfilter hook number (NLA_U32) +++ * @NFTA_FLOWTABLE_HOOK_PRIORITY: netfilter hook priority (NLA_U32) +++ * @NFTA_FLOWTABLE_HOOK_DEVS: input devices this flow table is bound to (NLA_NESTED) +++ */ +++enum nft_flowtable_hook_attributes { +++ NFTA_FLOWTABLE_HOOK_UNSPEC, +++ NFTA_FLOWTABLE_HOOK_NUM, +++ NFTA_FLOWTABLE_HOOK_PRIORITY, +++ NFTA_FLOWTABLE_HOOK_DEVS, +++ __NFTA_FLOWTABLE_HOOK_MAX +++}; +++#define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1) +++ +++/** +++ * enum nft_device_attributes - nf_tables device netlink attributes +++ * +++ * @NFTA_DEVICE_NAME: name of this device (NLA_STRING) +++ */ +++enum nft_devices_attributes { +++ NFTA_DEVICE_UNSPEC, +++ NFTA_DEVICE_NAME, +++ __NFTA_DEVICE_MAX +++}; +++#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1) +++ +++ +++/** ++ * enum nft_trace_attributes - nf_tables trace netlink attributes ++ * ++ * @NFTA_TRACE_TABLE: name of the table (NLA_STRING) ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -17,6 +17,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -24,6 +25,7 @@ ++ ++ static LIST_HEAD(nf_tables_expressions); ++ static LIST_HEAD(nf_tables_objects); +++static LIST_HEAD(nf_tables_flowtables); ++ ++ /** ++ * nft_register_afinfo - register nf_tables address family info ++@@ -389,6 +391,40 @@ static int nft_delobj(struct nft_ctx *ct ++ return err; ++ } ++ +++static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type, +++ struct nft_flowtable *flowtable) +++{ +++ struct nft_trans *trans; +++ +++ trans = nft_trans_alloc(ctx, msg_type, +++ sizeof(struct nft_trans_flowtable)); +++ if (trans == NULL) +++ return -ENOMEM; +++ +++ if (msg_type == NFT_MSG_NEWFLOWTABLE) +++ nft_activate_next(ctx->net, flowtable); +++ +++ nft_trans_flowtable(trans) = flowtable; +++ list_add_tail(&trans->list, &ctx->net->nft.commit_list); +++ +++ return 0; +++} +++ +++static int nft_delflowtable(struct nft_ctx *ctx, +++ struct nft_flowtable *flowtable) +++{ +++ int err; +++ +++ err = nft_trans_flowtable_add(ctx, NFT_MSG_DELFLOWTABLE, flowtable); +++ if (err < 0) +++ return err; +++ +++ nft_deactivate_next(ctx->net, flowtable); +++ ctx->table->use--; +++ +++ return err; +++} +++ ++ /* ++ * Tables ++ */ ++@@ -772,6 +808,7 @@ static int nf_tables_newtable(struct net ++ INIT_LIST_HEAD(&table->chains); ++ INIT_LIST_HEAD(&table->sets); ++ INIT_LIST_HEAD(&table->objects); +++ INIT_LIST_HEAD(&table->flowtables); ++ table->flags = flags; ++ ++ nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++@@ -793,10 +830,11 @@ err1: ++ ++ static int nft_flush_table(struct nft_ctx *ctx) ++ { ++- int err; +++ struct nft_flowtable *flowtable, *nft; ++ struct nft_chain *chain, *nc; ++ struct nft_object *obj, *ne; ++ struct nft_set *set, *ns; +++ int err; ++ ++ list_for_each_entry(chain, &ctx->table->chains, list) { ++ if (!nft_is_active_next(ctx->net, chain)) ++@@ -822,6 +860,12 @@ static int nft_flush_table(struct nft_ct ++ goto out; ++ } ++ +++ list_for_each_entry_safe(flowtable, nft, &ctx->table->flowtables, list) { +++ err = nft_delflowtable(ctx, flowtable); +++ if (err < 0) +++ goto out; +++ } +++ ++ list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) { ++ err = nft_delobj(ctx, obj); ++ if (err < 0) ++@@ -4862,6 +4906,605 @@ static void nf_tables_obj_notify(const s ++ ctx->afi->family, ctx->report, GFP_KERNEL); ++ } ++ +++/* +++ * Flow tables +++ */ +++void nft_register_flowtable_type(struct nf_flowtable_type *type) +++{ +++ nfnl_lock(NFNL_SUBSYS_NFTABLES); +++ list_add_tail_rcu(&type->list, &nf_tables_flowtables); +++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); +++} +++EXPORT_SYMBOL_GPL(nft_register_flowtable_type); +++ +++void nft_unregister_flowtable_type(struct nf_flowtable_type *type) +++{ +++ nfnl_lock(NFNL_SUBSYS_NFTABLES); +++ list_del_rcu(&type->list); +++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); +++} +++EXPORT_SYMBOL_GPL(nft_unregister_flowtable_type); +++ +++static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = { +++ [NFTA_FLOWTABLE_TABLE] = { .type = NLA_STRING, +++ .len = NFT_NAME_MAXLEN - 1 }, +++ [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, +++ .len = NFT_NAME_MAXLEN - 1 }, +++ [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, +++}; +++ +++struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, +++ const struct nlattr *nla, +++ u8 genmask) +++{ +++ struct nft_flowtable *flowtable; +++ +++ list_for_each_entry(flowtable, &table->flowtables, list) { +++ if (!nla_strcmp(nla, flowtable->name) && +++ nft_active_genmask(flowtable, genmask)) +++ return flowtable; +++ } +++ return ERR_PTR(-ENOENT); +++} +++EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); +++ +++#define NFT_FLOWTABLE_DEVICE_MAX 8 +++ +++static int nf_tables_parse_devices(const struct nft_ctx *ctx, +++ const struct nlattr *attr, +++ struct net_device *dev_array[], int *len) +++{ +++ const struct nlattr *tmp; +++ struct net_device *dev; +++ char ifname[IFNAMSIZ]; +++ int rem, n = 0, err; +++ +++ nla_for_each_nested(tmp, attr, rem) { +++ if (nla_type(tmp) != NFTA_DEVICE_NAME) { +++ err = -EINVAL; +++ goto err1; +++ } +++ +++ nla_strlcpy(ifname, tmp, IFNAMSIZ); +++ dev = dev_get_by_name(ctx->net, ifname); +++ if (!dev) { +++ err = -ENOENT; +++ goto err1; +++ } +++ +++ dev_array[n++] = dev; +++ if (n == NFT_FLOWTABLE_DEVICE_MAX) { +++ err = -EFBIG; +++ goto err1; +++ } +++ } +++ if (!len) +++ return -EINVAL; +++ +++ err = 0; +++err1: +++ *len = n; +++ return err; +++} +++ +++static const struct nla_policy nft_flowtable_hook_policy[NFTA_FLOWTABLE_HOOK_MAX + 1] = { +++ [NFTA_FLOWTABLE_HOOK_NUM] = { .type = NLA_U32 }, +++ [NFTA_FLOWTABLE_HOOK_PRIORITY] = { .type = NLA_U32 }, +++ [NFTA_FLOWTABLE_HOOK_DEVS] = { .type = NLA_NESTED }, +++}; +++ +++static int nf_tables_flowtable_parse_hook(const struct nft_ctx *ctx, +++ const struct nlattr *attr, +++ struct nft_flowtable *flowtable) +++{ +++ struct net_device *dev_array[NFT_FLOWTABLE_DEVICE_MAX]; +++ struct nlattr *tb[NFTA_FLOWTABLE_HOOK_MAX + 1]; +++ struct nf_hook_ops *ops; +++ int hooknum, priority; +++ int err, n = 0, i; +++ +++ err = nla_parse_nested(tb, NFTA_FLOWTABLE_HOOK_MAX, attr, +++ nft_flowtable_hook_policy, NULL); +++ if (err < 0) +++ return err; +++ +++ if (!tb[NFTA_FLOWTABLE_HOOK_NUM] || +++ !tb[NFTA_FLOWTABLE_HOOK_PRIORITY] || +++ !tb[NFTA_FLOWTABLE_HOOK_DEVS]) +++ return -EINVAL; +++ +++ hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM])); +++ if (hooknum >= ctx->afi->nhooks) +++ return -EINVAL; +++ +++ priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY])); +++ +++ err = nf_tables_parse_devices(ctx, tb[NFTA_FLOWTABLE_HOOK_DEVS], +++ dev_array, &n); +++ if (err < 0) +++ goto err1; +++ +++ ops = kzalloc(sizeof(struct nf_hook_ops) * n, GFP_KERNEL); +++ if (!ops) { +++ err = -ENOMEM; +++ goto err1; +++ } +++ +++ flowtable->ops = ops; +++ flowtable->ops_len = n; +++ +++ for (i = 0; i < n; i++) { +++ flowtable->ops[i].pf = NFPROTO_NETDEV; +++ flowtable->ops[i].hooknum = hooknum; +++ flowtable->ops[i].priority = priority; +++ flowtable->ops[i].priv = &flowtable->data.rhashtable; +++ flowtable->ops[i].hook = flowtable->data.type->hook; +++ flowtable->ops[i].dev = dev_array[i]; +++ } +++ +++ err = 0; +++err1: +++ for (i = 0; i < n; i++) +++ dev_put(dev_array[i]); +++ +++ return err; +++} +++ +++static const struct nf_flowtable_type * +++__nft_flowtable_type_get(const struct nft_af_info *afi) +++{ +++ const struct nf_flowtable_type *type; +++ +++ list_for_each_entry(type, &nf_tables_flowtables, list) { +++ if (afi->family == type->family) +++ return type; +++ } +++ return NULL; +++} +++ +++static const struct nf_flowtable_type * +++nft_flowtable_type_get(const struct nft_af_info *afi) +++{ +++ const struct nf_flowtable_type *type; +++ +++ type = __nft_flowtable_type_get(afi); +++ if (type != NULL && try_module_get(type->owner)) +++ return type; +++ +++#ifdef CONFIG_MODULES +++ if (type == NULL) { +++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); +++ request_module("nf-flowtable-%u", afi->family); +++ nfnl_lock(NFNL_SUBSYS_NFTABLES); +++ if (__nft_flowtable_type_get(afi)) +++ return ERR_PTR(-EAGAIN); +++ } +++#endif +++ return ERR_PTR(-ENOENT); +++} +++ +++void nft_flow_table_iterate(struct net *net, +++ void (*iter)(struct nf_flowtable *flowtable, void *data), +++ void *data) +++{ +++ struct nft_flowtable *flowtable; +++ const struct nft_af_info *afi; +++ const struct nft_table *table; +++ +++ rcu_read_lock(); +++ list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +++ list_for_each_entry_rcu(table, &afi->tables, list) { +++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { +++ iter(&flowtable->data, data); +++ } +++ } +++ } +++ rcu_read_unlock(); +++} +++EXPORT_SYMBOL_GPL(nft_flow_table_iterate); +++ +++static void nft_unregister_flowtable_net_hooks(struct net *net, +++ struct nft_flowtable *flowtable) +++{ +++ int i; +++ +++ for (i = 0; i < flowtable->ops_len; i++) { +++ if (!flowtable->ops[i].dev) +++ continue; +++ +++ nf_unregister_net_hook(net, &flowtable->ops[i]); +++ } +++} +++ +++static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, +++ struct sk_buff *skb, +++ const struct nlmsghdr *nlh, +++ const struct nlattr * const nla[], +++ struct netlink_ext_ack *extack) +++{ +++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); +++ const struct nf_flowtable_type *type; +++ u8 genmask = nft_genmask_next(net); +++ int family = nfmsg->nfgen_family; +++ struct nft_flowtable *flowtable; +++ struct nft_af_info *afi; +++ struct nft_table *table; +++ struct nft_ctx ctx; +++ int err, i, k; +++ +++ if (!nla[NFTA_FLOWTABLE_TABLE] || +++ !nla[NFTA_FLOWTABLE_NAME] || +++ !nla[NFTA_FLOWTABLE_HOOK]) +++ return -EINVAL; +++ +++ afi = nf_tables_afinfo_lookup(net, family, true); +++ if (IS_ERR(afi)) +++ return PTR_ERR(afi); +++ +++ table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); +++ if (IS_ERR(table)) +++ return PTR_ERR(table); +++ +++ flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], +++ genmask); +++ if (IS_ERR(flowtable)) { +++ err = PTR_ERR(flowtable); +++ if (err != -ENOENT) +++ return err; +++ } else { +++ if (nlh->nlmsg_flags & NLM_F_EXCL) +++ return -EEXIST; +++ +++ return 0; +++ } +++ +++ nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ +++ flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL); +++ if (!flowtable) +++ return -ENOMEM; +++ +++ flowtable->table = table; +++ flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); +++ if (!flowtable->name) { +++ err = -ENOMEM; +++ goto err1; +++ } +++ +++ type = nft_flowtable_type_get(afi); +++ if (IS_ERR(type)) { +++ err = PTR_ERR(type); +++ goto err2; +++ } +++ +++ flowtable->data.type = type; +++ err = rhashtable_init(&flowtable->data.rhashtable, type->params); +++ if (err < 0) +++ goto err3; +++ +++ err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK], +++ flowtable); +++ if (err < 0) +++ goto err3; +++ +++ for (i = 0; i < flowtable->ops_len; i++) { +++ err = nf_register_net_hook(net, &flowtable->ops[i]); +++ if (err < 0) +++ goto err4; +++ } +++ +++ err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable); +++ if (err < 0) +++ goto err5; +++ +++ INIT_DEFERRABLE_WORK(&flowtable->data.gc_work, type->gc); +++ queue_delayed_work(system_power_efficient_wq, +++ &flowtable->data.gc_work, HZ); +++ +++ list_add_tail_rcu(&flowtable->list, &table->flowtables); +++ table->use++; +++ +++ return 0; +++err5: +++ i = flowtable->ops_len; +++err4: +++ for (k = i - 1; k >= 0; k--) +++ nf_unregister_net_hook(net, &flowtable->ops[i]); +++ +++ kfree(flowtable->ops); +++err3: +++ module_put(type->owner); +++err2: +++ kfree(flowtable->name); +++err1: +++ kfree(flowtable); +++ return err; +++} +++ +++static int nf_tables_delflowtable(struct net *net, struct sock *nlsk, +++ struct sk_buff *skb, +++ const struct nlmsghdr *nlh, +++ const struct nlattr * const nla[], +++ struct netlink_ext_ack *extack) +++{ +++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); +++ u8 genmask = nft_genmask_next(net); +++ int family = nfmsg->nfgen_family; +++ struct nft_flowtable *flowtable; +++ struct nft_af_info *afi; +++ struct nft_table *table; +++ struct nft_ctx ctx; +++ +++ afi = nf_tables_afinfo_lookup(net, family, true); +++ if (IS_ERR(afi)) +++ return PTR_ERR(afi); +++ +++ table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); +++ if (IS_ERR(table)) +++ return PTR_ERR(table); +++ +++ flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], +++ genmask); +++ if (IS_ERR(flowtable)) +++ return PTR_ERR(flowtable); +++ if (flowtable->use > 0) +++ return -EBUSY; +++ +++ nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ +++ return nft_delflowtable(&ctx, flowtable); +++} +++ +++static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net, +++ u32 portid, u32 seq, int event, +++ u32 flags, int family, +++ struct nft_flowtable *flowtable) +++{ +++ struct nlattr *nest, *nest_devs; +++ struct nfgenmsg *nfmsg; +++ struct nlmsghdr *nlh; +++ int i; +++ +++ event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); +++ nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags); +++ if (nlh == NULL) +++ goto nla_put_failure; +++ +++ nfmsg = nlmsg_data(nlh); +++ nfmsg->nfgen_family = family; +++ nfmsg->version = NFNETLINK_V0; +++ nfmsg->res_id = htons(net->nft.base_seq & 0xffff); +++ +++ if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || +++ nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || +++ nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use))) +++ goto nla_put_failure; +++ +++ nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); +++ if (nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_NUM, htonl(flowtable->hooknum)) || +++ nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(flowtable->priority))) +++ goto nla_put_failure; +++ +++ nest_devs = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK_DEVS); +++ if (!nest_devs) +++ goto nla_put_failure; +++ +++ for (i = 0; i < flowtable->ops_len; i++) { +++ if (flowtable->ops[i].dev && +++ nla_put_string(skb, NFTA_DEVICE_NAME, +++ flowtable->ops[i].dev->name)) +++ goto nla_put_failure; +++ } +++ nla_nest_end(skb, nest_devs); +++ nla_nest_end(skb, nest); +++ +++ nlmsg_end(skb, nlh); +++ return 0; +++ +++nla_put_failure: +++ nlmsg_trim(skb, nlh); +++ return -1; +++} +++ +++struct nft_flowtable_filter { +++ char *table; +++}; +++ +++static int nf_tables_dump_flowtable(struct sk_buff *skb, +++ struct netlink_callback *cb) +++{ +++ const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); +++ struct nft_flowtable_filter *filter = cb->data; +++ unsigned int idx = 0, s_idx = cb->args[0]; +++ struct net *net = sock_net(skb->sk); +++ int family = nfmsg->nfgen_family; +++ struct nft_flowtable *flowtable; +++ const struct nft_af_info *afi; +++ const struct nft_table *table; +++ +++ rcu_read_lock(); +++ cb->seq = net->nft.base_seq; +++ +++ list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +++ if (family != NFPROTO_UNSPEC && family != afi->family) +++ continue; +++ +++ list_for_each_entry_rcu(table, &afi->tables, list) { +++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { +++ if (!nft_is_active(net, flowtable)) +++ goto cont; +++ if (idx < s_idx) +++ goto cont; +++ if (idx > s_idx) +++ memset(&cb->args[1], 0, +++ sizeof(cb->args) - sizeof(cb->args[0])); +++ if (filter && filter->table[0] && +++ strcmp(filter->table, table->name)) +++ goto cont; +++ +++ if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, +++ cb->nlh->nlmsg_seq, +++ NFT_MSG_NEWFLOWTABLE, +++ NLM_F_MULTI | NLM_F_APPEND, +++ afi->family, flowtable) < 0) +++ goto done; +++ +++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +++cont: +++ idx++; +++ } +++ } +++ } +++done: +++ rcu_read_unlock(); +++ +++ cb->args[0] = idx; +++ return skb->len; +++} +++ +++static int nf_tables_dump_flowtable_done(struct netlink_callback *cb) +++{ +++ struct nft_flowtable_filter *filter = cb->data; +++ +++ if (!filter) +++ return 0; +++ +++ kfree(filter->table); +++ kfree(filter); +++ +++ return 0; +++} +++ +++static struct nft_flowtable_filter * +++nft_flowtable_filter_alloc(const struct nlattr * const nla[]) +++{ +++ struct nft_flowtable_filter *filter; +++ +++ filter = kzalloc(sizeof(*filter), GFP_KERNEL); +++ if (!filter) +++ return ERR_PTR(-ENOMEM); +++ +++ if (nla[NFTA_FLOWTABLE_TABLE]) { +++ filter->table = nla_strdup(nla[NFTA_FLOWTABLE_TABLE], +++ GFP_KERNEL); +++ if (!filter->table) { +++ kfree(filter); +++ return ERR_PTR(-ENOMEM); +++ } +++ } +++ return filter; +++} +++ +++static int nf_tables_getflowtable(struct net *net, struct sock *nlsk, +++ struct sk_buff *skb, +++ const struct nlmsghdr *nlh, +++ const struct nlattr * const nla[], +++ struct netlink_ext_ack *extack) +++{ +++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); +++ u8 genmask = nft_genmask_cur(net); +++ int family = nfmsg->nfgen_family; +++ struct nft_flowtable *flowtable; +++ const struct nft_af_info *afi; +++ const struct nft_table *table; +++ struct sk_buff *skb2; +++ int err; +++ +++ if (nlh->nlmsg_flags & NLM_F_DUMP) { +++ struct netlink_dump_control c = { +++ .dump = nf_tables_dump_flowtable, +++ .done = nf_tables_dump_flowtable_done, +++ }; +++ +++ if (nla[NFTA_FLOWTABLE_TABLE]) { +++ struct nft_flowtable_filter *filter; +++ +++ filter = nft_flowtable_filter_alloc(nla); +++ if (IS_ERR(filter)) +++ return -ENOMEM; +++ +++ c.data = filter; +++ } +++ return netlink_dump_start(nlsk, skb, nlh, &c); +++ } +++ +++ if (!nla[NFTA_FLOWTABLE_NAME]) +++ return -EINVAL; +++ +++ afi = nf_tables_afinfo_lookup(net, family, false); +++ if (IS_ERR(afi)) +++ return PTR_ERR(afi); +++ +++ table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); +++ if (IS_ERR(table)) +++ return PTR_ERR(table); +++ +++ flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], +++ genmask); +++ if (IS_ERR(table)) +++ return PTR_ERR(flowtable); +++ +++ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); +++ if (!skb2) +++ return -ENOMEM; +++ +++ err = nf_tables_fill_flowtable_info(skb2, net, NETLINK_CB(skb).portid, +++ nlh->nlmsg_seq, +++ NFT_MSG_NEWFLOWTABLE, 0, family, +++ flowtable); +++ if (err < 0) +++ goto err; +++ +++ return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid); +++err: +++ kfree_skb(skb2); +++ return err; +++} +++ +++static void nf_tables_flowtable_notify(struct nft_ctx *ctx, +++ struct nft_flowtable *flowtable, +++ int event) +++{ +++ struct sk_buff *skb; +++ int err; +++ +++ if (ctx->report && +++ !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) +++ return; +++ +++ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); +++ if (skb == NULL) +++ goto err; +++ +++ err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid, +++ ctx->seq, event, 0, +++ ctx->afi->family, flowtable); +++ if (err < 0) { +++ kfree_skb(skb); +++ goto err; +++ } +++ +++ nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES, +++ ctx->report, GFP_KERNEL); +++ return; +++err: +++ nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS); +++} +++ +++static void nft_flowtable_destroy(void *ptr, void *arg) +++{ +++ kfree(ptr); +++} +++ +++static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) +++{ +++ cancel_delayed_work_sync(&flowtable->data.gc_work); +++ kfree(flowtable->name); +++ rhashtable_free_and_destroy(&flowtable->data.rhashtable, +++ nft_flowtable_destroy, NULL); +++ module_put(flowtable->data.type->owner); +++} +++ ++ static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, ++ u32 portid, u32 seq) ++ { ++@@ -4892,6 +5535,49 @@ nla_put_failure: ++ return -EMSGSIZE; ++ } ++ +++static void nft_flowtable_event(unsigned long event, struct net_device *dev, +++ struct nft_flowtable *flowtable) +++{ +++ int i; +++ +++ for (i = 0; i < flowtable->ops_len; i++) { +++ if (flowtable->ops[i].dev != dev) +++ continue; +++ +++ nf_unregister_net_hook(dev_net(dev), &flowtable->ops[i]); +++ flowtable->ops[i].dev = NULL; +++ break; +++ } +++} +++ +++static int nf_tables_flowtable_event(struct notifier_block *this, +++ unsigned long event, void *ptr) +++{ +++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); +++ struct nft_flowtable *flowtable; +++ struct nft_table *table; +++ struct nft_af_info *afi; +++ +++ if (event != NETDEV_UNREGISTER) +++ return 0; +++ +++ nfnl_lock(NFNL_SUBSYS_NFTABLES); +++ list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { +++ list_for_each_entry(table, &afi->tables, list) { +++ list_for_each_entry(flowtable, &table->flowtables, list) { +++ nft_flowtable_event(event, dev, flowtable); +++ } +++ } +++ } +++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); +++ +++ return NOTIFY_DONE; +++} +++ +++static struct notifier_block nf_tables_flowtable_notifier = { +++ .notifier_call = nf_tables_flowtable_event, +++}; +++ ++ static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb, ++ int event) ++ { ++@@ -5044,6 +5730,21 @@ static const struct nfnl_callback nf_tab ++ .attr_count = NFTA_OBJ_MAX, ++ .policy = nft_obj_policy, ++ }, +++ [NFT_MSG_NEWFLOWTABLE] = { +++ .call_batch = nf_tables_newflowtable, +++ .attr_count = NFTA_FLOWTABLE_MAX, +++ .policy = nft_flowtable_policy, +++ }, +++ [NFT_MSG_GETFLOWTABLE] = { +++ .call = nf_tables_getflowtable, +++ .attr_count = NFTA_FLOWTABLE_MAX, +++ .policy = nft_flowtable_policy, +++ }, +++ [NFT_MSG_DELFLOWTABLE] = { +++ .call_batch = nf_tables_delflowtable, +++ .attr_count = NFTA_FLOWTABLE_MAX, +++ .policy = nft_flowtable_policy, +++ }, ++ }; ++ ++ static void nft_chain_commit_update(struct nft_trans *trans) ++@@ -5092,6 +5793,9 @@ static void nf_tables_commit_release(str ++ case NFT_MSG_DELOBJ: ++ nft_obj_destroy(nft_trans_obj(trans)); ++ break; +++ case NFT_MSG_DELFLOWTABLE: +++ nf_tables_flowtable_destroy(nft_trans_flowtable(trans)); +++ break; ++ } ++ kfree(trans); ++ } ++@@ -5211,6 +5915,21 @@ static int nf_tables_commit(struct net * ++ nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans), ++ NFT_MSG_DELOBJ); ++ break; +++ case NFT_MSG_NEWFLOWTABLE: +++ nft_clear(net, nft_trans_flowtable(trans)); +++ nf_tables_flowtable_notify(&trans->ctx, +++ nft_trans_flowtable(trans), +++ NFT_MSG_NEWFLOWTABLE); +++ nft_trans_destroy(trans); +++ break; +++ case NFT_MSG_DELFLOWTABLE: +++ list_del_rcu(&nft_trans_flowtable(trans)->list); +++ nf_tables_flowtable_notify(&trans->ctx, +++ nft_trans_flowtable(trans), +++ NFT_MSG_DELFLOWTABLE); +++ nft_unregister_flowtable_net_hooks(net, +++ nft_trans_flowtable(trans)); +++ break; ++ } ++ } ++ ++@@ -5248,6 +5967,9 @@ static void nf_tables_abort_release(stru ++ case NFT_MSG_NEWOBJ: ++ nft_obj_destroy(nft_trans_obj(trans)); ++ break; +++ case NFT_MSG_NEWFLOWTABLE: +++ nf_tables_flowtable_destroy(nft_trans_flowtable(trans)); +++ break; ++ } ++ kfree(trans); ++ } ++@@ -5339,6 +6061,17 @@ static int nf_tables_abort(struct net *n ++ nft_clear(trans->ctx.net, nft_trans_obj(trans)); ++ nft_trans_destroy(trans); ++ break; +++ case NFT_MSG_NEWFLOWTABLE: +++ trans->ctx.table->use--; +++ list_del_rcu(&nft_trans_flowtable(trans)->list); +++ nft_unregister_flowtable_net_hooks(net, +++ nft_trans_flowtable(trans)); +++ break; +++ case NFT_MSG_DELFLOWTABLE: +++ trans->ctx.table->use++; +++ nft_clear(trans->ctx.net, nft_trans_flowtable(trans)); +++ nft_trans_destroy(trans); +++ break; ++ } ++ } ++ ++@@ -5889,6 +6622,7 @@ EXPORT_SYMBOL_GPL(__nft_release_basechai ++ /* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */ ++ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) ++ { +++ struct nft_flowtable *flowtable, *nf; ++ struct nft_table *table, *nt; ++ struct nft_chain *chain, *nc; ++ struct nft_object *obj, *ne; ++@@ -5902,6 +6636,9 @@ static void __nft_release_afinfo(struct ++ list_for_each_entry_safe(table, nt, &afi->tables, list) { ++ list_for_each_entry(chain, &table->chains, list) ++ nf_tables_unregister_hook(net, table, chain); +++ list_for_each_entry(flowtable, &table->flowtables, list) +++ nf_unregister_net_hooks(net, flowtable->ops, +++ flowtable->ops_len); ++ /* No packets are walking on these chains anymore. */ ++ ctx.table = table; ++ list_for_each_entry(chain, &table->chains, list) { ++@@ -5912,6 +6649,11 @@ static void __nft_release_afinfo(struct ++ nf_tables_rule_release(&ctx, rule); ++ } ++ } +++ list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) { +++ list_del(&flowtable->list); +++ table->use--; +++ nf_tables_flowtable_destroy(flowtable); +++ } ++ list_for_each_entry_safe(set, ns, &table->sets, list) { ++ list_del(&set->list); ++ table->use--; ++@@ -5955,6 +6697,8 @@ static int __init nf_tables_module_init( ++ if (err < 0) ++ goto err3; ++ +++ register_netdevice_notifier(&nf_tables_flowtable_notifier); +++ ++ pr_info("nf_tables: (c) 2007-2009 Patrick McHardy \n"); ++ return register_pernet_subsys(&nf_tables_net_ops); ++ err3: ++@@ -5969,6 +6713,7 @@ static void __exit nf_tables_module_exit ++ { ++ unregister_pernet_subsys(&nf_tables_net_ops); ++ nfnetlink_subsys_unregister(&nf_tables_subsys); +++ unregister_netdevice_notifier(&nf_tables_flowtable_notifier); ++ rcu_barrier(); ++ nf_tables_core_module_exit(); ++ kfree(info); +diff --git a/target/linux/generic/backport-4.14/322-v4.16-netfilter-add-generic-flow-table-infrastructure.patch b/target/linux/generic/backport-4.14/322-v4.16-netfilter-add-generic-flow-table-infrastructure.patch +new file mode 100644 +index 0000000000..16de9571a8 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/322-v4.16-netfilter-add-generic-flow-table-infrastructure.patch +@@ -0,0 +1,586 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 7 Jan 2018 01:04:11 +0100 ++Subject: [PATCH] netfilter: add generic flow table infrastructure ++ ++This patch defines the API to interact with flow tables, this allows to ++add, delete and lookup for entries in the flow table. This also adds the ++generic garbage code that removes entries that have expired, ie. no ++traffic has been seen for a while. ++ ++Users of the flow table infrastructure can delete entries via ++flow_offload_dead(), which sets the dying bit, this signals the garbage ++collector to release an entry from user context. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ create mode 100644 net/netfilter/nf_flow_table.c ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -1,7 +1,12 @@ ++ #ifndef _NF_FLOW_TABLE_H ++ #define _NF_FLOW_TABLE_H ++ +++#include +++#include +++#include ++ #include +++#include +++#include ++ ++ struct nf_flowtable; ++ ++@@ -20,4 +25,93 @@ struct nf_flowtable { ++ struct delayed_work gc_work; ++ }; ++ +++enum flow_offload_tuple_dir { +++ FLOW_OFFLOAD_DIR_ORIGINAL, +++ FLOW_OFFLOAD_DIR_REPLY, +++ __FLOW_OFFLOAD_DIR_MAX = FLOW_OFFLOAD_DIR_REPLY, +++}; +++#define FLOW_OFFLOAD_DIR_MAX (__FLOW_OFFLOAD_DIR_MAX + 1) +++ +++struct flow_offload_tuple { +++ union { +++ struct in_addr src_v4; +++ struct in6_addr src_v6; +++ }; +++ union { +++ struct in_addr dst_v4; +++ struct in6_addr dst_v6; +++ }; +++ struct { +++ __be16 src_port; +++ __be16 dst_port; +++ }; +++ +++ int iifidx; +++ +++ u8 l3proto; +++ u8 l4proto; +++ u8 dir; +++ +++ int oifidx; +++ +++ struct dst_entry *dst_cache; +++}; +++ +++struct flow_offload_tuple_rhash { +++ struct rhash_head node; +++ struct flow_offload_tuple tuple; +++}; +++ +++#define FLOW_OFFLOAD_SNAT 0x1 +++#define FLOW_OFFLOAD_DNAT 0x2 +++#define FLOW_OFFLOAD_DYING 0x4 +++ +++struct flow_offload { +++ struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; +++ u32 flags; +++ union { +++ /* Your private driver data here. */ +++ u32 timeout; +++ }; +++}; +++ +++#define NF_FLOW_TIMEOUT (30 * HZ) +++ +++struct nf_flow_route { +++ struct { +++ struct dst_entry *dst; +++ int ifindex; +++ } tuple[FLOW_OFFLOAD_DIR_MAX]; +++}; +++ +++struct flow_offload *flow_offload_alloc(struct nf_conn *ct, +++ struct nf_flow_route *route); +++void flow_offload_free(struct flow_offload *flow); +++ +++int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); +++void flow_offload_del(struct nf_flowtable *flow_table, struct flow_offload *flow); +++struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table, +++ struct flow_offload_tuple *tuple); +++int nf_flow_table_iterate(struct nf_flowtable *flow_table, +++ void (*iter)(struct flow_offload *flow, void *data), +++ void *data); +++void nf_flow_offload_work_gc(struct work_struct *work); +++extern const struct rhashtable_params nf_flow_offload_rhash_params; +++ +++void flow_offload_dead(struct flow_offload *flow); +++ +++int nf_flow_snat_port(const struct flow_offload *flow, +++ struct sk_buff *skb, unsigned int thoff, +++ u8 protocol, enum flow_offload_tuple_dir dir); +++int nf_flow_dnat_port(const struct flow_offload *flow, +++ struct sk_buff *skb, unsigned int thoff, +++ u8 protocol, enum flow_offload_tuple_dir dir); +++ +++struct flow_ports { +++ __be16 source, dest; +++}; +++ +++#define MODULE_ALIAS_NF_FLOWTABLE(family) \ +++ MODULE_ALIAS("nf-flowtable-" __stringify(family)) +++ ++ #endif /* _FLOW_OFFLOAD_H */ ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -667,6 +667,13 @@ endif # NF_TABLES_NETDEV ++ ++ endif # NF_TABLES ++ +++config NF_FLOW_TABLE +++ tristate "Netfilter flow table module" +++ help +++ This option adds the flow table core infrastructure. +++ +++ To compile it as a module, choose M here. +++ ++ config NETFILTER_XTABLES ++ tristate "Netfilter Xtables support (required for ip_tables)" ++ default m if NETFILTER_ADVANCED=n ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -110,6 +110,9 @@ obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_ ++ obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o ++ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o ++ +++# flow table infrastructure +++obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o +++ ++ # generic X tables ++ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o ++ ++--- /dev/null +++++ b/net/netfilter/nf_flow_table.c ++@@ -0,0 +1,429 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++struct flow_offload_entry { +++ struct flow_offload flow; +++ struct nf_conn *ct; +++ struct rcu_head rcu_head; +++}; +++ +++struct flow_offload * +++flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) +++{ +++ struct flow_offload_entry *entry; +++ struct flow_offload *flow; +++ +++ if (unlikely(nf_ct_is_dying(ct) || +++ !atomic_inc_not_zero(&ct->ct_general.use))) +++ return NULL; +++ +++ entry = kzalloc(sizeof(*entry), GFP_ATOMIC); +++ if (!entry) +++ goto err_ct_refcnt; +++ +++ flow = &entry->flow; +++ +++ if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst)) +++ goto err_dst_cache_original; +++ +++ if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst)) +++ goto err_dst_cache_reply; +++ +++ entry->ct = ct; +++ +++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) { +++ case NFPROTO_IPV4: +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4 = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4 = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4 = +++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4 = +++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in; +++ break; +++ case NFPROTO_IPV6: +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6 = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in6; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6 = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6 = +++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in6; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6 = +++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in6; +++ break; +++ } +++ +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l3proto = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l4proto = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.l3proto = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.l4proto = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; +++ +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache = +++ route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache = +++ route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst; +++ +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port = +++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port = +++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.tcp.port; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port = +++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; +++ +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dir = +++ FLOW_OFFLOAD_DIR_ORIGINAL; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dir = +++ FLOW_OFFLOAD_DIR_REPLY; +++ +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.iifidx = +++ route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].ifindex; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.oifidx = +++ route->tuple[FLOW_OFFLOAD_DIR_REPLY].ifindex; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.iifidx = +++ route->tuple[FLOW_OFFLOAD_DIR_REPLY].ifindex; +++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.oifidx = +++ route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].ifindex; +++ +++ if (ct->status & IPS_SRC_NAT) +++ flow->flags |= FLOW_OFFLOAD_SNAT; +++ else if (ct->status & IPS_DST_NAT) +++ flow->flags |= FLOW_OFFLOAD_DNAT; +++ +++ return flow; +++ +++err_dst_cache_reply: +++ dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst); +++err_dst_cache_original: +++ kfree(entry); +++err_ct_refcnt: +++ nf_ct_put(ct); +++ +++ return NULL; +++} +++EXPORT_SYMBOL_GPL(flow_offload_alloc); +++ +++void flow_offload_free(struct flow_offload *flow) +++{ +++ struct flow_offload_entry *e; +++ +++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); +++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); +++ e = container_of(flow, struct flow_offload_entry, flow); +++ kfree(e); +++} +++EXPORT_SYMBOL_GPL(flow_offload_free); +++ +++void flow_offload_dead(struct flow_offload *flow) +++{ +++ flow->flags |= FLOW_OFFLOAD_DYING; +++} +++EXPORT_SYMBOL_GPL(flow_offload_dead); +++ +++int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) +++{ +++ flow->timeout = (u32)jiffies; +++ +++ rhashtable_insert_fast(&flow_table->rhashtable, +++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +++ *flow_table->type->params); +++ rhashtable_insert_fast(&flow_table->rhashtable, +++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, +++ *flow_table->type->params); +++ return 0; +++} +++EXPORT_SYMBOL_GPL(flow_offload_add); +++ +++void flow_offload_del(struct nf_flowtable *flow_table, +++ struct flow_offload *flow) +++{ +++ struct flow_offload_entry *e; +++ +++ rhashtable_remove_fast(&flow_table->rhashtable, +++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +++ *flow_table->type->params); +++ rhashtable_remove_fast(&flow_table->rhashtable, +++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, +++ *flow_table->type->params); +++ +++ e = container_of(flow, struct flow_offload_entry, flow); +++ kfree_rcu(e, rcu_head); +++} +++EXPORT_SYMBOL_GPL(flow_offload_del); +++ +++struct flow_offload_tuple_rhash * +++flow_offload_lookup(struct nf_flowtable *flow_table, +++ struct flow_offload_tuple *tuple) +++{ +++ return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, +++ *flow_table->type->params); +++} +++EXPORT_SYMBOL_GPL(flow_offload_lookup); +++ +++static void nf_flow_release_ct(const struct flow_offload *flow) +++{ +++ struct flow_offload_entry *e; +++ +++ e = container_of(flow, struct flow_offload_entry, flow); +++ nf_ct_delete(e->ct, 0, 0); +++ nf_ct_put(e->ct); +++} +++ +++int nf_flow_table_iterate(struct nf_flowtable *flow_table, +++ void (*iter)(struct flow_offload *flow, void *data), +++ void *data) +++{ +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct rhashtable_iter hti; +++ struct flow_offload *flow; +++ int err; +++ +++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); +++ if (err) +++ return err; +++ +++ rhashtable_walk_start(&hti); +++ +++ while ((tuplehash = rhashtable_walk_next(&hti))) { +++ if (IS_ERR(tuplehash)) { +++ err = PTR_ERR(tuplehash); +++ if (err != -EAGAIN) +++ goto out; +++ +++ continue; +++ } +++ if (tuplehash->tuple.dir) +++ continue; +++ +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); +++ +++ iter(flow, data); +++ } +++out: +++ rhashtable_walk_stop(&hti); +++ rhashtable_walk_exit(&hti); +++ +++ return err; +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_iterate); +++ +++static inline bool nf_flow_has_expired(const struct flow_offload *flow) +++{ +++ return (__s32)(flow->timeout - (u32)jiffies) <= 0; +++} +++ +++static inline bool nf_flow_is_dying(const struct flow_offload *flow) +++{ +++ return flow->flags & FLOW_OFFLOAD_DYING; +++} +++ +++void nf_flow_offload_work_gc(struct work_struct *work) +++{ +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct nf_flowtable *flow_table; +++ struct rhashtable_iter hti; +++ struct flow_offload *flow; +++ int err; +++ +++ flow_table = container_of(work, struct nf_flowtable, gc_work.work); +++ +++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); +++ if (err) +++ goto schedule; +++ +++ rhashtable_walk_start(&hti); +++ +++ while ((tuplehash = rhashtable_walk_next(&hti))) { +++ if (IS_ERR(tuplehash)) { +++ err = PTR_ERR(tuplehash); +++ if (err != -EAGAIN) +++ goto out; +++ +++ continue; +++ } +++ if (tuplehash->tuple.dir) +++ continue; +++ +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); +++ +++ if (nf_flow_has_expired(flow) || +++ nf_flow_is_dying(flow)) { +++ flow_offload_del(flow_table, flow); +++ nf_flow_release_ct(flow); +++ } +++ } +++out: +++ rhashtable_walk_stop(&hti); +++ rhashtable_walk_exit(&hti); +++schedule: +++ queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); +++} +++EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); +++ +++static u32 flow_offload_hash(const void *data, u32 len, u32 seed) +++{ +++ const struct flow_offload_tuple *tuple = data; +++ +++ return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); +++} +++ +++static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) +++{ +++ const struct flow_offload_tuple_rhash *tuplehash = data; +++ +++ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); +++} +++ +++static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, +++ const void *ptr) +++{ +++ const struct flow_offload_tuple *tuple = arg->key; +++ const struct flow_offload_tuple_rhash *x = ptr; +++ +++ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) +++ return 1; +++ +++ return 0; +++} +++ +++const struct rhashtable_params nf_flow_offload_rhash_params = { +++ .head_offset = offsetof(struct flow_offload_tuple_rhash, node), +++ .hashfn = flow_offload_hash, +++ .obj_hashfn = flow_offload_hash_obj, +++ .obj_cmpfn = flow_offload_hash_cmp, +++ .automatic_shrinking = true, +++}; +++EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); +++ +++static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, +++ __be16 port, __be16 new_port) +++{ +++ struct tcphdr *tcph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) +++ return -1; +++ +++ tcph = (void *)(skb_network_header(skb) + thoff); +++ inet_proto_csum_replace2(&tcph->check, skb, port, new_port, true); +++ +++ return 0; +++} +++ +++static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, +++ __be16 port, __be16 new_port) +++{ +++ struct udphdr *udph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*udph))) +++ return -1; +++ +++ udph = (void *)(skb_network_header(skb) + thoff); +++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +++ inet_proto_csum_replace2(&udph->check, skb, port, +++ new_port, true); +++ if (!udph->check) +++ udph->check = CSUM_MANGLED_0; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, +++ u8 protocol, __be16 port, __be16 new_port) +++{ +++ switch (protocol) { +++ case IPPROTO_TCP: +++ if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0) +++ return NF_DROP; +++ break; +++ case IPPROTO_UDP: +++ if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0) +++ return NF_DROP; +++ break; +++ } +++ +++ return 0; +++} +++ +++int nf_flow_snat_port(const struct flow_offload *flow, +++ struct sk_buff *skb, unsigned int thoff, +++ u8 protocol, enum flow_offload_tuple_dir dir) +++{ +++ struct flow_ports *hdr; +++ __be16 port, new_port; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || +++ skb_try_make_writable(skb, thoff + sizeof(*hdr))) +++ return -1; +++ +++ hdr = (void *)(skb_network_header(skb) + thoff); +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ port = hdr->source; +++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port; +++ hdr->source = new_port; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ port = hdr->dest; +++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; +++ hdr->dest = new_port; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_port(skb, thoff, protocol, port, new_port); +++} +++EXPORT_SYMBOL_GPL(nf_flow_snat_port); +++ +++int nf_flow_dnat_port(const struct flow_offload *flow, +++ struct sk_buff *skb, unsigned int thoff, +++ u8 protocol, enum flow_offload_tuple_dir dir) +++{ +++ struct flow_ports *hdr; +++ __be16 port, new_port; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || +++ skb_try_make_writable(skb, thoff + sizeof(*hdr))) +++ return -1; +++ +++ hdr = (void *)(skb_network_header(skb) + thoff); +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ port = hdr->dest; +++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port; +++ hdr->dest = new_port; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ port = hdr->source; +++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port; +++ hdr->source = new_port; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_port(skb, thoff, protocol, port, new_port); +++} +++EXPORT_SYMBOL_GPL(nf_flow_dnat_port); +++ +++MODULE_LICENSE("GPL"); +++MODULE_AUTHOR("Pablo Neira Ayuso "); +diff --git a/target/linux/generic/backport-4.14/323-v4.16-netfilter-flow-table-support-for-IPv4.patch b/target/linux/generic/backport-4.14/323-v4.16-netfilter-flow-table-support-for-IPv4.patch +new file mode 100644 +index 0000000000..50d9039c12 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/323-v4.16-netfilter-flow-table-support-for-IPv4.patch +@@ -0,0 +1,334 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 7 Jan 2018 01:04:15 +0100 ++Subject: [PATCH] netfilter: flow table support for IPv4 ++ ++This patch adds the IPv4 flow table type, that implements the datapath ++flow table to forward IPv4 traffic. Rationale is: ++ ++1) Look up for the packet in the flow table, from the ingress hook. ++2) If there's a hit, decrement ttl and pass it on to the neighbour layer ++ for transmission. ++3) If there's a miss, packet is passed up to the classic forwarding ++ path. ++ ++This patch also supports layer 3 source and destination NAT. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ create mode 100644 net/ipv4/netfilter/nf_flow_table_ipv4.c ++ ++--- a/net/ipv4/netfilter/Kconfig +++++ b/net/ipv4/netfilter/Kconfig ++@@ -78,6 +78,14 @@ config NF_TABLES_ARP ++ ++ endif # NF_TABLES ++ +++config NF_FLOW_TABLE_IPV4 +++ select NF_FLOW_TABLE +++ tristate "Netfilter flow table IPv4 module" +++ help +++ This option adds the flow table IPv4 support. +++ +++ To compile it as a module, choose M here. +++ ++ config NF_DUP_IPV4 ++ tristate "Netfilter IPv4 packet duplication to alternate destination" ++ depends on !NF_CONNTRACK || NF_CONNTRACK ++--- a/net/ipv4/netfilter/Makefile +++++ b/net/ipv4/netfilter/Makefile ++@@ -43,6 +43,9 @@ obj-$(CONFIG_NFT_REDIR_IPV4) += nft_redi ++ obj-$(CONFIG_NFT_DUP_IPV4) += nft_dup_ipv4.o ++ obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o ++ +++# flow table support +++obj-$(CONFIG_NF_FLOW_TABLE_IPV4) += nf_flow_table_ipv4.o +++ ++ # generic IP tables ++ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o ++ ++--- /dev/null +++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c ++@@ -0,0 +1,283 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++/* For layer 4 checksum field offset. */ +++#include +++#include +++ +++static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, +++ __be32 addr, __be32 new_addr) +++{ +++ struct tcphdr *tcph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) +++ return -1; +++ +++ tcph = (void *)(skb_network_header(skb) + thoff); +++ inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); +++ +++ return 0; +++} +++ +++static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, +++ __be32 addr, __be32 new_addr) +++{ +++ struct udphdr *udph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*udph))) +++ return -1; +++ +++ udph = (void *)(skb_network_header(skb) + thoff); +++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +++ inet_proto_csum_replace4(&udph->check, skb, addr, +++ new_addr, true); +++ if (!udph->check) +++ udph->check = CSUM_MANGLED_0; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, +++ unsigned int thoff, __be32 addr, +++ __be32 new_addr) +++{ +++ switch (iph->protocol) { +++ case IPPROTO_TCP: +++ if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0) +++ return NF_DROP; +++ break; +++ case IPPROTO_UDP: +++ if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0) +++ return NF_DROP; +++ break; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb, +++ struct iphdr *iph, unsigned int thoff, +++ enum flow_offload_tuple_dir dir) +++{ +++ __be32 addr, new_addr; +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ addr = iph->saddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr; +++ iph->saddr = new_addr; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ addr = iph->daddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; +++ iph->daddr = new_addr; +++ break; +++ default: +++ return -1; +++ } +++ csum_replace4(&iph->check, addr, new_addr); +++ +++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); +++} +++ +++static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, +++ struct iphdr *iph, unsigned int thoff, +++ enum flow_offload_tuple_dir dir) +++{ +++ __be32 addr, new_addr; +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ addr = iph->daddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr; +++ iph->daddr = new_addr; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ addr = iph->saddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; +++ iph->saddr = new_addr; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); +++} +++ +++static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct iphdr *iph = ip_hdr(skb); +++ unsigned int thoff = iph->ihl * 4; +++ +++ if (flow->flags & FLOW_OFFLOAD_SNAT && +++ (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +++ nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) +++ return -1; +++ if (flow->flags & FLOW_OFFLOAD_DNAT && +++ (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +++ nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) +++ return -1; +++ +++ return 0; +++} +++ +++static bool ip_has_options(unsigned int thoff) +++{ +++ return thoff != sizeof(struct iphdr); +++} +++ +++static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, +++ struct flow_offload_tuple *tuple) +++{ +++ struct flow_ports *ports; +++ unsigned int thoff; +++ struct iphdr *iph; +++ +++ if (!pskb_may_pull(skb, sizeof(*iph))) +++ return -1; +++ +++ iph = ip_hdr(skb); +++ thoff = iph->ihl * 4; +++ +++ if (ip_is_fragment(iph) || +++ unlikely(ip_has_options(thoff))) +++ return -1; +++ +++ if (iph->protocol != IPPROTO_TCP && +++ iph->protocol != IPPROTO_UDP) +++ return -1; +++ +++ thoff = iph->ihl * 4; +++ if (!pskb_may_pull(skb, thoff + sizeof(*ports))) +++ return -1; +++ +++ ports = (struct flow_ports *)(skb_network_header(skb) + thoff); +++ +++ tuple->src_v4.s_addr = iph->saddr; +++ tuple->dst_v4.s_addr = iph->daddr; +++ tuple->src_port = ports->source; +++ tuple->dst_port = ports->dest; +++ tuple->l3proto = AF_INET; +++ tuple->l4proto = iph->protocol; +++ tuple->iifidx = dev->ifindex; +++ +++ return 0; +++} +++ +++/* Based on ip_exceeds_mtu(). */ +++static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +++{ +++ if (skb->len <= mtu) +++ return false; +++ +++ if ((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) +++ return false; +++ +++ if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) +++ return false; +++ +++ return true; +++} +++ +++static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rtable *rt) +++{ +++ u32 mtu; +++ +++ mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); +++ if (__nf_flow_exceeds_mtu(skb, mtu)) +++ return true; +++ +++ return false; +++} +++ +++static unsigned int +++nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct nf_flowtable *flow_table = priv; +++ struct flow_offload_tuple tuple = {}; +++ enum flow_offload_tuple_dir dir; +++ struct flow_offload *flow; +++ struct net_device *outdev; +++ const struct rtable *rt; +++ struct iphdr *iph; +++ __be32 nexthop; +++ +++ if (skb->protocol != htons(ETH_P_IP)) +++ return NF_ACCEPT; +++ +++ if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) +++ return NF_ACCEPT; +++ +++ tuplehash = flow_offload_lookup(flow_table, &tuple); +++ if (tuplehash == NULL) +++ return NF_ACCEPT; +++ +++ outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); +++ if (!outdev) +++ return NF_ACCEPT; +++ +++ dir = tuplehash->tuple.dir; +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +++ +++ rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; +++ if (unlikely(nf_flow_exceeds_mtu(skb, rt))) +++ return NF_ACCEPT; +++ +++ if (skb_try_make_writable(skb, sizeof(*iph))) +++ return NF_DROP; +++ +++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && +++ nf_flow_nat_ip(flow, skb, dir) < 0) +++ return NF_DROP; +++ +++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; +++ iph = ip_hdr(skb); +++ ip_decrease_ttl(iph); +++ +++ skb->dev = outdev; +++ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); +++ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); +++ +++ return NF_STOLEN; +++} +++ +++static struct nf_flowtable_type flowtable_ipv4 = { +++ .family = NFPROTO_IPV4, +++ .params = &nf_flow_offload_rhash_params, +++ .gc = nf_flow_offload_work_gc, +++ .hook = nf_flow_offload_ip_hook, +++ .owner = THIS_MODULE, +++}; +++ +++static int __init nf_flow_ipv4_module_init(void) +++{ +++ nft_register_flowtable_type(&flowtable_ipv4); +++ +++ return 0; +++} +++ +++static void __exit nf_flow_ipv4_module_exit(void) +++{ +++ nft_unregister_flowtable_type(&flowtable_ipv4); +++} +++ +++module_init(nf_flow_ipv4_module_init); +++module_exit(nf_flow_ipv4_module_exit); +++ +++MODULE_LICENSE("GPL"); +++MODULE_AUTHOR("Pablo Neira Ayuso "); +++MODULE_ALIAS_NF_FLOWTABLE(AF_INET); +diff --git a/target/linux/generic/backport-4.14/324-v4.16-netfilter-flow-table-support-for-IPv6.patch b/target/linux/generic/backport-4.14/324-v4.16-netfilter-flow-table-support-for-IPv6.patch +new file mode 100644 +index 0000000000..8e776383d1 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/324-v4.16-netfilter-flow-table-support-for-IPv6.patch +@@ -0,0 +1,354 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 7 Jan 2018 01:04:19 +0100 ++Subject: [PATCH] netfilter: flow table support for IPv6 ++ ++This patch adds the IPv6 flow table type, that implements the datapath ++flow table to forward IPv6 traffic. ++ ++This patch exports ip6_dst_mtu_forward() that is required to check for ++mtu to pass up packets that need PMTUD handling to the classic ++forwarding path. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ create mode 100644 net/ipv6/netfilter/nf_flow_table_ipv6.c ++ ++--- a/include/net/ipv6.h +++++ b/include/net/ipv6.h ++@@ -860,6 +860,8 @@ static inline struct sk_buff *ip6_finish ++ &inet6_sk(sk)->cork); ++ } ++ +++unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst); +++ ++ int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst, ++ struct flowi6 *fl6); ++ struct dst_entry *ip6_dst_lookup_flow(struct net *net, const struct sock *sk, struct flowi6 *fl6, ++--- a/net/ipv6/ip6_output.c +++++ b/net/ipv6/ip6_output.c ++@@ -381,7 +381,7 @@ static inline int ip6_forward_finish(str ++ return dst_output(net, sk, skb); ++ } ++ ++-static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) +++unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) ++ { ++ unsigned int mtu; ++ struct inet6_dev *idev; ++@@ -401,6 +401,7 @@ static unsigned int ip6_dst_mtu_forward( ++ ++ return mtu; ++ } +++EXPORT_SYMBOL_GPL(ip6_dst_mtu_forward); ++ ++ static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) ++ { ++--- a/net/ipv6/netfilter/Kconfig +++++ b/net/ipv6/netfilter/Kconfig ++@@ -99,6 +99,14 @@ config NFT_FIB_IPV6 ++ endif # NF_TABLES_IPV6 ++ endif # NF_TABLES ++ +++config NF_FLOW_TABLE_IPV6 +++ select NF_FLOW_TABLE +++ tristate "Netfilter flow table IPv6 module" +++ help +++ This option adds the flow table IPv6 support. +++ +++ To compile it as a module, choose M here. +++ ++ config NF_DUP_IPV6 ++ tristate "Netfilter IPv6 packet duplication to alternate destination" ++ depends on !NF_CONNTRACK || NF_CONNTRACK ++--- a/net/ipv6/netfilter/Makefile +++++ b/net/ipv6/netfilter/Makefile ++@@ -45,6 +45,9 @@ obj-$(CONFIG_NFT_REDIR_IPV6) += nft_redi ++ obj-$(CONFIG_NFT_DUP_IPV6) += nft_dup_ipv6.o ++ obj-$(CONFIG_NFT_FIB_IPV6) += nft_fib_ipv6.o ++ +++# flow table support +++obj-$(CONFIG_NF_FLOW_TABLE_IPV6) += nf_flow_table_ipv6.o +++ ++ # matches ++ obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o ++ obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o ++--- /dev/null +++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c ++@@ -0,0 +1,277 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++/* For layer 4 checksum field offset. */ +++#include +++#include +++ +++static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, +++ struct in6_addr *addr, +++ struct in6_addr *new_addr) +++{ +++ struct tcphdr *tcph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) +++ return -1; +++ +++ tcph = (void *)(skb_network_header(skb) + thoff); +++ inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, +++ new_addr->s6_addr32, true); +++ +++ return 0; +++} +++ +++static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, +++ struct in6_addr *addr, +++ struct in6_addr *new_addr) +++{ +++ struct udphdr *udph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*udph))) +++ return -1; +++ +++ udph = (void *)(skb_network_header(skb) + thoff); +++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +++ inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, +++ new_addr->s6_addr32, true); +++ if (!udph->check) +++ udph->check = CSUM_MANGLED_0; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, +++ unsigned int thoff, struct in6_addr *addr, +++ struct in6_addr *new_addr) +++{ +++ switch (ip6h->nexthdr) { +++ case IPPROTO_TCP: +++ if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0) +++ return NF_DROP; +++ break; +++ case IPPROTO_UDP: +++ if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0) +++ return NF_DROP; +++ break; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_snat_ipv6(const struct flow_offload *flow, +++ struct sk_buff *skb, struct ipv6hdr *ip6h, +++ unsigned int thoff, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct in6_addr addr, new_addr; +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ addr = ip6h->saddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6; +++ ip6h->saddr = new_addr; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ addr = ip6h->daddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; +++ ip6h->daddr = new_addr; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); +++} +++ +++static int nf_flow_dnat_ipv6(const struct flow_offload *flow, +++ struct sk_buff *skb, struct ipv6hdr *ip6h, +++ unsigned int thoff, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct in6_addr addr, new_addr; +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ addr = ip6h->daddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6; +++ ip6h->daddr = new_addr; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ addr = ip6h->saddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; +++ ip6h->saddr = new_addr; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); +++} +++ +++static int nf_flow_nat_ipv6(const struct flow_offload *flow, +++ struct sk_buff *skb, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct ipv6hdr *ip6h = ipv6_hdr(skb); +++ unsigned int thoff = sizeof(*ip6h); +++ +++ if (flow->flags & FLOW_OFFLOAD_SNAT && +++ (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +++ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) +++ return -1; +++ if (flow->flags & FLOW_OFFLOAD_DNAT && +++ (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +++ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) +++ return -1; +++ +++ return 0; +++} +++ +++static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, +++ struct flow_offload_tuple *tuple) +++{ +++ struct flow_ports *ports; +++ struct ipv6hdr *ip6h; +++ unsigned int thoff; +++ +++ if (!pskb_may_pull(skb, sizeof(*ip6h))) +++ return -1; +++ +++ ip6h = ipv6_hdr(skb); +++ +++ if (ip6h->nexthdr != IPPROTO_TCP && +++ ip6h->nexthdr != IPPROTO_UDP) +++ return -1; +++ +++ thoff = sizeof(*ip6h); +++ if (!pskb_may_pull(skb, thoff + sizeof(*ports))) +++ return -1; +++ +++ ports = (struct flow_ports *)(skb_network_header(skb) + thoff); +++ +++ tuple->src_v6 = ip6h->saddr; +++ tuple->dst_v6 = ip6h->daddr; +++ tuple->src_port = ports->source; +++ tuple->dst_port = ports->dest; +++ tuple->l3proto = AF_INET6; +++ tuple->l4proto = ip6h->nexthdr; +++ tuple->iifidx = dev->ifindex; +++ +++ return 0; +++} +++ +++/* Based on ip_exceeds_mtu(). */ +++static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +++{ +++ if (skb->len <= mtu) +++ return false; +++ +++ if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) +++ return false; +++ +++ return true; +++} +++ +++static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rt6_info *rt) +++{ +++ u32 mtu; +++ +++ mtu = ip6_dst_mtu_forward(&rt->dst); +++ if (__nf_flow_exceeds_mtu(skb, mtu)) +++ return true; +++ +++ return false; +++} +++ +++static unsigned int +++nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct nf_flowtable *flow_table = priv; +++ struct flow_offload_tuple tuple = {}; +++ enum flow_offload_tuple_dir dir; +++ struct flow_offload *flow; +++ struct net_device *outdev; +++ struct in6_addr *nexthop; +++ struct ipv6hdr *ip6h; +++ struct rt6_info *rt; +++ +++ if (skb->protocol != htons(ETH_P_IPV6)) +++ return NF_ACCEPT; +++ +++ if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) +++ return NF_ACCEPT; +++ +++ tuplehash = flow_offload_lookup(flow_table, &tuple); +++ if (tuplehash == NULL) +++ return NF_ACCEPT; +++ +++ outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); +++ if (!outdev) +++ return NF_ACCEPT; +++ +++ dir = tuplehash->tuple.dir; +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +++ +++ rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; +++ if (unlikely(nf_flow_exceeds_mtu(skb, rt))) +++ return NF_ACCEPT; +++ +++ if (skb_try_make_writable(skb, sizeof(*ip6h))) +++ return NF_DROP; +++ +++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && +++ nf_flow_nat_ipv6(flow, skb, dir) < 0) +++ return NF_DROP; +++ +++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; +++ ip6h = ipv6_hdr(skb); +++ ip6h->hop_limit--; +++ +++ skb->dev = outdev; +++ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); +++ neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); +++ +++ return NF_STOLEN; +++} +++ +++static struct nf_flowtable_type flowtable_ipv6 = { +++ .family = NFPROTO_IPV6, +++ .params = &nf_flow_offload_rhash_params, +++ .gc = nf_flow_offload_work_gc, +++ .hook = nf_flow_offload_ipv6_hook, +++ .owner = THIS_MODULE, +++}; +++ +++static int __init nf_flow_ipv6_module_init(void) +++{ +++ nft_register_flowtable_type(&flowtable_ipv6); +++ +++ return 0; +++} +++ +++static void __exit nf_flow_ipv6_module_exit(void) +++{ +++ nft_unregister_flowtable_type(&flowtable_ipv6); +++} +++ +++module_init(nf_flow_ipv6_module_init); +++module_exit(nf_flow_ipv6_module_exit); +++ +++MODULE_LICENSE("GPL"); +++MODULE_AUTHOR("Pablo Neira Ayuso "); +++MODULE_ALIAS_NF_FLOWTABLE(AF_INET6); +diff --git a/target/linux/generic/backport-4.14/325-v4.16-netfilter-flow-table-support-for-the-mixed-IPv4-IPv6.patch b/target/linux/generic/backport-4.14/325-v4.16-netfilter-flow-table-support-for-the-mixed-IPv4-IPv6.patch +new file mode 100644 +index 0000000000..04948d88ab +--- /dev/null ++++ b/target/linux/generic/backport-4.14/325-v4.16-netfilter-flow-table-support-for-the-mixed-IPv4-IPv6.patch +@@ -0,0 +1,141 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 7 Jan 2018 01:04:22 +0100 ++Subject: [PATCH] netfilter: flow table support for the mixed IPv4/IPv6 family ++ ++This patch adds the IPv6 flow table type, that implements the datapath ++flow table to forward IPv6 traffic. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ create mode 100644 net/netfilter/nf_flow_table_inet.c ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -111,6 +111,11 @@ struct flow_ports { ++ __be16 source, dest; ++ }; ++ +++unsigned int nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state); +++unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state); +++ ++ #define MODULE_ALIAS_NF_FLOWTABLE(family) \ ++ MODULE_ALIAS("nf-flowtable-" __stringify(family)) ++ ++--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c +++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c ++@@ -202,7 +202,7 @@ static bool nf_flow_exceeds_mtu(struct s ++ return false; ++ } ++ ++-static unsigned int +++unsigned int ++ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++ { ++@@ -254,6 +254,7 @@ nf_flow_offload_ip_hook(void *priv, stru ++ ++ return NF_STOLEN; ++ } +++EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); ++ ++ static struct nf_flowtable_type flowtable_ipv4 = { ++ .family = NFPROTO_IPV4, ++--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c +++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c ++@@ -196,7 +196,7 @@ static bool nf_flow_exceeds_mtu(struct s ++ return false; ++ } ++ ++-static unsigned int +++unsigned int ++ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++ { ++@@ -248,6 +248,7 @@ nf_flow_offload_ipv6_hook(void *priv, st ++ ++ return NF_STOLEN; ++ } +++EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook); ++ ++ static struct nf_flowtable_type flowtable_ipv6 = { ++ .family = NFPROTO_IPV6, ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -667,6 +667,14 @@ endif # NF_TABLES_NETDEV ++ ++ endif # NF_TABLES ++ +++config NF_FLOW_TABLE_INET +++ select NF_FLOW_TABLE +++ tristate "Netfilter flow table mixed IPv4/IPv6 module" +++ help +++ This option adds the flow table mixed IPv4/IPv6 support. +++ +++ To compile it as a module, choose M here. +++ ++ config NF_FLOW_TABLE ++ tristate "Netfilter flow table module" ++ help ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -112,6 +112,7 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_ ++ ++ # flow table infrastructure ++ obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o +++obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o ++ ++ # generic X tables ++ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o ++--- /dev/null +++++ b/net/netfilter/nf_flow_table_inet.c ++@@ -0,0 +1,48 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++static unsigned int +++nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ switch (skb->protocol) { +++ case htons(ETH_P_IP): +++ return nf_flow_offload_ip_hook(priv, skb, state); +++ case htons(ETH_P_IPV6): +++ return nf_flow_offload_ipv6_hook(priv, skb, state); +++ } +++ +++ return NF_ACCEPT; +++} +++ +++static struct nf_flowtable_type flowtable_inet = { +++ .family = NFPROTO_INET, +++ .params = &nf_flow_offload_rhash_params, +++ .gc = nf_flow_offload_work_gc, +++ .hook = nf_flow_offload_inet_hook, +++ .owner = THIS_MODULE, +++}; +++ +++static int __init nf_flow_inet_module_init(void) +++{ +++ nft_register_flowtable_type(&flowtable_inet); +++ +++ return 0; +++} +++ +++static void __exit nf_flow_inet_module_exit(void) +++{ +++ nft_unregister_flowtable_type(&flowtable_inet); +++} +++ +++module_init(nf_flow_inet_module_init); +++module_exit(nf_flow_inet_module_exit); +++ +++MODULE_LICENSE("GPL"); +++MODULE_AUTHOR("Pablo Neira Ayuso "); +++MODULE_ALIAS_NF_FLOWTABLE(1); /* NFPROTO_INET */ +diff --git a/target/linux/generic/backport-4.14/326-v4.16-netfilter-nf_tables-flow-offload-expression.patch b/target/linux/generic/backport-4.14/326-v4.16-netfilter-nf_tables-flow-offload-expression.patch +new file mode 100644 +index 0000000000..0decc34105 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/326-v4.16-netfilter-nf_tables-flow-offload-expression.patch +@@ -0,0 +1,332 @@ ++From: Pablo Neira Ayuso ++Date: Sun, 7 Jan 2018 01:04:26 +0100 ++Subject: [PATCH] netfilter: nf_tables: flow offload expression ++ ++Add new instruction for the nf_tables VM that allows us to specify what ++flows are offloaded into a given flow table via name. This new ++instruction creates the flow entry and adds it to the flow table. ++ ++Only established flows, ie. we have seen traffic in both directions, are ++added to the flow table. You can still decide to offload entries at a ++later stage via packet counting or checking the ct status in case you ++want to offload assured conntracks. ++ ++This new extension depends on the conntrack subsystem. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ create mode 100644 net/netfilter/nft_flow_offload.c ++ ++--- a/include/uapi/linux/netfilter/nf_tables.h +++++ b/include/uapi/linux/netfilter/nf_tables.h ++@@ -957,6 +957,17 @@ enum nft_ct_attributes { ++ }; ++ #define NFTA_CT_MAX (__NFTA_CT_MAX - 1) ++ +++/** +++ * enum nft_flow_attributes - ct offload expression attributes +++ * @NFTA_FLOW_TABLE_NAME: flow table name (NLA_STRING) +++ */ +++enum nft_offload_attributes { +++ NFTA_FLOW_UNSPEC, +++ NFTA_FLOW_TABLE_NAME, +++ __NFTA_FLOW_MAX, +++}; +++#define NFTA_FLOW_MAX (__NFTA_FLOW_MAX - 1) +++ ++ enum nft_limit_type { ++ NFT_LIMIT_PKTS, ++ NFT_LIMIT_PKT_BYTES ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -515,6 +515,13 @@ config NFT_CT ++ This option adds the "ct" expression that you can use to match ++ connection tracking information such as the flow state. ++ +++config NFT_FLOW_OFFLOAD +++ depends on NF_CONNTRACK +++ tristate "Netfilter nf_tables hardware flow offload module" +++ help +++ This option adds the "flow_offload" expression that you can use to +++ choose what flows are placed into the hardware. +++ ++ config NFT_SET_RBTREE ++ tristate "Netfilter nf_tables rbtree set module" ++ help ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -87,6 +87,7 @@ obj-$(CONFIG_NFT_META) += nft_meta.o ++ obj-$(CONFIG_NFT_RT) += nft_rt.o ++ obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o ++ obj-$(CONFIG_NFT_CT) += nft_ct.o +++obj-$(CONFIG_NFT_FLOW_OFFLOAD) += nft_flow_offload.o ++ obj-$(CONFIG_NFT_LIMIT) += nft_limit.o ++ obj-$(CONFIG_NFT_NAT) += nft_nat.o ++ obj-$(CONFIG_NFT_OBJREF) += nft_objref.o ++--- /dev/null +++++ b/net/netfilter/nft_flow_offload.c ++@@ -0,0 +1,264 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include /* for ipv4 options. */ +++#include +++#include +++#include +++#include +++#include +++ +++struct nft_flow_offload { +++ struct nft_flowtable *flowtable; +++}; +++ +++static int nft_flow_route(const struct nft_pktinfo *pkt, +++ const struct nf_conn *ct, +++ struct nf_flow_route *route, +++ enum ip_conntrack_dir dir) +++{ +++ struct dst_entry *this_dst = skb_dst(pkt->skb); +++ struct dst_entry *other_dst = NULL; +++ struct flowi fl; +++ +++ memset(&fl, 0, sizeof(fl)); +++ switch (nft_pf(pkt)) { +++ case NFPROTO_IPV4: +++ fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip; +++ break; +++ case NFPROTO_IPV6: +++ fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6; +++ break; +++ } +++ +++ nf_route(nft_net(pkt), &other_dst, &fl, false, nft_pf(pkt)); +++ if (!other_dst) +++ return -ENOENT; +++ +++ route->tuple[dir].dst = this_dst; +++ route->tuple[dir].ifindex = nft_in(pkt)->ifindex; +++ route->tuple[!dir].dst = other_dst; +++ route->tuple[!dir].ifindex = nft_out(pkt)->ifindex; +++ +++ return 0; +++} +++ +++static bool nft_flow_offload_skip(struct sk_buff *skb) +++{ +++ struct ip_options *opt = &(IPCB(skb)->opt); +++ +++ if (unlikely(opt->optlen)) +++ return true; +++ if (skb_sec_path(skb)) +++ return true; +++ +++ return false; +++} +++ +++static void nft_flow_offload_eval(const struct nft_expr *expr, +++ struct nft_regs *regs, +++ const struct nft_pktinfo *pkt) +++{ +++ struct nft_flow_offload *priv = nft_expr_priv(expr); +++ struct nf_flowtable *flowtable = &priv->flowtable->data; +++ enum ip_conntrack_info ctinfo; +++ struct nf_flow_route route; +++ struct flow_offload *flow; +++ enum ip_conntrack_dir dir; +++ struct nf_conn *ct; +++ int ret; +++ +++ if (nft_flow_offload_skip(pkt->skb)) +++ goto out; +++ +++ ct = nf_ct_get(pkt->skb, &ctinfo); +++ if (!ct) +++ goto out; +++ +++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { +++ case IPPROTO_TCP: +++ case IPPROTO_UDP: +++ break; +++ default: +++ goto out; +++ } +++ +++ if (test_bit(IPS_HELPER_BIT, &ct->status)) +++ goto out; +++ +++ if (ctinfo == IP_CT_NEW || +++ ctinfo == IP_CT_RELATED) +++ goto out; +++ +++ if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status)) +++ goto out; +++ +++ dir = CTINFO2DIR(ctinfo); +++ if (nft_flow_route(pkt, ct, &route, dir) < 0) +++ goto err_flow_route; +++ +++ flow = flow_offload_alloc(ct, &route); +++ if (!flow) +++ goto err_flow_alloc; +++ +++ ret = flow_offload_add(flowtable, flow); +++ if (ret < 0) +++ goto err_flow_add; +++ +++ return; +++ +++err_flow_add: +++ flow_offload_free(flow); +++err_flow_alloc: +++ dst_release(route.tuple[!dir].dst); +++err_flow_route: +++ clear_bit(IPS_OFFLOAD_BIT, &ct->status); +++out: +++ regs->verdict.code = NFT_BREAK; +++} +++ +++static int nft_flow_offload_validate(const struct nft_ctx *ctx, +++ const struct nft_expr *expr, +++ const struct nft_data **data) +++{ +++ unsigned int hook_mask = (1 << NF_INET_FORWARD); +++ +++ return nft_chain_validate_hooks(ctx->chain, hook_mask); +++} +++ +++static int nft_flow_offload_init(const struct nft_ctx *ctx, +++ const struct nft_expr *expr, +++ const struct nlattr * const tb[]) +++{ +++ struct nft_flow_offload *priv = nft_expr_priv(expr); +++ u8 genmask = nft_genmask_next(ctx->net); +++ struct nft_flowtable *flowtable; +++ +++ if (!tb[NFTA_FLOW_TABLE_NAME]) +++ return -EINVAL; +++ +++ flowtable = nf_tables_flowtable_lookup(ctx->table, +++ tb[NFTA_FLOW_TABLE_NAME], +++ genmask); +++ if (IS_ERR(flowtable)) +++ return PTR_ERR(flowtable); +++ +++ priv->flowtable = flowtable; +++ flowtable->use++; +++ +++ return nf_ct_netns_get(ctx->net, ctx->afi->family); +++} +++ +++static void nft_flow_offload_destroy(const struct nft_ctx *ctx, +++ const struct nft_expr *expr) +++{ +++ struct nft_flow_offload *priv = nft_expr_priv(expr); +++ +++ priv->flowtable->use--; +++ nf_ct_netns_put(ctx->net, ctx->afi->family); +++} +++ +++static int nft_flow_offload_dump(struct sk_buff *skb, const struct nft_expr *expr) +++{ +++ struct nft_flow_offload *priv = nft_expr_priv(expr); +++ +++ if (nla_put_string(skb, NFTA_FLOW_TABLE_NAME, priv->flowtable->name)) +++ goto nla_put_failure; +++ +++ return 0; +++ +++nla_put_failure: +++ return -1; +++} +++ +++static struct nft_expr_type nft_flow_offload_type; +++static const struct nft_expr_ops nft_flow_offload_ops = { +++ .type = &nft_flow_offload_type, +++ .size = NFT_EXPR_SIZE(sizeof(struct nft_flow_offload)), +++ .eval = nft_flow_offload_eval, +++ .init = nft_flow_offload_init, +++ .destroy = nft_flow_offload_destroy, +++ .validate = nft_flow_offload_validate, +++ .dump = nft_flow_offload_dump, +++}; +++ +++static struct nft_expr_type nft_flow_offload_type __read_mostly = { +++ .name = "flow_offload", +++ .ops = &nft_flow_offload_ops, +++ .maxattr = NFTA_FLOW_MAX, +++ .owner = THIS_MODULE, +++}; +++ +++static void flow_offload_iterate_cleanup(struct flow_offload *flow, void *data) +++{ +++ struct net_device *dev = data; +++ +++ if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) +++ return; +++ +++ flow_offload_dead(flow); +++} +++ +++static void nft_flow_offload_iterate_cleanup(struct nf_flowtable *flowtable, +++ void *data) +++{ +++ nf_flow_table_iterate(flowtable, flow_offload_iterate_cleanup, data); +++} +++ +++static int flow_offload_netdev_event(struct notifier_block *this, +++ unsigned long event, void *ptr) +++{ +++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); +++ +++ if (event != NETDEV_DOWN) +++ return NOTIFY_DONE; +++ +++ nft_flow_table_iterate(dev_net(dev), nft_flow_offload_iterate_cleanup, dev); +++ +++ return NOTIFY_DONE; +++} +++ +++static struct notifier_block flow_offload_netdev_notifier = { +++ .notifier_call = flow_offload_netdev_event, +++}; +++ +++static int __init nft_flow_offload_module_init(void) +++{ +++ int err; +++ +++ register_netdevice_notifier(&flow_offload_netdev_notifier); +++ +++ err = nft_register_expr(&nft_flow_offload_type); +++ if (err < 0) +++ goto register_expr; +++ +++ return 0; +++ +++register_expr: +++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); +++ return err; +++} +++ +++static void __exit nft_flow_offload_module_exit(void) +++{ +++ struct net *net; +++ +++ nft_unregister_expr(&nft_flow_offload_type); +++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); +++ rtnl_lock(); +++ for_each_net(net) +++ nft_flow_table_iterate(net, nft_flow_offload_iterate_cleanup, NULL); +++ rtnl_unlock(); +++} +++ +++module_init(nft_flow_offload_module_init); +++module_exit(nft_flow_offload_module_exit); +++ +++MODULE_LICENSE("GPL"); +++MODULE_AUTHOR("Pablo Neira Ayuso "); +++MODULE_ALIAS_NFT_EXPR("flow_offload"); +diff --git a/target/linux/generic/backport-4.14/327-v4.16-netfilter-nf_tables-remove-nhooks-field-from-struct-.patch b/target/linux/generic/backport-4.14/327-v4.16-netfilter-nf_tables-remove-nhooks-field-from-struct-.patch +new file mode 100644 +index 0000000000..188ee11b84 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/327-v4.16-netfilter-nf_tables-remove-nhooks-field-from-struct-.patch +@@ -0,0 +1,113 @@ ++From: Pablo Neira Ayuso ++Date: Tue, 19 Dec 2017 13:53:45 +0100 ++Subject: [PATCH] netfilter: nf_tables: remove nhooks field from struct ++ nft_af_info ++ ++We already validate the hook through bitmask, so this check is ++superfluous. When removing this, this patch is also fixing a bug in the ++new flowtable codebase, since ctx->afi points to the table family ++instead of the netdev family which is where the flowtable is really ++hooked in. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -969,7 +969,6 @@ enum nft_af_flags { ++ * ++ * @list: used internally ++ * @family: address family ++- * @nhooks: number of hooks in this family ++ * @owner: module owner ++ * @tables: used internally ++ * @flags: family flags ++@@ -977,7 +976,6 @@ enum nft_af_flags { ++ struct nft_af_info { ++ struct list_head list; ++ int family; ++- unsigned int nhooks; ++ struct module *owner; ++ struct list_head tables; ++ u32 flags; ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -44,7 +44,6 @@ nft_do_chain_bridge(void *priv, ++ ++ static struct nft_af_info nft_af_bridge __read_mostly = { ++ .family = NFPROTO_BRIDGE, ++- .nhooks = NF_BR_NUMHOOKS, ++ .owner = THIS_MODULE, ++ }; ++ ++--- a/net/ipv4/netfilter/nf_tables_arp.c +++++ b/net/ipv4/netfilter/nf_tables_arp.c ++@@ -29,7 +29,6 @@ nft_do_chain_arp(void *priv, ++ ++ static struct nft_af_info nft_af_arp __read_mostly = { ++ .family = NFPROTO_ARP, ++- .nhooks = NF_ARP_NUMHOOKS, ++ .owner = THIS_MODULE, ++ }; ++ ++--- a/net/ipv4/netfilter/nf_tables_ipv4.c +++++ b/net/ipv4/netfilter/nf_tables_ipv4.c ++@@ -32,7 +32,6 @@ static unsigned int nft_do_chain_ipv4(vo ++ ++ static struct nft_af_info nft_af_ipv4 __read_mostly = { ++ .family = NFPROTO_IPV4, ++- .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++ }; ++ ++--- a/net/ipv6/netfilter/nf_tables_ipv6.c +++++ b/net/ipv6/netfilter/nf_tables_ipv6.c ++@@ -30,7 +30,6 @@ static unsigned int nft_do_chain_ipv6(vo ++ ++ static struct nft_af_info nft_af_ipv6 __read_mostly = { ++ .family = NFPROTO_IPV6, ++- .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++ }; ++ ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -1374,9 +1374,6 @@ static int nft_chain_parse_hook(struct n ++ return -EINVAL; ++ ++ hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); ++- if (hook->num >= afi->nhooks) ++- return -EINVAL; ++- ++ hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); ++ ++ type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT]; ++@@ -5014,7 +5011,7 @@ static int nf_tables_flowtable_parse_hoo ++ return -EINVAL; ++ ++ hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM])); ++- if (hooknum >= ctx->afi->nhooks) +++ if (hooknum != NF_NETDEV_INGRESS) ++ return -EINVAL; ++ ++ priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY])); ++--- a/net/netfilter/nf_tables_inet.c +++++ b/net/netfilter/nf_tables_inet.c ++@@ -40,7 +40,6 @@ static unsigned int nft_do_chain_inet(vo ++ ++ static struct nft_af_info nft_af_inet __read_mostly = { ++ .family = NFPROTO_INET, ++- .nhooks = NF_INET_NUMHOOKS, ++ .owner = THIS_MODULE, ++ }; ++ ++--- a/net/netfilter/nf_tables_netdev.c +++++ b/net/netfilter/nf_tables_netdev.c ++@@ -40,7 +40,6 @@ nft_do_chain_netdev(void *priv, struct s ++ ++ static struct nft_af_info nft_af_netdev __read_mostly = { ++ .family = NFPROTO_NETDEV, ++- .nhooks = NF_NETDEV_NUMHOOKS, ++ .owner = THIS_MODULE, ++ .flags = NFT_AF_NEEDS_DEV, ++ }; +diff --git a/target/linux/generic/backport-4.14/328-v4.16-netfilter-nf_tables-fix-a-typo-in-nf_tables_getflowt.patch b/target/linux/generic/backport-4.14/328-v4.16-netfilter-nf_tables-fix-a-typo-in-nf_tables_getflowt.patch +new file mode 100644 +index 0000000000..1f0a5a2bb3 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/328-v4.16-netfilter-nf_tables-fix-a-typo-in-nf_tables_getflowt.patch +@@ -0,0 +1,22 @@ ++From: Wei Yongjun ++Date: Wed, 10 Jan 2018 07:04:54 +0000 ++Subject: [PATCH] netfilter: nf_tables: fix a typo in nf_tables_getflowtable() ++ ++Fix a typo, we should check 'flowtable' instead of 'table'. ++ ++Fixes: 3b49e2e94e6e ("netfilter: nf_tables: add flow table netlink frontend") ++Signed-off-by: Wei Yongjun ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -5438,7 +5438,7 @@ static int nf_tables_getflowtable(struct ++ ++ flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], ++ genmask); ++- if (IS_ERR(table)) +++ if (IS_ERR(flowtable)) ++ return PTR_ERR(flowtable); ++ ++ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); +diff --git a/target/linux/generic/backport-4.14/329-v4.16-netfilter-improve-flow-table-Kconfig-dependencies.patch b/target/linux/generic/backport-4.14/329-v4.16-netfilter-improve-flow-table-Kconfig-dependencies.patch +new file mode 100644 +index 0000000000..0d5cd3bb4f +--- /dev/null ++++ b/target/linux/generic/backport-4.14/329-v4.16-netfilter-improve-flow-table-Kconfig-dependencies.patch +@@ -0,0 +1,106 @@ ++From: Arnd Bergmann ++Date: Wed, 10 Jan 2018 18:10:59 +0100 ++Subject: [PATCH] netfilter: improve flow table Kconfig dependencies ++ ++The newly added NF_FLOW_TABLE options cause some build failures in ++randconfig kernels: ++ ++- when CONFIG_NF_CONNTRACK is disabled, or is a loadable module but ++ NF_FLOW_TABLE is built-in: ++ ++ In file included from net/netfilter/nf_flow_table.c:8:0: ++ include/net/netfilter/nf_conntrack.h:59:22: error: field 'ct_general' has incomplete type ++ struct nf_conntrack ct_general; ++ include/net/netfilter/nf_conntrack.h: In function 'nf_ct_get': ++ include/net/netfilter/nf_conntrack.h:148:15: error: 'const struct sk_buff' has no member named '_nfct' ++ include/net/netfilter/nf_conntrack.h: In function 'nf_ct_put': ++ include/net/netfilter/nf_conntrack.h:157:2: error: implicit declaration of function 'nf_conntrack_put'; did you mean 'nf_ct_put'? [-Werror=implicit-function-declaration] ++ ++ net/netfilter/nf_flow_table.o: In function `nf_flow_offload_work_gc': ++ (.text+0x1540): undefined reference to `nf_ct_delete' ++ ++- when CONFIG_NF_TABLES is disabled: ++ ++ In file included from net/ipv6/netfilter/nf_flow_table_ipv6.c:13:0: ++ include/net/netfilter/nf_tables.h: In function 'nft_gencursor_next': ++ include/net/netfilter/nf_tables.h:1189:14: error: 'const struct net' has no member named 'nft'; did you mean 'nf'? ++ ++ - when CONFIG_NF_FLOW_TABLE_INET is enabled, but NF_FLOW_TABLE_IPV4 ++ or NF_FLOW_TABLE_IPV6 are not, or are loadable modules ++ ++ net/netfilter/nf_flow_table_inet.o: In function `nf_flow_offload_inet_hook': ++ nf_flow_table_inet.c:(.text+0x94): undefined reference to `nf_flow_offload_ipv6_hook' ++ nf_flow_table_inet.c:(.text+0x40): undefined reference to `nf_flow_offload_ip_hook' ++ ++- when CONFIG_NF_FLOW_TABLES is disabled, but the other options are ++ enabled: ++ ++ net/netfilter/nf_flow_table_inet.o: In function `nf_flow_offload_inet_hook': ++ nf_flow_table_inet.c:(.text+0x6c): undefined reference to `nf_flow_offload_ipv6_hook' ++ net/netfilter/nf_flow_table_inet.o: In function `nf_flow_inet_module_exit': ++ nf_flow_table_inet.c:(.exit.text+0x8): undefined reference to `nft_unregister_flowtable_type' ++ net/netfilter/nf_flow_table_inet.o: In function `nf_flow_inet_module_init': ++ nf_flow_table_inet.c:(.init.text+0x8): undefined reference to `nft_register_flowtable_type' ++ net/ipv4/netfilter/nf_flow_table_ipv4.o: In function `nf_flow_ipv4_module_exit': ++ nf_flow_table_ipv4.c:(.exit.text+0x8): undefined reference to `nft_unregister_flowtable_type' ++ net/ipv4/netfilter/nf_flow_table_ipv4.o: In function `nf_flow_ipv4_module_init': ++ nf_flow_table_ipv4.c:(.init.text+0x8): undefined reference to `nft_register_flowtable_type' ++ ++This adds additional Kconfig dependencies to ensure that NF_CONNTRACK and NF_TABLES ++are always visible from NF_FLOW_TABLE, and that the internal dependencies between ++the four new modules are met. ++ ++Fixes: 7c23b629a808 ("netfilter: flow table support for the mixed IPv4/IPv6 family") ++Fixes: 0995210753a2 ("netfilter: flow table support for IPv6") ++Fixes: 97add9f0d66d ("netfilter: flow table support for IPv4") ++Signed-off-by: Arnd Bergmann ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/ipv4/netfilter/Kconfig +++++ b/net/ipv4/netfilter/Kconfig ++@@ -79,8 +79,9 @@ config NF_TABLES_ARP ++ endif # NF_TABLES ++ ++ config NF_FLOW_TABLE_IPV4 ++- select NF_FLOW_TABLE ++ tristate "Netfilter flow table IPv4 module" +++ depends on NF_CONNTRACK && NF_TABLES +++ select NF_FLOW_TABLE ++ help ++ This option adds the flow table IPv4 support. ++ ++--- a/net/ipv6/netfilter/Kconfig +++++ b/net/ipv6/netfilter/Kconfig ++@@ -100,8 +100,9 @@ endif # NF_TABLES_IPV6 ++ endif # NF_TABLES ++ ++ config NF_FLOW_TABLE_IPV6 ++- select NF_FLOW_TABLE ++ tristate "Netfilter flow table IPv6 module" +++ depends on NF_CONNTRACK && NF_TABLES +++ select NF_FLOW_TABLE ++ help ++ This option adds the flow table IPv6 support. ++ ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -675,8 +675,9 @@ endif # NF_TABLES_NETDEV ++ endif # NF_TABLES ++ ++ config NF_FLOW_TABLE_INET ++- select NF_FLOW_TABLE ++ tristate "Netfilter flow table mixed IPv4/IPv6 module" +++ depends on NF_FLOW_TABLE_IPV4 && NF_FLOW_TABLE_IPV6 +++ select NF_FLOW_TABLE ++ help ++ This option adds the flow table mixed IPv4/IPv6 support. ++ ++@@ -684,6 +685,7 @@ config NF_FLOW_TABLE_INET ++ ++ config NF_FLOW_TABLE ++ tristate "Netfilter flow table module" +++ depends on NF_CONNTRACK && NF_TABLES ++ help ++ This option adds the flow table core infrastructure. ++ +diff --git a/target/linux/generic/backport-4.14/330-v4.16-netfilter-nf_tables-remove-flag-field-from-struct-nf.patch b/target/linux/generic/backport-4.14/330-v4.16-netfilter-nf_tables-remove-flag-field-from-struct-nf.patch +new file mode 100644 +index 0000000000..8f82effa79 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/330-v4.16-netfilter-nf_tables-remove-flag-field-from-struct-nf.patch +@@ -0,0 +1,59 @@ ++From: Pablo Neira Ayuso ++Date: Tue, 19 Dec 2017 14:07:52 +0100 ++Subject: [PATCH] netfilter: nf_tables: remove flag field from struct ++ nft_af_info ++ ++Replace it by a direct check for the netdev protocol family. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -960,10 +960,6 @@ struct nft_table { ++ char *name; ++ }; ++ ++-enum nft_af_flags { ++- NFT_AF_NEEDS_DEV = (1 << 0), ++-}; ++- ++ /** ++ * struct nft_af_info - nf_tables address family info ++ * ++@@ -971,14 +967,12 @@ enum nft_af_flags { ++ * @family: address family ++ * @owner: module owner ++ * @tables: used internally ++- * @flags: family flags ++ */ ++ struct nft_af_info { ++ struct list_head list; ++ int family; ++ struct module *owner; ++ struct list_head tables; ++- u32 flags; ++ }; ++ ++ int nft_register_afinfo(struct net *, struct nft_af_info *); ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -1391,7 +1391,7 @@ static int nft_chain_parse_hook(struct n ++ hook->type = type; ++ ++ hook->dev = NULL; ++- if (afi->flags & NFT_AF_NEEDS_DEV) { +++ if (afi->family == NFPROTO_NETDEV) { ++ char ifname[IFNAMSIZ]; ++ ++ if (!ha[NFTA_HOOK_DEV]) { ++--- a/net/netfilter/nf_tables_netdev.c +++++ b/net/netfilter/nf_tables_netdev.c ++@@ -41,7 +41,6 @@ nft_do_chain_netdev(void *priv, struct s ++ static struct nft_af_info nft_af_netdev __read_mostly = { ++ .family = NFPROTO_NETDEV, ++ .owner = THIS_MODULE, ++- .flags = NFT_AF_NEEDS_DEV, ++ }; ++ ++ static int nf_tables_netdev_init_net(struct net *net) +diff --git a/target/linux/generic/backport-4.14/331-v4.16-netfilter-nf_tables-no-need-for-struct-nft_af_info-t.patch b/target/linux/generic/backport-4.14/331-v4.16-netfilter-nf_tables-no-need-for-struct-nft_af_info-t.patch +new file mode 100644 +index 0000000000..f7e7eeaa05 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/331-v4.16-netfilter-nf_tables-no-need-for-struct-nft_af_info-t.patch +@@ -0,0 +1,80 @@ ++From: Pablo Neira Ayuso ++Date: Tue, 19 Dec 2017 12:17:52 +0100 ++Subject: [PATCH] netfilter: nf_tables: no need for struct nft_af_info to ++ enable/disable table ++ ++nf_tables_table_enable() and nf_tables_table_disable() take a pointer to ++struct nft_af_info that is never used, remove it. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -655,10 +655,7 @@ err: ++ return err; ++ } ++ ++-static void _nf_tables_table_disable(struct net *net, ++- const struct nft_af_info *afi, ++- struct nft_table *table, ++- u32 cnt) +++static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt) ++ { ++ struct nft_chain *chain; ++ u32 i = 0; ++@@ -676,9 +673,7 @@ static void _nf_tables_table_disable(str ++ } ++ } ++ ++-static int nf_tables_table_enable(struct net *net, ++- const struct nft_af_info *afi, ++- struct nft_table *table) +++static int nf_tables_table_enable(struct net *net, struct nft_table *table) ++ { ++ struct nft_chain *chain; ++ int err, i = 0; ++@@ -698,15 +693,13 @@ static int nf_tables_table_enable(struct ++ return 0; ++ err: ++ if (i) ++- _nf_tables_table_disable(net, afi, table, i); +++ nft_table_disable(net, table, i); ++ return err; ++ } ++ ++-static void nf_tables_table_disable(struct net *net, ++- const struct nft_af_info *afi, ++- struct nft_table *table) +++static void nf_tables_table_disable(struct net *net, struct nft_table *table) ++ { ++- _nf_tables_table_disable(net, afi, table, 0); +++ nft_table_disable(net, table, 0); ++ } ++ ++ static int nf_tables_updtable(struct nft_ctx *ctx) ++@@ -735,7 +728,7 @@ static int nf_tables_updtable(struct nft ++ nft_trans_table_enable(trans) = false; ++ } else if (!(flags & NFT_TABLE_F_DORMANT) && ++ ctx->table->flags & NFT_TABLE_F_DORMANT) { ++- ret = nf_tables_table_enable(ctx->net, ctx->afi, ctx->table); +++ ret = nf_tables_table_enable(ctx->net, ctx->table); ++ if (ret >= 0) { ++ ctx->table->flags &= ~NFT_TABLE_F_DORMANT; ++ nft_trans_table_enable(trans) = true; ++@@ -5819,7 +5812,6 @@ static int nf_tables_commit(struct net * ++ if (nft_trans_table_update(trans)) { ++ if (!nft_trans_table_enable(trans)) { ++ nf_tables_table_disable(net, ++- trans->ctx.afi, ++ trans->ctx.table); ++ trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; ++ } ++@@ -5983,7 +5975,6 @@ static int nf_tables_abort(struct net *n ++ if (nft_trans_table_update(trans)) { ++ if (nft_trans_table_enable(trans)) { ++ nf_tables_table_disable(net, ++- trans->ctx.afi, ++ trans->ctx.table); ++ trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; ++ } +diff --git a/target/linux/generic/backport-4.14/332-v4.16-netfilter-nf_tables-remove-struct-nft_af_info-parame.patch b/target/linux/generic/backport-4.14/332-v4.16-netfilter-nf_tables-remove-struct-nft_af_info-parame.patch +new file mode 100644 +index 0000000000..0ce65dc141 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/332-v4.16-netfilter-nf_tables-remove-struct-nft_af_info-parame.patch +@@ -0,0 +1,60 @@ ++From: Pablo Neira Ayuso ++Date: Tue, 19 Dec 2017 13:40:22 +0100 ++Subject: [PATCH] netfilter: nf_tables: remove struct nft_af_info parameter in ++ nf_tables_chain_type_lookup() ++ ++Pass family number instead, this comes in preparation for the removal of ++struct nft_af_info. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -467,7 +467,7 @@ static inline u64 nf_tables_alloc_handle ++ static const struct nf_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX]; ++ ++ static const struct nf_chain_type * ++-__nf_tables_chain_type_lookup(int family, const struct nlattr *nla) +++__nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family) ++ { ++ int i; ++ ++@@ -480,22 +480,20 @@ __nf_tables_chain_type_lookup(int family ++ } ++ ++ static const struct nf_chain_type * ++-nf_tables_chain_type_lookup(const struct nft_af_info *afi, ++- const struct nlattr *nla, ++- bool autoload) +++nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload) ++ { ++ const struct nf_chain_type *type; ++ ++- type = __nf_tables_chain_type_lookup(afi->family, nla); +++ type = __nf_tables_chain_type_lookup(nla, family); ++ if (type != NULL) ++ return type; ++ #ifdef CONFIG_MODULES ++ if (autoload) { ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++- request_module("nft-chain-%u-%.*s", afi->family, +++ request_module("nft-chain-%u-%.*s", family, ++ nla_len(nla), (const char *)nla_data(nla)); ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- type = __nf_tables_chain_type_lookup(afi->family, nla); +++ type = __nf_tables_chain_type_lookup(nla, family); ++ if (type != NULL) ++ return ERR_PTR(-EAGAIN); ++ } ++@@ -1371,8 +1369,8 @@ static int nft_chain_parse_hook(struct n ++ ++ type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT]; ++ if (nla[NFTA_CHAIN_TYPE]) { ++- type = nf_tables_chain_type_lookup(afi, nla[NFTA_CHAIN_TYPE], ++- create); +++ type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE], +++ afi->family, create); ++ if (IS_ERR(type)) ++ return PTR_ERR(type); ++ } +diff --git a/target/linux/generic/backport-4.14/334-v4.15-netfilter-nf_tables-fix-potential-NULL-ptr-deref-in-.patch b/target/linux/generic/backport-4.14/334-v4.15-netfilter-nf_tables-fix-potential-NULL-ptr-deref-in-.patch +new file mode 100644 +index 0000000000..f6e1ef0823 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/334-v4.15-netfilter-nf_tables-fix-potential-NULL-ptr-deref-in-.patch +@@ -0,0 +1,30 @@ ++From: Hangbin Liu ++Date: Mon, 25 Dec 2017 11:34:54 +0800 ++Subject: [PATCH] netfilter: nf_tables: fix potential NULL-ptr deref in ++ nf_tables_dump_obj_done() ++ ++If there is no NFTA_OBJ_TABLE and NFTA_OBJ_TYPE, the c.data will be NULL in ++nf_tables_getobj(). So before free filter->table in nf_tables_dump_obj_done(), ++we need to check if filter is NULL first. ++ ++Fixes: e46abbcc05aa ("netfilter: nf_tables: Allow table names of up to 255 chars") ++Signed-off-by: Hangbin Liu ++Acked-by: Phil Sutter ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -5357,8 +5357,10 @@ static int nf_tables_dump_flowtable_done ++ if (!filter) ++ return 0; ++ ++- kfree(filter->table); ++- kfree(filter); +++ if (filter) { +++ kfree(filter->table); +++ kfree(filter); +++ } ++ ++ return 0; ++ } +diff --git a/target/linux/generic/backport-4.14/335-v4.16-netfilter-nf_tables-add-single-table-list-for-all-fa.patch b/target/linux/generic/backport-4.14/335-v4.16-netfilter-nf_tables-add-single-table-list-for-all-fa.patch +new file mode 100644 +index 0000000000..340d7167ea +--- /dev/null ++++ b/target/linux/generic/backport-4.14/335-v4.16-netfilter-nf_tables-add-single-table-list-for-all-fa.patch +@@ -0,0 +1,1450 @@ ++From: Pablo Neira Ayuso ++Date: Tue, 9 Jan 2018 02:38:03 +0100 ++Subject: [PATCH] netfilter: nf_tables: add single table list for all families ++ ++Place all existing user defined tables in struct net *, instead of ++having one list per family. This saves us from one level of indentation ++in netlink dump functions. ++ ++Place pointer to struct nft_af_info in struct nft_table temporarily, as ++we still need this to put back reference module reference counter on ++table removal. ++ ++This patch comes in preparation for the removal of struct nft_af_info. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -143,22 +143,22 @@ static inline void nft_data_debug(const ++ * struct nft_ctx - nf_tables rule/set context ++ * ++ * @net: net namespace ++- * @afi: address family info ++ * @table: the table the chain is contained in ++ * @chain: the chain the rule is contained in ++ * @nla: netlink attributes ++ * @portid: netlink portID of the original message ++ * @seq: netlink sequence number +++ * @family: protocol family ++ * @report: notify via unicast netlink message ++ */ ++ struct nft_ctx { ++ struct net *net; ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_chain *chain; ++ const struct nlattr * const *nla; ++ u32 portid; ++ u32 seq; +++ u8 family; ++ bool report; ++ }; ++ ++@@ -945,6 +945,7 @@ unsigned int nft_do_chain(struct nft_pkt ++ * @use: number of chain references to this table ++ * @flags: table flag (see enum nft_table_flags) ++ * @genmask: generation mask +++ * @afinfo: address family info ++ * @name: name of the table ++ */ ++ struct nft_table { ++@@ -957,6 +958,7 @@ struct nft_table { ++ u32 use; ++ u16 flags:14, ++ genmask:2; +++ struct nft_af_info *afi; ++ char *name; ++ }; ++ ++@@ -966,13 +968,11 @@ struct nft_table { ++ * @list: used internally ++ * @family: address family ++ * @owner: module owner ++- * @tables: used internally ++ */ ++ struct nft_af_info { ++ struct list_head list; ++ int family; ++ struct module *owner; ++- struct list_head tables; ++ }; ++ ++ int nft_register_afinfo(struct net *, struct nft_af_info *); ++--- a/include/net/netns/nftables.h +++++ b/include/net/netns/nftables.h ++@@ -8,6 +8,7 @@ struct nft_af_info; ++ ++ struct netns_nftables { ++ struct list_head af_info; +++ struct list_head tables; ++ struct list_head commit_list; ++ struct nft_af_info *ipv4; ++ struct nft_af_info *ipv6; ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -37,7 +37,6 @@ static LIST_HEAD(nf_tables_flowtables); ++ */ ++ int nft_register_afinfo(struct net *net, struct nft_af_info *afi) ++ { ++- INIT_LIST_HEAD(&afi->tables); ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++ list_add_tail_rcu(&afi->list, &net->nft.af_info); ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++@@ -99,13 +98,13 @@ static void nft_ctx_init(struct nft_ctx ++ struct net *net, ++ const struct sk_buff *skb, ++ const struct nlmsghdr *nlh, ++- struct nft_af_info *afi, +++ u8 family, ++ struct nft_table *table, ++ struct nft_chain *chain, ++ const struct nlattr * const *nla) ++ { ++ ctx->net = net; ++- ctx->afi = afi; +++ ctx->family = family; ++ ctx->table = table; ++ ctx->chain = chain; ++ ctx->nla = nla; ++@@ -429,30 +428,31 @@ static int nft_delflowtable(struct nft_c ++ * Tables ++ */ ++ ++-static struct nft_table *nft_table_lookup(const struct nft_af_info *afi, +++static struct nft_table *nft_table_lookup(const struct net *net, ++ const struct nlattr *nla, ++- u8 genmask) +++ u8 family, u8 genmask) ++ { ++ struct nft_table *table; ++ ++- list_for_each_entry(table, &afi->tables, list) { +++ list_for_each_entry(table, &net->nft.tables, list) { ++ if (!nla_strcmp(nla, table->name) && +++ table->afi->family == family && ++ nft_active_genmask(table, genmask)) ++ return table; ++ } ++ return NULL; ++ } ++ ++-static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi, +++static struct nft_table *nf_tables_table_lookup(const struct net *net, ++ const struct nlattr *nla, ++- u8 genmask) +++ u8 family, u8 genmask) ++ { ++ struct nft_table *table; ++ ++ if (nla == NULL) ++ return ERR_PTR(-EINVAL); ++ ++- table = nft_table_lookup(afi, nla, genmask); +++ table = nft_table_lookup(net, nla, family, genmask); ++ if (table != NULL) ++ return table; ++ ++@@ -551,7 +551,7 @@ static void nf_tables_table_notify(const ++ goto err; ++ ++ err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq, ++- event, 0, ctx->afi->family, ctx->table); +++ event, 0, ctx->family, ctx->table); ++ if (err < 0) { ++ kfree_skb(skb); ++ goto err; ++@@ -568,7 +568,6 @@ static int nf_tables_dump_tables(struct ++ struct netlink_callback *cb) ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ unsigned int idx = 0, s_idx = cb->args[0]; ++ struct net *net = sock_net(skb->sk); ++@@ -577,30 +576,27 @@ static int nf_tables_dump_tables(struct ++ rcu_read_lock(); ++ cb->seq = net->nft.base_seq; ++ ++- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- if (family != NFPROTO_UNSPEC && family != afi->family) +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { +++ if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ continue; ++ ++- list_for_each_entry_rcu(table, &afi->tables, list) { ++- if (idx < s_idx) ++- goto cont; ++- if (idx > s_idx) ++- memset(&cb->args[1], 0, ++- sizeof(cb->args) - sizeof(cb->args[0])); ++- if (!nft_is_active(net, table)) ++- continue; ++- if (nf_tables_fill_table_info(skb, net, ++- NETLINK_CB(cb->skb).portid, ++- cb->nlh->nlmsg_seq, ++- NFT_MSG_NEWTABLE, ++- NLM_F_MULTI, ++- afi->family, table) < 0) ++- goto done; +++ if (idx < s_idx) +++ goto cont; +++ if (idx > s_idx) +++ memset(&cb->args[1], 0, +++ sizeof(cb->args) - sizeof(cb->args[0])); +++ if (!nft_is_active(net, table)) +++ continue; +++ if (nf_tables_fill_table_info(skb, net, +++ NETLINK_CB(cb->skb).portid, +++ cb->nlh->nlmsg_seq, +++ NFT_MSG_NEWTABLE, NLM_F_MULTI, +++ table->afi->family, table) < 0) +++ goto done; ++ ++- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ cont: ++- idx++; ++- } +++ idx++; ++ } ++ done: ++ rcu_read_unlock(); ++@@ -632,7 +628,8 @@ static int nf_tables_gettable(struct net ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -763,7 +760,7 @@ static int nf_tables_newtable(struct net ++ return PTR_ERR(afi); ++ ++ name = nla[NFTA_TABLE_NAME]; ++- table = nf_tables_table_lookup(afi, name, genmask); +++ table = nf_tables_table_lookup(net, name, afi->family, genmask); ++ if (IS_ERR(table)) { ++ if (PTR_ERR(table) != -ENOENT) ++ return PTR_ERR(table); ++@@ -773,7 +770,7 @@ static int nf_tables_newtable(struct net ++ if (nlh->nlmsg_flags & NLM_F_REPLACE) ++ return -EOPNOTSUPP; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ return nf_tables_updtable(&ctx); ++ } ++ ++@@ -800,14 +797,15 @@ static int nf_tables_newtable(struct net ++ INIT_LIST_HEAD(&table->sets); ++ INIT_LIST_HEAD(&table->objects); ++ INIT_LIST_HEAD(&table->flowtables); +++ table->afi = afi; ++ table->flags = flags; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); ++ if (err < 0) ++ goto err4; ++ ++- list_add_tail_rcu(&table->list, &afi->tables); +++ list_add_tail_rcu(&table->list, &net->nft.tables); ++ return 0; ++ err4: ++ kfree(table->name); ++@@ -881,30 +879,28 @@ out: ++ ++ static int nft_flush(struct nft_ctx *ctx, int family) ++ { ++- struct nft_af_info *afi; ++ struct nft_table *table, *nt; ++ const struct nlattr * const *nla = ctx->nla; ++ int err = 0; ++ ++- list_for_each_entry(afi, &ctx->net->nft.af_info, list) { ++- if (family != AF_UNSPEC && afi->family != family) +++ list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) { +++ if (family != AF_UNSPEC && table->afi->family != family) ++ continue; ++ ++- ctx->afi = afi; ++- list_for_each_entry_safe(table, nt, &afi->tables, list) { ++- if (!nft_is_active_next(ctx->net, table)) ++- continue; +++ ctx->family = table->afi->family; ++ ++- if (nla[NFTA_TABLE_NAME] && ++- nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) ++- continue; +++ if (!nft_is_active_next(ctx->net, table)) +++ continue; ++ ++- ctx->table = table; +++ if (nla[NFTA_TABLE_NAME] && +++ nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) +++ continue; ++ ++- err = nft_flush_table(ctx); ++- if (err < 0) ++- goto out; ++- } +++ ctx->table = table; +++ +++ err = nft_flush_table(ctx); +++ if (err < 0) +++ goto out; ++ } ++ out: ++ return err; ++@@ -922,7 +918,7 @@ static int nf_tables_deltable(struct net ++ int family = nfmsg->nfgen_family; ++ struct nft_ctx ctx; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, NULL, NULL, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); ++ if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) ++ return nft_flush(&ctx, family); ++ ++@@ -930,7 +926,8 @@ static int nf_tables_deltable(struct net ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -938,7 +935,7 @@ static int nf_tables_deltable(struct net ++ table->use > 0) ++ return -EBUSY; ++ ++- ctx.afi = afi; +++ ctx.family = afi->family; ++ ctx.table = table; ++ ++ return nft_flush_table(&ctx); ++@@ -950,7 +947,7 @@ static void nf_tables_table_destroy(stru ++ ++ kfree(ctx->table->name); ++ kfree(ctx->table); ++- module_put(ctx->afi->owner); +++ module_put(ctx->table->afi->owner); ++ } ++ ++ int nft_register_chain_type(const struct nf_chain_type *ctype) ++@@ -1151,7 +1148,7 @@ static void nf_tables_chain_notify(const ++ goto err; ++ ++ err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq, ++- event, 0, ctx->afi->family, ctx->table, +++ event, 0, ctx->family, ctx->table, ++ ctx->chain); ++ if (err < 0) { ++ kfree_skb(skb); ++@@ -1169,7 +1166,6 @@ static int nf_tables_dump_chains(struct ++ struct netlink_callback *cb) ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ const struct nft_chain *chain; ++ unsigned int idx = 0, s_idx = cb->args[0]; ++@@ -1179,31 +1175,30 @@ static int nf_tables_dump_chains(struct ++ rcu_read_lock(); ++ cb->seq = net->nft.base_seq; ++ ++- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- if (family != NFPROTO_UNSPEC && family != afi->family) +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { +++ if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ continue; ++ ++- list_for_each_entry_rcu(table, &afi->tables, list) { ++- list_for_each_entry_rcu(chain, &table->chains, list) { ++- if (idx < s_idx) ++- goto cont; ++- if (idx > s_idx) ++- memset(&cb->args[1], 0, ++- sizeof(cb->args) - sizeof(cb->args[0])); ++- if (!nft_is_active(net, chain)) ++- continue; ++- if (nf_tables_fill_chain_info(skb, net, ++- NETLINK_CB(cb->skb).portid, ++- cb->nlh->nlmsg_seq, ++- NFT_MSG_NEWCHAIN, ++- NLM_F_MULTI, ++- afi->family, table, chain) < 0) ++- goto done; +++ list_for_each_entry_rcu(chain, &table->chains, list) { +++ if (idx < s_idx) +++ goto cont; +++ if (idx > s_idx) +++ memset(&cb->args[1], 0, +++ sizeof(cb->args) - sizeof(cb->args[0])); +++ if (!nft_is_active(net, chain)) +++ continue; +++ if (nf_tables_fill_chain_info(skb, net, +++ NETLINK_CB(cb->skb).portid, +++ cb->nlh->nlmsg_seq, +++ NFT_MSG_NEWCHAIN, +++ NLM_F_MULTI, +++ table->afi->family, table, +++ chain) < 0) +++ goto done; ++ ++- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ cont: ++- idx++; ++- } +++ idx++; ++ } ++ } ++ done: ++@@ -1237,7 +1232,8 @@ static int nf_tables_getchain(struct net ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -1347,8 +1343,8 @@ struct nft_chain_hook { ++ ++ static int nft_chain_parse_hook(struct net *net, ++ const struct nlattr * const nla[], ++- struct nft_af_info *afi, ++- struct nft_chain_hook *hook, bool create) +++ struct nft_chain_hook *hook, u8 family, +++ bool create) ++ { ++ struct nlattr *ha[NFTA_HOOK_MAX + 1]; ++ const struct nf_chain_type *type; ++@@ -1367,10 +1363,10 @@ static int nft_chain_parse_hook(struct n ++ hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); ++ hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); ++ ++- type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT]; +++ type = chain_type[family][NFT_CHAIN_T_DEFAULT]; ++ if (nla[NFTA_CHAIN_TYPE]) { ++ type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE], ++- afi->family, create); +++ family, create); ++ if (IS_ERR(type)) ++ return PTR_ERR(type); ++ } ++@@ -1382,7 +1378,7 @@ static int nft_chain_parse_hook(struct n ++ hook->type = type; ++ ++ hook->dev = NULL; ++- if (afi->family == NFPROTO_NETDEV) { +++ if (family == NFPROTO_NETDEV) { ++ char ifname[IFNAMSIZ]; ++ ++ if (!ha[NFTA_HOOK_DEV]) { ++@@ -1417,7 +1413,6 @@ static int nf_tables_addchain(struct nft ++ { ++ const struct nlattr * const *nla = ctx->nla; ++ struct nft_table *table = ctx->table; ++- struct nft_af_info *afi = ctx->afi; ++ struct nft_base_chain *basechain; ++ struct nft_stats __percpu *stats; ++ struct net *net = ctx->net; ++@@ -1431,7 +1426,7 @@ static int nf_tables_addchain(struct nft ++ struct nft_chain_hook hook; ++ struct nf_hook_ops *ops; ++ ++- err = nft_chain_parse_hook(net, nla, afi, &hook, create); +++ err = nft_chain_parse_hook(net, nla, &hook, family, create); ++ if (err < 0) ++ return err; ++ ++@@ -1523,7 +1518,7 @@ static int nf_tables_updchain(struct nft ++ if (!nft_is_base_chain(chain)) ++ return -EBUSY; ++ ++- err = nft_chain_parse_hook(ctx->net, nla, ctx->afi, &hook, +++ err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family, ++ create); ++ if (err < 0) ++ return err; ++@@ -1633,7 +1628,8 @@ static int nf_tables_newchain(struct net ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -1673,7 +1669,7 @@ static int nf_tables_newchain(struct net ++ } ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); ++ ++ if (chain != NULL) { ++ if (nlh->nlmsg_flags & NLM_F_EXCL) ++@@ -1707,7 +1703,8 @@ static int nf_tables_delchain(struct net ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -1719,7 +1716,7 @@ static int nf_tables_delchain(struct net ++ chain->use > 0) ++ return -EBUSY; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); ++ ++ use = chain->use; ++ list_for_each_entry(rule, &chain->rules, list) { ++@@ -1887,7 +1884,7 @@ static int nf_tables_expr_parse(const st ++ if (err < 0) ++ return err; ++ ++- type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]); +++ type = nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]); ++ if (IS_ERR(type)) ++ return PTR_ERR(type); ++ ++@@ -2115,7 +2112,7 @@ static void nf_tables_rule_notify(const ++ goto err; ++ ++ err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq, ++- event, 0, ctx->afi->family, ctx->table, +++ event, 0, ctx->family, ctx->table, ++ ctx->chain, rule); ++ if (err < 0) { ++ kfree_skb(skb); ++@@ -2139,7 +2136,6 @@ static int nf_tables_dump_rules(struct s ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); ++ const struct nft_rule_dump_ctx *ctx = cb->data; ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ const struct nft_chain *chain; ++ const struct nft_rule *rule; ++@@ -2150,39 +2146,37 @@ static int nf_tables_dump_rules(struct s ++ rcu_read_lock(); ++ cb->seq = net->nft.base_seq; ++ ++- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- if (family != NFPROTO_UNSPEC && family != afi->family) +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { +++ if (family != NFPROTO_UNSPEC && family != table->afi->family) +++ continue; +++ +++ if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0) ++ continue; ++ ++- list_for_each_entry_rcu(table, &afi->tables, list) { ++- if (ctx && ctx->table && ++- strcmp(ctx->table, table->name) != 0) +++ list_for_each_entry_rcu(chain, &table->chains, list) { +++ if (ctx && ctx->chain && +++ strcmp(ctx->chain, chain->name) != 0) ++ continue; ++ ++- list_for_each_entry_rcu(chain, &table->chains, list) { ++- if (ctx && ctx->chain && ++- strcmp(ctx->chain, chain->name) != 0) ++- continue; ++- ++- list_for_each_entry_rcu(rule, &chain->rules, list) { ++- if (!nft_is_active(net, rule)) ++- goto cont; ++- if (idx < s_idx) ++- goto cont; ++- if (idx > s_idx) ++- memset(&cb->args[1], 0, ++- sizeof(cb->args) - sizeof(cb->args[0])); ++- if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid, ++- cb->nlh->nlmsg_seq, ++- NFT_MSG_NEWRULE, ++- NLM_F_MULTI | NLM_F_APPEND, ++- afi->family, table, chain, rule) < 0) ++- goto done; +++ list_for_each_entry_rcu(rule, &chain->rules, list) { +++ if (!nft_is_active(net, rule)) +++ goto cont; +++ if (idx < s_idx) +++ goto cont; +++ if (idx > s_idx) +++ memset(&cb->args[1], 0, +++ sizeof(cb->args) - sizeof(cb->args[0])); +++ if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid, +++ cb->nlh->nlmsg_seq, +++ NFT_MSG_NEWRULE, +++ NLM_F_MULTI | NLM_F_APPEND, +++ table->afi->family, +++ table, chain, rule) < 0) +++ goto done; ++ ++- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ cont: ++- idx++; ++- } +++ idx++; ++ } ++ } ++ } ++@@ -2260,7 +2254,8 @@ static int nf_tables_getrule(struct net ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -2345,7 +2340,8 @@ static int nf_tables_newrule(struct net ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -2384,7 +2380,7 @@ static int nf_tables_newrule(struct net ++ return PTR_ERR(old_rule); ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); ++ ++ n = 0; ++ size = 0; ++@@ -2517,7 +2513,8 @@ static int nf_tables_delrule(struct net ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -2528,7 +2525,7 @@ static int nf_tables_delrule(struct net ++ return PTR_ERR(chain); ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); ++ ++ if (chain) { ++ if (nla[NFTA_RULE_HANDLE]) { ++@@ -2726,13 +2723,13 @@ static int nft_ctx_init_from_setattr(str ++ if (afi == NULL) ++ return -EAFNOSUPPORT; ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], ++- genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], +++ afi->family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ } ++ ++- nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ return 0; ++ } ++ ++@@ -2860,7 +2857,7 @@ static int nf_tables_fill_set(struct sk_ ++ goto nla_put_failure; ++ ++ nfmsg = nlmsg_data(nlh); ++- nfmsg->nfgen_family = ctx->afi->family; +++ nfmsg->nfgen_family = ctx->family; ++ nfmsg->version = NFNETLINK_V0; ++ nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); ++ ++@@ -2952,10 +2949,8 @@ static int nf_tables_dump_sets(struct sk ++ { ++ const struct nft_set *set; ++ unsigned int idx, s_idx = cb->args[0]; ++- struct nft_af_info *afi; ++ struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; ++ struct net *net = sock_net(skb->sk); ++- int cur_family = cb->args[3]; ++ struct nft_ctx *ctx = cb->data, ctx_set; ++ ++ if (cb->args[1]) ++@@ -2964,51 +2959,44 @@ static int nf_tables_dump_sets(struct sk ++ rcu_read_lock(); ++ cb->seq = net->nft.base_seq; ++ ++- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- if (ctx->afi && ctx->afi != afi) +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { +++ if (ctx->family != NFPROTO_UNSPEC && +++ ctx->family != table->afi->family) ++ continue; ++ ++- if (cur_family) { ++- if (afi->family != cur_family) ++- continue; +++ if (ctx->table && ctx->table != table) +++ continue; ++ ++- cur_family = 0; ++- } ++- list_for_each_entry_rcu(table, &afi->tables, list) { ++- if (ctx->table && ctx->table != table) +++ if (cur_table) { +++ if (cur_table != table) ++ continue; ++ ++- if (cur_table) { ++- if (cur_table != table) ++- continue; +++ cur_table = NULL; +++ } +++ idx = 0; +++ list_for_each_entry_rcu(set, &table->sets, list) { +++ if (idx < s_idx) +++ goto cont; +++ if (!nft_is_active(net, set)) +++ goto cont; ++ ++- cur_table = NULL; +++ ctx_set = *ctx; +++ ctx_set.table = table; +++ ctx_set.family = table->afi->family; +++ +++ if (nf_tables_fill_set(skb, &ctx_set, set, +++ NFT_MSG_NEWSET, +++ NLM_F_MULTI) < 0) { +++ cb->args[0] = idx; +++ cb->args[2] = (unsigned long) table; +++ goto done; ++ } ++- idx = 0; ++- list_for_each_entry_rcu(set, &table->sets, list) { ++- if (idx < s_idx) ++- goto cont; ++- if (!nft_is_active(net, set)) ++- goto cont; ++- ++- ctx_set = *ctx; ++- ctx_set.table = table; ++- ctx_set.afi = afi; ++- if (nf_tables_fill_set(skb, &ctx_set, set, ++- NFT_MSG_NEWSET, ++- NLM_F_MULTI) < 0) { ++- cb->args[0] = idx; ++- cb->args[2] = (unsigned long) table; ++- cb->args[3] = afi->family; ++- goto done; ++- } ++- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ cont: ++- idx++; ++- } ++- if (s_idx) ++- s_idx = 0; +++ idx++; ++ } +++ if (s_idx) +++ s_idx = 0; ++ } ++ cb->args[1] = 1; ++ done: ++@@ -3221,11 +3209,12 @@ static int nf_tables_newset(struct net * ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ ++ set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask); ++ if (IS_ERR(set)) { ++@@ -3494,12 +3483,12 @@ static int nft_ctx_init_from_elemattr(st ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE], ++- genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], +++ afi->family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++- nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ return 0; ++ } ++ ++@@ -3604,7 +3593,6 @@ static int nf_tables_dump_set(struct sk_ ++ { ++ struct nft_set_dump_ctx *dump_ctx = cb->data; ++ struct net *net = sock_net(skb->sk); ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_set *set; ++ struct nft_set_dump_args args; ++@@ -3616,21 +3604,19 @@ static int nf_tables_dump_set(struct sk_ ++ int event; ++ ++ rcu_read_lock(); ++- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- if (afi != dump_ctx->ctx.afi) +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { +++ if (dump_ctx->ctx.family != NFPROTO_UNSPEC && +++ dump_ctx->ctx.family != table->afi->family) ++ continue; ++ ++- list_for_each_entry_rcu(table, &afi->tables, list) { ++- if (table != dump_ctx->ctx.table) ++- continue; +++ if (table != dump_ctx->ctx.table) +++ continue; ++ ++- list_for_each_entry_rcu(set, &table->sets, list) { ++- if (set == dump_ctx->set) { ++- set_found = true; ++- break; ++- } +++ list_for_each_entry_rcu(set, &table->sets, list) { +++ if (set == dump_ctx->set) { +++ set_found = true; +++ break; ++ } ++- break; ++ } ++ break; ++ } ++@@ -3650,7 +3636,7 @@ static int nf_tables_dump_set(struct sk_ ++ goto nla_put_failure; ++ ++ nfmsg = nlmsg_data(nlh); ++- nfmsg->nfgen_family = afi->family; +++ nfmsg->nfgen_family = table->afi->family; ++ nfmsg->version = NFNETLINK_V0; ++ nfmsg->res_id = htons(net->nft.base_seq & 0xffff); ++ ++@@ -3752,7 +3738,7 @@ static int nf_tables_fill_setelem_info(s ++ goto nla_put_failure; ++ ++ nfmsg = nlmsg_data(nlh); ++- nfmsg->nfgen_family = ctx->afi->family; +++ nfmsg->nfgen_family = ctx->family; ++ nfmsg->version = NFNETLINK_V0; ++ nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); ++ ++@@ -4002,7 +3988,7 @@ static int nft_add_set_elem(struct nft_c ++ list_for_each_entry(binding, &set->bindings, list) { ++ struct nft_ctx bind_ctx = { ++ .net = ctx->net, ++- .afi = ctx->afi, +++ .family = ctx->family, ++ .table = ctx->table, ++ .chain = (struct nft_chain *)binding->chain, ++ }; ++@@ -4554,7 +4540,8 @@ static int nf_tables_newobj(struct net * ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -4572,7 +4559,7 @@ static int nf_tables_newobj(struct net * ++ return 0; ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ ++ type = nft_obj_type_get(objtype); ++ if (IS_ERR(type)) ++@@ -4649,7 +4636,6 @@ struct nft_obj_filter { ++ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ unsigned int idx = 0, s_idx = cb->args[0]; ++ struct nft_obj_filter *filter = cb->data; ++@@ -4664,38 +4650,37 @@ static int nf_tables_dump_obj(struct sk_ ++ rcu_read_lock(); ++ cb->seq = net->nft.base_seq; ++ ++- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- if (family != NFPROTO_UNSPEC && family != afi->family) +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { +++ if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ continue; ++ ++- list_for_each_entry_rcu(table, &afi->tables, list) { ++- list_for_each_entry_rcu(obj, &table->objects, list) { ++- if (!nft_is_active(net, obj)) ++- goto cont; ++- if (idx < s_idx) ++- goto cont; ++- if (idx > s_idx) ++- memset(&cb->args[1], 0, ++- sizeof(cb->args) - sizeof(cb->args[0])); ++- if (filter && filter->table && ++- strcmp(filter->table, table->name)) ++- goto cont; ++- if (filter && ++- filter->type != NFT_OBJECT_UNSPEC && ++- obj->ops->type->type != filter->type) ++- goto cont; +++ list_for_each_entry_rcu(obj, &table->objects, list) { +++ if (!nft_is_active(net, obj)) +++ goto cont; +++ if (idx < s_idx) +++ goto cont; +++ if (idx > s_idx) +++ memset(&cb->args[1], 0, +++ sizeof(cb->args) - sizeof(cb->args[0])); +++ if (filter && filter->table && +++ strcmp(filter->table, table->name)) +++ goto cont; +++ if (filter && +++ filter->type != NFT_OBJECT_UNSPEC && +++ obj->ops->type->type != filter->type) +++ goto cont; ++ ++- if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, ++- cb->nlh->nlmsg_seq, ++- NFT_MSG_NEWOBJ, ++- NLM_F_MULTI | NLM_F_APPEND, ++- afi->family, table, obj, reset) < 0) ++- goto done; +++ if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, +++ cb->nlh->nlmsg_seq, +++ NFT_MSG_NEWOBJ, +++ NLM_F_MULTI | NLM_F_APPEND, +++ table->afi->family, table, +++ obj, reset) < 0) +++ goto done; ++ ++- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ cont: ++- idx++; ++- } +++ idx++; ++ } ++ } ++ done: ++@@ -4782,7 +4767,8 @@ static int nf_tables_getobj(struct net * ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -4842,7 +4828,8 @@ static int nf_tables_delobj(struct net * ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, +++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -4853,7 +4840,7 @@ static int nf_tables_delobj(struct net * ++ if (obj->use > 0) ++ return -EBUSY; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ ++ return nft_delobj(&ctx, obj); ++ } ++@@ -4891,7 +4878,7 @@ static void nf_tables_obj_notify(const s ++ struct nft_object *obj, int event) ++ { ++ nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, ++- ctx->afi->family, ctx->report, GFP_KERNEL); +++ ctx->family, ctx->report, GFP_KERNEL); ++ } ++ ++ /* ++@@ -5081,7 +5068,7 @@ void nft_flow_table_iterate(struct net * ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- list_for_each_entry_rcu(table, &afi->tables, list) { +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++ iter(&flowtable->data, data); ++ } ++@@ -5129,7 +5116,8 @@ static int nf_tables_newflowtable(struct ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], +++ afi->family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -5146,7 +5134,7 @@ static int nf_tables_newflowtable(struct ++ return 0; ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ ++ flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL); ++ if (!flowtable) ++@@ -5227,7 +5215,8 @@ static int nf_tables_delflowtable(struct ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], +++ afi->family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -5238,7 +5227,7 @@ static int nf_tables_delflowtable(struct ++ if (flowtable->use > 0) ++ return -EBUSY; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ ++ return nft_delflowtable(&ctx, flowtable); ++ } ++@@ -5307,40 +5296,37 @@ static int nf_tables_dump_flowtable(stru ++ struct net *net = sock_net(skb->sk); ++ int family = nfmsg->nfgen_family; ++ struct nft_flowtable *flowtable; ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ ++ rcu_read_lock(); ++ cb->seq = net->nft.base_seq; ++ ++- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- if (family != NFPROTO_UNSPEC && family != afi->family) +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { +++ if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ continue; ++ ++- list_for_each_entry_rcu(table, &afi->tables, list) { ++- list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++- if (!nft_is_active(net, flowtable)) ++- goto cont; ++- if (idx < s_idx) ++- goto cont; ++- if (idx > s_idx) ++- memset(&cb->args[1], 0, ++- sizeof(cb->args) - sizeof(cb->args[0])); ++- if (filter && filter->table[0] && ++- strcmp(filter->table, table->name)) ++- goto cont; +++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { +++ if (!nft_is_active(net, flowtable)) +++ goto cont; +++ if (idx < s_idx) +++ goto cont; +++ if (idx > s_idx) +++ memset(&cb->args[1], 0, +++ sizeof(cb->args) - sizeof(cb->args[0])); +++ if (filter && filter->table && +++ strcmp(filter->table, table->name)) +++ goto cont; ++ ++- if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, ++- cb->nlh->nlmsg_seq, ++- NFT_MSG_NEWFLOWTABLE, ++- NLM_F_MULTI | NLM_F_APPEND, ++- afi->family, flowtable) < 0) ++- goto done; +++ if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, +++ cb->nlh->nlmsg_seq, +++ NFT_MSG_NEWFLOWTABLE, +++ NLM_F_MULTI | NLM_F_APPEND, +++ table->afi->family, flowtable) < 0) +++ goto done; ++ ++- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ cont: ++- idx++; ++- } +++ idx++; ++ } ++ } ++ done: ++@@ -5425,7 +5411,8 @@ static int nf_tables_getflowtable(struct ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++- table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); +++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], +++ afi->family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -5468,7 +5455,7 @@ static void nf_tables_flowtable_notify(s ++ ++ err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid, ++ ctx->seq, event, 0, ++- ctx->afi->family, flowtable); +++ ctx->family, flowtable); ++ if (err < 0) { ++ kfree_skb(skb); ++ goto err; ++@@ -5546,17 +5533,14 @@ static int nf_tables_flowtable_event(str ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ struct nft_flowtable *flowtable; ++ struct nft_table *table; ++- struct nft_af_info *afi; ++ ++ if (event != NETDEV_UNREGISTER) ++ return 0; ++ ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { ++- list_for_each_entry(table, &afi->tables, list) { ++- list_for_each_entry(flowtable, &table->flowtables, list) { ++- nft_flowtable_event(event, dev, flowtable); ++- } +++ list_for_each_entry(table, &dev_net(dev)->nft.tables, list) { +++ list_for_each_entry(flowtable, &table->flowtables, list) { +++ nft_flowtable_event(event, dev, flowtable); ++ } ++ } ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++@@ -6582,6 +6566,7 @@ EXPORT_SYMBOL_GPL(nft_data_dump); ++ static int __net_init nf_tables_init_net(struct net *net) ++ { ++ INIT_LIST_HEAD(&net->nft.af_info); +++ INIT_LIST_HEAD(&net->nft.tables); ++ INIT_LIST_HEAD(&net->nft.commit_list); ++ net->nft.base_seq = 1; ++ return 0; ++@@ -6618,10 +6603,10 @@ static void __nft_release_afinfo(struct ++ struct nft_set *set, *ns; ++ struct nft_ctx ctx = { ++ .net = net, ++- .afi = afi, +++ .family = afi->family, ++ }; ++ ++- list_for_each_entry_safe(table, nt, &afi->tables, list) { +++ list_for_each_entry_safe(table, nt, &net->nft.tables, list) { ++ list_for_each_entry(chain, &table->chains, list) ++ nf_tables_unregister_hook(net, table, chain); ++ list_for_each_entry(flowtable, &table->flowtables, list) ++--- a/net/netfilter/nf_tables_netdev.c +++++ b/net/netfilter/nf_tables_netdev.c ++@@ -107,7 +107,6 @@ static int nf_tables_netdev_event(struct ++ unsigned long event, void *ptr) ++ { ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_chain *chain, *nr; ++ struct nft_ctx ctx = { ++@@ -119,20 +118,18 @@ static int nf_tables_netdev_event(struct ++ return NOTIFY_DONE; ++ ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { ++- ctx.afi = afi; ++- if (afi->family != NFPROTO_NETDEV) +++ list_for_each_entry(table, &ctx.net->nft.tables, list) { +++ if (table->afi->family != NFPROTO_NETDEV) ++ continue; ++ ++- list_for_each_entry(table, &afi->tables, list) { ++- ctx.table = table; ++- list_for_each_entry_safe(chain, nr, &table->chains, list) { ++- if (!nft_is_base_chain(chain)) ++- continue; +++ ctx.family = table->afi->family; +++ ctx.table = table; +++ list_for_each_entry_safe(chain, nr, &table->chains, list) { +++ if (!nft_is_base_chain(chain)) +++ continue; ++ ++- ctx.chain = chain; ++- nft_netdev_event(event, dev, &ctx); ++- } +++ ctx.chain = chain; +++ nft_netdev_event(event, dev, &ctx); ++ } ++ } ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++--- a/net/netfilter/nft_compat.c +++++ b/net/netfilter/nft_compat.c ++@@ -161,7 +161,7 @@ nft_target_set_tgchk_param(struct xt_tgc ++ { ++ par->net = ctx->net; ++ par->table = ctx->table->name; ++- switch (ctx->afi->family) { +++ switch (ctx->family) { ++ case AF_INET: ++ entry->e4.ip.proto = proto; ++ entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; ++@@ -192,7 +192,7 @@ nft_target_set_tgchk_param(struct xt_tgc ++ } else { ++ par->hook_mask = 0; ++ } ++- par->family = ctx->afi->family; +++ par->family = ctx->family; ++ par->nft_compat = true; ++ } ++ ++@@ -283,7 +283,7 @@ nft_target_destroy(const struct nft_ctx ++ par.net = ctx->net; ++ par.target = target; ++ par.targinfo = info; ++- par.family = ctx->afi->family; +++ par.family = ctx->family; ++ if (par.target->destroy != NULL) ++ par.target->destroy(&par); ++ ++@@ -409,7 +409,7 @@ nft_match_set_mtchk_param(struct xt_mtch ++ { ++ par->net = ctx->net; ++ par->table = ctx->table->name; ++- switch (ctx->afi->family) { +++ switch (ctx->family) { ++ case AF_INET: ++ entry->e4.ip.proto = proto; ++ entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; ++@@ -440,7 +440,7 @@ nft_match_set_mtchk_param(struct xt_mtch ++ } else { ++ par->hook_mask = 0; ++ } ++- par->family = ctx->afi->family; +++ par->family = ctx->family; ++ par->nft_compat = true; ++ } ++ ++@@ -523,7 +523,7 @@ __nft_match_destroy(const struct nft_ctx ++ par.net = ctx->net; ++ par.match = match; ++ par.matchinfo = info; ++- par.family = ctx->afi->family; +++ par.family = ctx->family; ++ if (par.match->destroy != NULL) ++ par.match->destroy(&par); ++ ++@@ -754,7 +754,7 @@ nft_match_select_ops(const struct nft_ct ++ ++ mt_name = nla_data(tb[NFTA_MATCH_NAME]); ++ rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV])); ++- family = ctx->afi->family; +++ family = ctx->family; ++ ++ /* Re-use the existing match if it's already loaded. */ ++ list_for_each_entry(nft_match, &nft_match_list, head) { ++@@ -845,7 +845,7 @@ nft_target_select_ops(const struct nft_c ++ ++ tg_name = nla_data(tb[NFTA_TARGET_NAME]); ++ rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV])); ++- family = ctx->afi->family; +++ family = ctx->family; ++ ++ if (strcmp(tg_name, XT_ERROR_TARGET) == 0 || ++ strcmp(tg_name, XT_STANDARD_TARGET) == 0 || ++--- a/net/netfilter/nft_ct.c +++++ b/net/netfilter/nft_ct.c ++@@ -405,7 +405,7 @@ static int nft_ct_get_init(const struct ++ if (tb[NFTA_CT_DIRECTION] == NULL) ++ return -EINVAL; ++ ++- switch (ctx->afi->family) { +++ switch (ctx->family) { ++ case NFPROTO_IPV4: ++ len = FIELD_SIZEOF(struct nf_conntrack_tuple, ++ src.u3.ip); ++@@ -456,7 +456,7 @@ static int nft_ct_get_init(const struct ++ if (err < 0) ++ return err; ++ ++- err = nf_ct_netns_get(ctx->net, ctx->afi->family); +++ err = nf_ct_netns_get(ctx->net, ctx->family); ++ if (err < 0) ++ return err; ++ ++@@ -550,7 +550,7 @@ static int nft_ct_set_init(const struct ++ if (err < 0) ++ goto err1; ++ ++- err = nf_ct_netns_get(ctx->net, ctx->afi->family); +++ err = nf_ct_netns_get(ctx->net, ctx->family); ++ if (err < 0) ++ goto err1; ++ ++@@ -564,7 +564,7 @@ err1: ++ static void nft_ct_get_destroy(const struct nft_ctx *ctx, ++ const struct nft_expr *expr) ++ { ++- nf_ct_netns_put(ctx->net, ctx->afi->family); +++ nf_ct_netns_put(ctx->net, ctx->family); ++ } ++ ++ static void nft_ct_set_destroy(const struct nft_ctx *ctx, ++@@ -573,7 +573,7 @@ static void nft_ct_set_destroy(const str ++ struct nft_ct *priv = nft_expr_priv(expr); ++ ++ __nft_ct_set_destroy(ctx, priv); ++- nf_ct_netns_put(ctx->net, ctx->afi->family); +++ nf_ct_netns_put(ctx->net, ctx->family); ++ } ++ ++ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) ++@@ -734,7 +734,7 @@ static int nft_ct_helper_obj_init(const ++ struct nft_ct_helper_obj *priv = nft_obj_data(obj); ++ struct nf_conntrack_helper *help4, *help6; ++ char name[NF_CT_HELPER_NAME_LEN]; ++- int family = ctx->afi->family; +++ int family = ctx->family; ++ ++ if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO]) ++ return -EINVAL; ++@@ -753,14 +753,14 @@ static int nft_ct_helper_obj_init(const ++ ++ switch (family) { ++ case NFPROTO_IPV4: ++- if (ctx->afi->family == NFPROTO_IPV6) +++ if (ctx->family == NFPROTO_IPV6) ++ return -EINVAL; ++ ++ help4 = nf_conntrack_helper_try_module_get(name, family, ++ priv->l4proto); ++ break; ++ case NFPROTO_IPV6: ++- if (ctx->afi->family == NFPROTO_IPV4) +++ if (ctx->family == NFPROTO_IPV4) ++ return -EINVAL; ++ ++ help6 = nf_conntrack_helper_try_module_get(name, family, ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -151,7 +151,7 @@ static int nft_flow_offload_init(const s ++ priv->flowtable = flowtable; ++ flowtable->use++; ++ ++- return nf_ct_netns_get(ctx->net, ctx->afi->family); +++ return nf_ct_netns_get(ctx->net, ctx->family); ++ } ++ ++ static void nft_flow_offload_destroy(const struct nft_ctx *ctx, ++@@ -160,7 +160,7 @@ static void nft_flow_offload_destroy(con ++ struct nft_flow_offload *priv = nft_expr_priv(expr); ++ ++ priv->flowtable->use--; ++- nf_ct_netns_put(ctx->net, ctx->afi->family); +++ nf_ct_netns_put(ctx->net, ctx->family); ++ } ++ ++ static int nft_flow_offload_dump(struct sk_buff *skb, const struct nft_expr *expr) ++--- a/net/netfilter/nft_log.c +++++ b/net/netfilter/nft_log.c ++@@ -112,7 +112,7 @@ static int nft_log_init(const struct nft ++ break; ++ } ++ ++- err = nf_logger_find_get(ctx->afi->family, li->type); +++ err = nf_logger_find_get(ctx->family, li->type); ++ if (err < 0) ++ goto err1; ++ ++@@ -133,7 +133,7 @@ static void nft_log_destroy(const struct ++ if (priv->prefix != nft_log_null_prefix) ++ kfree(priv->prefix); ++ ++- nf_logger_put(ctx->afi->family, li->type); +++ nf_logger_put(ctx->family, li->type); ++ } ++ ++ static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr) ++--- a/net/netfilter/nft_masq.c +++++ b/net/netfilter/nft_masq.c ++@@ -73,7 +73,7 @@ int nft_masq_init(const struct nft_ctx * ++ } ++ } ++ ++- return nf_ct_netns_get(ctx->net, ctx->afi->family); +++ return nf_ct_netns_get(ctx->net, ctx->family); ++ } ++ EXPORT_SYMBOL_GPL(nft_masq_init); ++ ++--- a/net/netfilter/nft_meta.c +++++ b/net/netfilter/nft_meta.c ++@@ -341,7 +341,7 @@ static int nft_meta_get_validate(const s ++ if (priv->key != NFT_META_SECPATH) ++ return 0; ++ ++- switch (ctx->afi->family) { +++ switch (ctx->family) { ++ case NFPROTO_NETDEV: ++ hooks = 1 << NF_NETDEV_INGRESS; ++ break; ++@@ -372,7 +372,7 @@ int nft_meta_set_validate(const struct n ++ if (priv->key != NFT_META_PKTTYPE) ++ return 0; ++ ++- switch (ctx->afi->family) { +++ switch (ctx->family) { ++ case NFPROTO_BRIDGE: ++ hooks = 1 << NF_BR_PRE_ROUTING; ++ break; ++--- a/net/netfilter/nft_nat.c +++++ b/net/netfilter/nft_nat.c ++@@ -142,7 +142,7 @@ static int nft_nat_init(const struct nft ++ return -EINVAL; ++ ++ family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); ++- if (family != ctx->afi->family) +++ if (family != ctx->family) ++ return -EOPNOTSUPP; ++ ++ switch (family) { ++--- a/net/netfilter/nft_redir.c +++++ b/net/netfilter/nft_redir.c ++@@ -75,7 +75,7 @@ int nft_redir_init(const struct nft_ctx ++ return -EINVAL; ++ } ++ ++- return nf_ct_netns_get(ctx->net, ctx->afi->family); +++ return nf_ct_netns_get(ctx->net, ctx->family); ++ } ++ EXPORT_SYMBOL_GPL(nft_redir_init); ++ +diff --git a/target/linux/generic/backport-4.14/336-v4.15-netfilter-exit_net-cleanup-check-added.patch b/target/linux/generic/backport-4.14/336-v4.15-netfilter-exit_net-cleanup-check-added.patch +new file mode 100644 +index 0000000000..b00675df20 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/336-v4.15-netfilter-exit_net-cleanup-check-added.patch +@@ -0,0 +1,100 @@ ++From: Vasily Averin ++Date: Sun, 12 Nov 2017 14:32:37 +0300 ++Subject: [PATCH] netfilter: exit_net cleanup check added ++ ++Be sure that lists initialized in net_init hook was return to initial ++state. ++ ++Signed-off-by: Vasily Averin ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c ++@@ -835,6 +835,7 @@ static void clusterip_net_exit(struct ne ++ cn->procdir = NULL; ++ #endif ++ nf_unregister_net_hook(net, &cip_arp_ops); +++ WARN_ON_ONCE(!list_empty(&cn->configs)); ++ } ++ ++ static struct pernet_operations clusterip_net_ops = { ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -6572,6 +6572,12 @@ static int __net_init nf_tables_init_net ++ return 0; ++ } ++ +++static void __net_exit nf_tables_exit_net(struct net *net) +++{ +++ WARN_ON_ONCE(!list_empty(&net->nft.af_info)); +++ WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); +++} +++ ++ int __nft_release_basechain(struct nft_ctx *ctx) ++ { ++ struct nft_rule *rule, *nr; ++@@ -6649,6 +6655,7 @@ static void __nft_release_afinfo(struct ++ ++ static struct pernet_operations nf_tables_net_ops = { ++ .init = nf_tables_init_net, +++ .exit = nf_tables_exit_net, ++ }; ++ ++ static int __init nf_tables_module_init(void) ++--- a/net/netfilter/nfnetlink_log.c +++++ b/net/netfilter/nfnetlink_log.c ++@@ -1093,10 +1093,15 @@ static int __net_init nfnl_log_net_init( ++ ++ static void __net_exit nfnl_log_net_exit(struct net *net) ++ { +++ struct nfnl_log_net *log = nfnl_log_pernet(net); +++ unsigned int i; +++ ++ #ifdef CONFIG_PROC_FS ++ remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter); ++ #endif ++ nf_log_unset(net, &nfulnl_logger); +++ for (i = 0; i < INSTANCE_BUCKETS; i++) +++ WARN_ON_ONCE(!hlist_empty(&log->instance_table[i])); ++ } ++ ++ static struct pernet_operations nfnl_log_net_ops = { ++--- a/net/netfilter/nfnetlink_queue.c +++++ b/net/netfilter/nfnetlink_queue.c ++@@ -1510,10 +1510,15 @@ static int __net_init nfnl_queue_net_ini ++ ++ static void __net_exit nfnl_queue_net_exit(struct net *net) ++ { +++ struct nfnl_queue_net *q = nfnl_queue_pernet(net); +++ unsigned int i; +++ ++ nf_unregister_queue_handler(net); ++ #ifdef CONFIG_PROC_FS ++ remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter); ++ #endif +++ for (i = 0; i < INSTANCE_BUCKETS; i++) +++ WARN_ON_ONCE(!hlist_empty(&q->instance_table[i])); ++ } ++ ++ static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list) ++--- a/net/netfilter/x_tables.c +++++ b/net/netfilter/x_tables.c ++@@ -1785,8 +1785,17 @@ static int __net_init xt_net_init(struct ++ return 0; ++ } ++ +++static void __net_exit xt_net_exit(struct net *net) +++{ +++ int i; +++ +++ for (i = 0; i < NFPROTO_NUMPROTO; i++) +++ WARN_ON_ONCE(!list_empty(&net->xt.tables[i])); +++} +++ ++ static struct pernet_operations xt_net_ops = { ++ .init = xt_net_init, +++ .exit = xt_net_exit, ++ }; ++ ++ static int __init xt_init(void) +diff --git a/target/linux/generic/backport-4.14/337-v4.16-netfilter-nf_tables-get-rid-of-pernet-families.patch b/target/linux/generic/backport-4.14/337-v4.16-netfilter-nf_tables-get-rid-of-pernet-families.patch +new file mode 100644 +index 0000000000..a42581a4bb +--- /dev/null ++++ b/target/linux/generic/backport-4.14/337-v4.16-netfilter-nf_tables-get-rid-of-pernet-families.patch +@@ -0,0 +1,598 @@ ++From: Pablo Neira Ayuso ++Date: Tue, 9 Jan 2018 02:42:11 +0100 ++Subject: [PATCH] netfilter: nf_tables: get rid of pernet families ++ ++Now that we have a single table list for each netns, we can get rid of ++one pointer per family and the global afinfo list, thus, shrinking ++struct netns for nftables that now becomes 64 bytes smaller. ++ ++And call __nft_release_afinfo() from __net_exit path accordingly to ++release netnamespace objects on removal. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -975,8 +975,8 @@ struct nft_af_info { ++ struct module *owner; ++ }; ++ ++-int nft_register_afinfo(struct net *, struct nft_af_info *); ++-void nft_unregister_afinfo(struct net *, struct nft_af_info *); +++int nft_register_afinfo(struct nft_af_info *); +++void nft_unregister_afinfo(struct nft_af_info *); ++ ++ int nft_register_chain_type(const struct nf_chain_type *); ++ void nft_unregister_chain_type(const struct nf_chain_type *); ++--- a/include/net/netns/nftables.h +++++ b/include/net/netns/nftables.h ++@@ -7,15 +7,8 @@ ++ struct nft_af_info; ++ ++ struct netns_nftables { ++- struct list_head af_info; ++ struct list_head tables; ++ struct list_head commit_list; ++- struct nft_af_info *ipv4; ++- struct nft_af_info *ipv6; ++- struct nft_af_info *inet; ++- struct nft_af_info *arp; ++- struct nft_af_info *bridge; ++- struct nft_af_info *netdev; ++ unsigned int base_seq; ++ u8 gencursor; ++ }; ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -47,34 +47,6 @@ static struct nft_af_info nft_af_bridge ++ .owner = THIS_MODULE, ++ }; ++ ++-static int nf_tables_bridge_init_net(struct net *net) ++-{ ++- net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); ++- if (net->nft.bridge == NULL) ++- return -ENOMEM; ++- ++- memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge)); ++- ++- if (nft_register_afinfo(net, net->nft.bridge) < 0) ++- goto err; ++- ++- return 0; ++-err: ++- kfree(net->nft.bridge); ++- return -ENOMEM; ++-} ++- ++-static void nf_tables_bridge_exit_net(struct net *net) ++-{ ++- nft_unregister_afinfo(net, net->nft.bridge); ++- kfree(net->nft.bridge); ++-} ++- ++-static struct pernet_operations nf_tables_bridge_net_ops = { ++- .init = nf_tables_bridge_init_net, ++- .exit = nf_tables_bridge_exit_net, ++-}; ++- ++ static const struct nf_chain_type filter_bridge = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -98,17 +70,17 @@ static int __init nf_tables_bridge_init( ++ { ++ int ret; ++ ++- ret = nft_register_chain_type(&filter_bridge); +++ ret = nft_register_afinfo(&nft_af_bridge); ++ if (ret < 0) ++ return ret; ++ ++- ret = register_pernet_subsys(&nf_tables_bridge_net_ops); +++ ret = nft_register_chain_type(&filter_bridge); ++ if (ret < 0) ++- goto err_register_subsys; +++ goto err_register_chain; ++ ++ return ret; ++ ++-err_register_subsys: +++err_register_chain: ++ nft_unregister_chain_type(&filter_bridge); ++ ++ return ret; ++@@ -116,8 +88,8 @@ err_register_subsys: ++ ++ static void __exit nf_tables_bridge_exit(void) ++ { ++- unregister_pernet_subsys(&nf_tables_bridge_net_ops); ++ nft_unregister_chain_type(&filter_bridge); +++ nft_unregister_afinfo(&nft_af_bridge); ++ } ++ ++ module_init(nf_tables_bridge_init); ++--- a/net/ipv4/netfilter/nf_tables_arp.c +++++ b/net/ipv4/netfilter/nf_tables_arp.c ++@@ -32,34 +32,6 @@ static struct nft_af_info nft_af_arp __r ++ .owner = THIS_MODULE, ++ }; ++ ++-static int nf_tables_arp_init_net(struct net *net) ++-{ ++- net->nft.arp = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); ++- if (net->nft.arp== NULL) ++- return -ENOMEM; ++- ++- memcpy(net->nft.arp, &nft_af_arp, sizeof(nft_af_arp)); ++- ++- if (nft_register_afinfo(net, net->nft.arp) < 0) ++- goto err; ++- ++- return 0; ++-err: ++- kfree(net->nft.arp); ++- return -ENOMEM; ++-} ++- ++-static void nf_tables_arp_exit_net(struct net *net) ++-{ ++- nft_unregister_afinfo(net, net->nft.arp); ++- kfree(net->nft.arp); ++-} ++- ++-static struct pernet_operations nf_tables_arp_net_ops = { ++- .init = nf_tables_arp_init_net, ++- .exit = nf_tables_arp_exit_net, ++-}; ++- ++ static const struct nf_chain_type filter_arp = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -77,21 +49,26 @@ static int __init nf_tables_arp_init(voi ++ { ++ int ret; ++ ++- ret = nft_register_chain_type(&filter_arp); +++ ret = nft_register_afinfo(&nft_af_arp); ++ if (ret < 0) ++ return ret; ++ ++- ret = register_pernet_subsys(&nf_tables_arp_net_ops); +++ ret = nft_register_chain_type(&filter_arp); ++ if (ret < 0) ++- nft_unregister_chain_type(&filter_arp); +++ goto err_register_chain; +++ +++ return 0; +++ +++err_register_chain: +++ nft_unregister_chain_type(&filter_arp); ++ ++ return ret; ++ } ++ ++ static void __exit nf_tables_arp_exit(void) ++ { ++- unregister_pernet_subsys(&nf_tables_arp_net_ops); ++ nft_unregister_chain_type(&filter_arp); +++ nft_unregister_afinfo(&nft_af_arp); ++ } ++ ++ module_init(nf_tables_arp_init); ++--- a/net/ipv4/netfilter/nf_tables_ipv4.c +++++ b/net/ipv4/netfilter/nf_tables_ipv4.c ++@@ -35,34 +35,6 @@ static struct nft_af_info nft_af_ipv4 __ ++ .owner = THIS_MODULE, ++ }; ++ ++-static int nf_tables_ipv4_init_net(struct net *net) ++-{ ++- net->nft.ipv4 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); ++- if (net->nft.ipv4 == NULL) ++- return -ENOMEM; ++- ++- memcpy(net->nft.ipv4, &nft_af_ipv4, sizeof(nft_af_ipv4)); ++- ++- if (nft_register_afinfo(net, net->nft.ipv4) < 0) ++- goto err; ++- ++- return 0; ++-err: ++- kfree(net->nft.ipv4); ++- return -ENOMEM; ++-} ++- ++-static void nf_tables_ipv4_exit_net(struct net *net) ++-{ ++- nft_unregister_afinfo(net, net->nft.ipv4); ++- kfree(net->nft.ipv4); ++-} ++- ++-static struct pernet_operations nf_tables_ipv4_net_ops = { ++- .init = nf_tables_ipv4_init_net, ++- .exit = nf_tables_ipv4_exit_net, ++-}; ++- ++ static const struct nf_chain_type filter_ipv4 = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -86,21 +58,25 @@ static int __init nf_tables_ipv4_init(vo ++ { ++ int ret; ++ ++- ret = nft_register_chain_type(&filter_ipv4); +++ ret = nft_register_afinfo(&nft_af_ipv4); ++ if (ret < 0) ++ return ret; ++ ++- ret = register_pernet_subsys(&nf_tables_ipv4_net_ops); +++ ret = nft_register_chain_type(&filter_ipv4); ++ if (ret < 0) ++- nft_unregister_chain_type(&filter_ipv4); +++ goto err_register_chain; +++ +++ return 0; ++ +++err_register_chain: +++ nft_unregister_afinfo(&nft_af_ipv4); ++ return ret; ++ } ++ ++ static void __exit nf_tables_ipv4_exit(void) ++ { ++- unregister_pernet_subsys(&nf_tables_ipv4_net_ops); ++ nft_unregister_chain_type(&filter_ipv4); +++ nft_unregister_afinfo(&nft_af_ipv4); ++ } ++ ++ module_init(nf_tables_ipv4_init); ++--- a/net/ipv6/netfilter/nf_tables_ipv6.c +++++ b/net/ipv6/netfilter/nf_tables_ipv6.c ++@@ -33,34 +33,6 @@ static struct nft_af_info nft_af_ipv6 __ ++ .owner = THIS_MODULE, ++ }; ++ ++-static int nf_tables_ipv6_init_net(struct net *net) ++-{ ++- net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); ++- if (net->nft.ipv6 == NULL) ++- return -ENOMEM; ++- ++- memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6)); ++- ++- if (nft_register_afinfo(net, net->nft.ipv6) < 0) ++- goto err; ++- ++- return 0; ++-err: ++- kfree(net->nft.ipv6); ++- return -ENOMEM; ++-} ++- ++-static void nf_tables_ipv6_exit_net(struct net *net) ++-{ ++- nft_unregister_afinfo(net, net->nft.ipv6); ++- kfree(net->nft.ipv6); ++-} ++- ++-static struct pernet_operations nf_tables_ipv6_net_ops = { ++- .init = nf_tables_ipv6_init_net, ++- .exit = nf_tables_ipv6_exit_net, ++-}; ++- ++ static const struct nf_chain_type filter_ipv6 = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -84,20 +56,24 @@ static int __init nf_tables_ipv6_init(vo ++ { ++ int ret; ++ ++- ret = nft_register_chain_type(&filter_ipv6); +++ ret = nft_register_afinfo(&nft_af_ipv6); ++ if (ret < 0) ++ return ret; ++ ++- ret = register_pernet_subsys(&nf_tables_ipv6_net_ops); +++ ret = nft_register_chain_type(&filter_ipv6); ++ if (ret < 0) ++- nft_unregister_chain_type(&filter_ipv6); +++ goto err_register_chain; +++ +++ return 0; ++ +++err_register_chain: +++ nft_unregister_afinfo(&nft_af_ipv6); ++ return ret; ++ } ++ ++ static void __exit nf_tables_ipv6_exit(void) ++ { ++- unregister_pernet_subsys(&nf_tables_ipv6_net_ops); +++ nft_unregister_afinfo(&nft_af_ipv6); ++ nft_unregister_chain_type(&filter_ipv6); ++ } ++ ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -26,6 +26,7 @@ ++ static LIST_HEAD(nf_tables_expressions); ++ static LIST_HEAD(nf_tables_objects); ++ static LIST_HEAD(nf_tables_flowtables); +++static LIST_HEAD(nf_tables_af_info); ++ ++ /** ++ * nft_register_afinfo - register nf_tables address family info ++@@ -35,17 +36,15 @@ static LIST_HEAD(nf_tables_flowtables); ++ * Register the address family for use with nf_tables. Returns zero on ++ * success or a negative errno code otherwise. ++ */ ++-int nft_register_afinfo(struct net *net, struct nft_af_info *afi) +++int nft_register_afinfo(struct nft_af_info *afi) ++ { ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- list_add_tail_rcu(&afi->list, &net->nft.af_info); +++ list_add_tail_rcu(&afi->list, &nf_tables_af_info); ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++ return 0; ++ } ++ EXPORT_SYMBOL_GPL(nft_register_afinfo); ++ ++-static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi); ++- ++ /** ++ * nft_unregister_afinfo - unregister nf_tables address family info ++ * ++@@ -53,10 +52,9 @@ static void __nft_release_afinfo(struct ++ * ++ * Unregister the address family for use with nf_tables. ++ */ ++-void nft_unregister_afinfo(struct net *net, struct nft_af_info *afi) +++void nft_unregister_afinfo(struct nft_af_info *afi) ++ { ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- __nft_release_afinfo(net, afi); ++ list_del_rcu(&afi->list); ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++ } ++@@ -66,7 +64,7 @@ static struct nft_af_info *nft_afinfo_lo ++ { ++ struct nft_af_info *afi; ++ ++- list_for_each_entry(afi, &net->nft.af_info, list) { +++ list_for_each_entry(afi, &nf_tables_af_info, list) { ++ if (afi->family == family) ++ return afi; ++ } ++@@ -5063,15 +5061,12 @@ void nft_flow_table_iterate(struct net * ++ void *data) ++ { ++ struct nft_flowtable *flowtable; ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ ++ rcu_read_lock(); ++- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++- list_for_each_entry_rcu(table, &net->nft.tables, list) { ++- list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++- iter(&flowtable->data, data); ++- } +++ list_for_each_entry_rcu(table, &net->nft.tables, list) { +++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { +++ iter(&flowtable->data, data); ++ } ++ } ++ rcu_read_unlock(); ++@@ -6563,21 +6558,6 @@ int nft_data_dump(struct sk_buff *skb, i ++ } ++ EXPORT_SYMBOL_GPL(nft_data_dump); ++ ++-static int __net_init nf_tables_init_net(struct net *net) ++-{ ++- INIT_LIST_HEAD(&net->nft.af_info); ++- INIT_LIST_HEAD(&net->nft.tables); ++- INIT_LIST_HEAD(&net->nft.commit_list); ++- net->nft.base_seq = 1; ++- return 0; ++-} ++- ++-static void __net_exit nf_tables_exit_net(struct net *net) ++-{ ++- WARN_ON_ONCE(!list_empty(&net->nft.af_info)); ++- WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); ++-} ++- ++ int __nft_release_basechain(struct nft_ctx *ctx) ++ { ++ struct nft_rule *rule, *nr; ++@@ -6598,8 +6578,7 @@ int __nft_release_basechain(struct nft_c ++ } ++ EXPORT_SYMBOL_GPL(__nft_release_basechain); ++ ++-/* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */ ++-static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) +++static void __nft_release_afinfo(struct net *net) ++ { ++ struct nft_flowtable *flowtable, *nf; ++ struct nft_table *table, *nt; ++@@ -6609,10 +6588,11 @@ static void __nft_release_afinfo(struct ++ struct nft_set *set, *ns; ++ struct nft_ctx ctx = { ++ .net = net, ++- .family = afi->family, ++ }; ++ ++ list_for_each_entry_safe(table, nt, &net->nft.tables, list) { +++ ctx.family = table->afi->family; +++ ++ list_for_each_entry(chain, &table->chains, list) ++ nf_tables_unregister_hook(net, table, chain); ++ list_for_each_entry(flowtable, &table->flowtables, list) ++@@ -6653,6 +6633,21 @@ static void __nft_release_afinfo(struct ++ } ++ } ++ +++static int __net_init nf_tables_init_net(struct net *net) +++{ +++ INIT_LIST_HEAD(&net->nft.tables); +++ INIT_LIST_HEAD(&net->nft.commit_list); +++ net->nft.base_seq = 1; +++ return 0; +++} +++ +++static void __net_exit nf_tables_exit_net(struct net *net) +++{ +++ __nft_release_afinfo(net); +++ WARN_ON_ONCE(!list_empty(&net->nft.tables)); +++ WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); +++} +++ ++ static struct pernet_operations nf_tables_net_ops = { ++ .init = nf_tables_init_net, ++ .exit = nf_tables_exit_net, ++--- a/net/netfilter/nf_tables_inet.c +++++ b/net/netfilter/nf_tables_inet.c ++@@ -43,34 +43,6 @@ static struct nft_af_info nft_af_inet __ ++ .owner = THIS_MODULE, ++ }; ++ ++-static int __net_init nf_tables_inet_init_net(struct net *net) ++-{ ++- net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); ++- if (net->nft.inet == NULL) ++- return -ENOMEM; ++- memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet)); ++- ++- if (nft_register_afinfo(net, net->nft.inet) < 0) ++- goto err; ++- ++- return 0; ++- ++-err: ++- kfree(net->nft.inet); ++- return -ENOMEM; ++-} ++- ++-static void __net_exit nf_tables_inet_exit_net(struct net *net) ++-{ ++- nft_unregister_afinfo(net, net->nft.inet); ++- kfree(net->nft.inet); ++-} ++- ++-static struct pernet_operations nf_tables_inet_net_ops = { ++- .init = nf_tables_inet_init_net, ++- .exit = nf_tables_inet_exit_net, ++-}; ++- ++ static const struct nf_chain_type filter_inet = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -94,21 +66,24 @@ static int __init nf_tables_inet_init(vo ++ { ++ int ret; ++ ++- ret = nft_register_chain_type(&filter_inet); ++- if (ret < 0) +++ if (nft_register_afinfo(&nft_af_inet) < 0) ++ return ret; ++ ++- ret = register_pernet_subsys(&nf_tables_inet_net_ops); +++ ret = nft_register_chain_type(&filter_inet); ++ if (ret < 0) ++- nft_unregister_chain_type(&filter_inet); +++ goto err_register_chain; +++ +++ return ret; ++ +++err_register_chain: +++ nft_unregister_afinfo(&nft_af_inet); ++ return ret; ++ } ++ ++ static void __exit nf_tables_inet_exit(void) ++ { ++- unregister_pernet_subsys(&nf_tables_inet_net_ops); ++ nft_unregister_chain_type(&filter_inet); +++ nft_unregister_afinfo(&nft_af_inet); ++ } ++ ++ module_init(nf_tables_inet_init); ++--- a/net/netfilter/nf_tables_netdev.c +++++ b/net/netfilter/nf_tables_netdev.c ++@@ -43,34 +43,6 @@ static struct nft_af_info nft_af_netdev ++ .owner = THIS_MODULE, ++ }; ++ ++-static int nf_tables_netdev_init_net(struct net *net) ++-{ ++- net->nft.netdev = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); ++- if (net->nft.netdev == NULL) ++- return -ENOMEM; ++- ++- memcpy(net->nft.netdev, &nft_af_netdev, sizeof(nft_af_netdev)); ++- ++- if (nft_register_afinfo(net, net->nft.netdev) < 0) ++- goto err; ++- ++- return 0; ++-err: ++- kfree(net->nft.netdev); ++- return -ENOMEM; ++-} ++- ++-static void nf_tables_netdev_exit_net(struct net *net) ++-{ ++- nft_unregister_afinfo(net, net->nft.netdev); ++- kfree(net->nft.netdev); ++-} ++- ++-static struct pernet_operations nf_tables_netdev_net_ops = { ++- .init = nf_tables_netdev_init_net, ++- .exit = nf_tables_netdev_exit_net, ++-}; ++- ++ static const struct nf_chain_type nft_filter_chain_netdev = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -145,32 +117,32 @@ static int __init nf_tables_netdev_init( ++ { ++ int ret; ++ ++- ret = nft_register_chain_type(&nft_filter_chain_netdev); ++- if (ret) +++ if (nft_register_afinfo(&nft_af_netdev) < 0) ++ return ret; ++ ++- ret = register_pernet_subsys(&nf_tables_netdev_net_ops); +++ ret = nft_register_chain_type(&nft_filter_chain_netdev); ++ if (ret) ++- goto err1; +++ goto err_register_chain_type; ++ ++ ret = register_netdevice_notifier(&nf_tables_netdev_notifier); ++ if (ret) ++- goto err2; +++ goto err_register_netdevice_notifier; ++ ++ return 0; ++ ++-err2: ++- unregister_pernet_subsys(&nf_tables_netdev_net_ops); ++-err1: +++err_register_netdevice_notifier: ++ nft_unregister_chain_type(&nft_filter_chain_netdev); +++err_register_chain_type: +++ nft_unregister_afinfo(&nft_af_netdev); +++ ++ return ret; ++ } ++ ++ static void __exit nf_tables_netdev_exit(void) ++ { ++ unregister_netdevice_notifier(&nf_tables_netdev_notifier); ++- unregister_pernet_subsys(&nf_tables_netdev_net_ops); ++ nft_unregister_chain_type(&nft_filter_chain_netdev); +++ nft_unregister_afinfo(&nft_af_netdev); ++ } ++ ++ module_init(nf_tables_netdev_init); +diff --git a/target/linux/generic/backport-4.14/338-v4.16-netfilter-nf_tables-get-rid-of-struct-nft_af_info-ab.patch b/target/linux/generic/backport-4.14/338-v4.16-netfilter-nf_tables-get-rid-of-struct-nft_af_info-ab.patch +new file mode 100644 +index 0000000000..7816718466 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/338-v4.16-netfilter-nf_tables-get-rid-of-struct-nft_af_info-ab.patch +@@ -0,0 +1,1204 @@ ++From: Pablo Neira Ayuso ++Date: Tue, 9 Jan 2018 02:48:47 +0100 ++Subject: [PATCH] netfilter: nf_tables: get rid of struct nft_af_info ++ abstraction ++ ++Remove the infrastructure to register/unregister nft_af_info structure, ++this structure stores no useful information anymore. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -956,28 +956,12 @@ struct nft_table { ++ struct list_head flowtables; ++ u64 hgenerator; ++ u32 use; ++- u16 flags:14, +++ u16 family:6, +++ flags:8, ++ genmask:2; ++- struct nft_af_info *afi; ++ char *name; ++ }; ++ ++-/** ++- * struct nft_af_info - nf_tables address family info ++- * ++- * @list: used internally ++- * @family: address family ++- * @owner: module owner ++- */ ++-struct nft_af_info { ++- struct list_head list; ++- int family; ++- struct module *owner; ++-}; ++- ++-int nft_register_afinfo(struct nft_af_info *); ++-void nft_unregister_afinfo(struct nft_af_info *); ++- ++ int nft_register_chain_type(const struct nf_chain_type *); ++ void nft_unregister_chain_type(const struct nf_chain_type *); ++ ++@@ -1145,9 +1129,6 @@ void nft_trace_notify(struct nft_tracein ++ #define nft_dereference(p) \ ++ nfnl_dereference(p, NFNL_SUBSYS_NFTABLES) ++ ++-#define MODULE_ALIAS_NFT_FAMILY(family) \ ++- MODULE_ALIAS("nft-afinfo-" __stringify(family)) ++- ++ #define MODULE_ALIAS_NFT_CHAIN(family, name) \ ++ MODULE_ALIAS("nft-chain-" __stringify(family) "-" name) ++ ++--- a/net/bridge/netfilter/nf_tables_bridge.c +++++ b/net/bridge/netfilter/nf_tables_bridge.c ++@@ -42,11 +42,6 @@ nft_do_chain_bridge(void *priv, ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static struct nft_af_info nft_af_bridge __read_mostly = { ++- .family = NFPROTO_BRIDGE, ++- .owner = THIS_MODULE, ++-}; ++- ++ static const struct nf_chain_type filter_bridge = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -68,28 +63,12 @@ static const struct nf_chain_type filter ++ ++ static int __init nf_tables_bridge_init(void) ++ { ++- int ret; ++- ++- ret = nft_register_afinfo(&nft_af_bridge); ++- if (ret < 0) ++- return ret; ++- ++- ret = nft_register_chain_type(&filter_bridge); ++- if (ret < 0) ++- goto err_register_chain; ++- ++- return ret; ++- ++-err_register_chain: ++- nft_unregister_chain_type(&filter_bridge); ++- ++- return ret; +++ return nft_register_chain_type(&filter_bridge); ++ } ++ ++ static void __exit nf_tables_bridge_exit(void) ++ { ++ nft_unregister_chain_type(&filter_bridge); ++- nft_unregister_afinfo(&nft_af_bridge); ++ } ++ ++ module_init(nf_tables_bridge_init); ++@@ -97,4 +76,4 @@ module_exit(nf_tables_bridge_exit); ++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Patrick McHardy "); ++-MODULE_ALIAS_NFT_FAMILY(AF_BRIDGE); +++MODULE_ALIAS_NFT_CHAIN(AF_BRIDGE, "filter"); ++--- a/net/ipv4/netfilter/nf_tables_arp.c +++++ b/net/ipv4/netfilter/nf_tables_arp.c ++@@ -27,11 +27,6 @@ nft_do_chain_arp(void *priv, ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static struct nft_af_info nft_af_arp __read_mostly = { ++- .family = NFPROTO_ARP, ++- .owner = THIS_MODULE, ++-}; ++- ++ static const struct nf_chain_type filter_arp = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -47,28 +42,12 @@ static const struct nf_chain_type filter ++ ++ static int __init nf_tables_arp_init(void) ++ { ++- int ret; ++- ++- ret = nft_register_afinfo(&nft_af_arp); ++- if (ret < 0) ++- return ret; ++- ++- ret = nft_register_chain_type(&filter_arp); ++- if (ret < 0) ++- goto err_register_chain; ++- ++- return 0; ++- ++-err_register_chain: ++- nft_unregister_chain_type(&filter_arp); ++- ++- return ret; +++ return nft_register_chain_type(&filter_arp); ++ } ++ ++ static void __exit nf_tables_arp_exit(void) ++ { ++ nft_unregister_chain_type(&filter_arp); ++- nft_unregister_afinfo(&nft_af_arp); ++ } ++ ++ module_init(nf_tables_arp_init); ++@@ -76,4 +55,4 @@ module_exit(nf_tables_arp_exit); ++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Patrick McHardy "); ++-MODULE_ALIAS_NFT_FAMILY(3); /* NFPROTO_ARP */ +++MODULE_ALIAS_NFT_CHAIN(3, "filter"); /* NFPROTO_ARP */ ++--- a/net/ipv4/netfilter/nf_tables_ipv4.c +++++ b/net/ipv4/netfilter/nf_tables_ipv4.c ++@@ -30,11 +30,6 @@ static unsigned int nft_do_chain_ipv4(vo ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static struct nft_af_info nft_af_ipv4 __read_mostly = { ++- .family = NFPROTO_IPV4, ++- .owner = THIS_MODULE, ++-}; ++- ++ static const struct nf_chain_type filter_ipv4 = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -56,27 +51,12 @@ static const struct nf_chain_type filter ++ ++ static int __init nf_tables_ipv4_init(void) ++ { ++- int ret; ++- ++- ret = nft_register_afinfo(&nft_af_ipv4); ++- if (ret < 0) ++- return ret; ++- ++- ret = nft_register_chain_type(&filter_ipv4); ++- if (ret < 0) ++- goto err_register_chain; ++- ++- return 0; ++- ++-err_register_chain: ++- nft_unregister_afinfo(&nft_af_ipv4); ++- return ret; +++ return nft_register_chain_type(&filter_ipv4); ++ } ++ ++ static void __exit nf_tables_ipv4_exit(void) ++ { ++ nft_unregister_chain_type(&filter_ipv4); ++- nft_unregister_afinfo(&nft_af_ipv4); ++ } ++ ++ module_init(nf_tables_ipv4_init); ++@@ -84,4 +64,4 @@ module_exit(nf_tables_ipv4_exit); ++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Patrick McHardy "); ++-MODULE_ALIAS_NFT_FAMILY(AF_INET); +++MODULE_ALIAS_NFT_CHAIN(AF_INET, "filter"); ++--- a/net/ipv6/netfilter/nf_tables_ipv6.c +++++ b/net/ipv6/netfilter/nf_tables_ipv6.c ++@@ -28,11 +28,6 @@ static unsigned int nft_do_chain_ipv6(vo ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static struct nft_af_info nft_af_ipv6 __read_mostly = { ++- .family = NFPROTO_IPV6, ++- .owner = THIS_MODULE, ++-}; ++- ++ static const struct nf_chain_type filter_ipv6 = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -54,26 +49,11 @@ static const struct nf_chain_type filter ++ ++ static int __init nf_tables_ipv6_init(void) ++ { ++- int ret; ++- ++- ret = nft_register_afinfo(&nft_af_ipv6); ++- if (ret < 0) ++- return ret; ++- ++- ret = nft_register_chain_type(&filter_ipv6); ++- if (ret < 0) ++- goto err_register_chain; ++- ++- return 0; ++- ++-err_register_chain: ++- nft_unregister_afinfo(&nft_af_ipv6); ++- return ret; +++ return nft_register_chain_type(&filter_ipv6); ++ } ++ ++ static void __exit nf_tables_ipv6_exit(void) ++ { ++- nft_unregister_afinfo(&nft_af_ipv6); ++ nft_unregister_chain_type(&filter_ipv6); ++ } ++ ++@@ -82,4 +62,4 @@ module_exit(nf_tables_ipv6_exit); ++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Patrick McHardy "); ++-MODULE_ALIAS_NFT_FAMILY(AF_INET6); +++MODULE_ALIAS_NFT_CHAIN(AF_INET6, "filter"); ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -26,71 +26,6 @@ ++ static LIST_HEAD(nf_tables_expressions); ++ static LIST_HEAD(nf_tables_objects); ++ static LIST_HEAD(nf_tables_flowtables); ++-static LIST_HEAD(nf_tables_af_info); ++- ++-/** ++- * nft_register_afinfo - register nf_tables address family info ++- * ++- * @afi: address family info to register ++- * ++- * Register the address family for use with nf_tables. Returns zero on ++- * success or a negative errno code otherwise. ++- */ ++-int nft_register_afinfo(struct nft_af_info *afi) ++-{ ++- nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- list_add_tail_rcu(&afi->list, &nf_tables_af_info); ++- nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++- return 0; ++-} ++-EXPORT_SYMBOL_GPL(nft_register_afinfo); ++- ++-/** ++- * nft_unregister_afinfo - unregister nf_tables address family info ++- * ++- * @afi: address family info to unregister ++- * ++- * Unregister the address family for use with nf_tables. ++- */ ++-void nft_unregister_afinfo(struct nft_af_info *afi) ++-{ ++- nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- list_del_rcu(&afi->list); ++- nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++-} ++-EXPORT_SYMBOL_GPL(nft_unregister_afinfo); ++- ++-static struct nft_af_info *nft_afinfo_lookup(struct net *net, int family) ++-{ ++- struct nft_af_info *afi; ++- ++- list_for_each_entry(afi, &nf_tables_af_info, list) { ++- if (afi->family == family) ++- return afi; ++- } ++- return NULL; ++-} ++- ++-static struct nft_af_info * ++-nf_tables_afinfo_lookup(struct net *net, int family, bool autoload) ++-{ ++- struct nft_af_info *afi; ++- ++- afi = nft_afinfo_lookup(net, family); ++- if (afi != NULL) ++- return afi; ++-#ifdef CONFIG_MODULES ++- if (autoload) { ++- nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++- request_module("nft-afinfo-%u", family); ++- nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- afi = nft_afinfo_lookup(net, family); ++- if (afi != NULL) ++- return ERR_PTR(-EAGAIN); ++- } ++-#endif ++- return ERR_PTR(-EAFNOSUPPORT); ++-} ++ ++ static void nft_ctx_init(struct nft_ctx *ctx, ++ struct net *net, ++@@ -434,7 +369,7 @@ static struct nft_table *nft_table_looku ++ ++ list_for_each_entry(table, &net->nft.tables, list) { ++ if (!nla_strcmp(nla, table->name) && ++- table->afi->family == family && +++ table->family == family && ++ nft_active_genmask(table, genmask)) ++ return table; ++ } ++@@ -575,7 +510,7 @@ static int nf_tables_dump_tables(struct ++ cb->seq = net->nft.base_seq; ++ ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++- if (family != NFPROTO_UNSPEC && family != table->afi->family) +++ if (family != NFPROTO_UNSPEC && family != table->family) ++ continue; ++ ++ if (idx < s_idx) ++@@ -589,7 +524,7 @@ static int nf_tables_dump_tables(struct ++ NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWTABLE, NLM_F_MULTI, ++- table->afi->family, table) < 0) +++ table->family, table) < 0) ++ goto done; ++ ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++@@ -609,7 +544,6 @@ static int nf_tables_gettable(struct net ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_cur(net); ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ struct sk_buff *skb2; ++ int family = nfmsg->nfgen_family; ++@@ -622,11 +556,7 @@ static int nf_tables_gettable(struct net ++ return netlink_dump_start(nlsk, skb, nlh, &c); ++ } ++ ++- afi = nf_tables_afinfo_lookup(net, family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -746,19 +676,14 @@ static int nf_tables_newtable(struct net ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_next(net); ++ const struct nlattr *name; ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ int family = nfmsg->nfgen_family; ++ u32 flags = 0; ++ struct nft_ctx ctx; ++ int err; ++ ++- afi = nf_tables_afinfo_lookup(net, family, true); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++ name = nla[NFTA_TABLE_NAME]; ++- table = nf_tables_table_lookup(net, name, afi->family, genmask); +++ table = nf_tables_table_lookup(net, name, family, genmask); ++ if (IS_ERR(table)) { ++ if (PTR_ERR(table) != -ENOENT) ++ return PTR_ERR(table); ++@@ -768,7 +693,7 @@ static int nf_tables_newtable(struct net ++ if (nlh->nlmsg_flags & NLM_F_REPLACE) ++ return -EOPNOTSUPP; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); ++ return nf_tables_updtable(&ctx); ++ } ++ ++@@ -778,40 +703,34 @@ static int nf_tables_newtable(struct net ++ return -EINVAL; ++ } ++ ++- err = -EAFNOSUPPORT; ++- if (!try_module_get(afi->owner)) ++- goto err1; ++- ++ err = -ENOMEM; ++ table = kzalloc(sizeof(*table), GFP_KERNEL); ++ if (table == NULL) ++- goto err2; +++ goto err_kzalloc; ++ ++ table->name = nla_strdup(name, GFP_KERNEL); ++ if (table->name == NULL) ++- goto err3; +++ goto err_strdup; ++ ++ INIT_LIST_HEAD(&table->chains); ++ INIT_LIST_HEAD(&table->sets); ++ INIT_LIST_HEAD(&table->objects); ++ INIT_LIST_HEAD(&table->flowtables); ++- table->afi = afi; +++ table->family = family; ++ table->flags = flags; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); ++ err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); ++ if (err < 0) ++- goto err4; +++ goto err_trans; ++ ++ list_add_tail_rcu(&table->list, &net->nft.tables); ++ return 0; ++-err4: +++err_trans: ++ kfree(table->name); ++-err3: +++err_strdup: ++ kfree(table); ++-err2: ++- module_put(afi->owner); ++-err1: +++err_kzalloc: ++ return err; ++ } ++ ++@@ -882,10 +801,10 @@ static int nft_flush(struct nft_ctx *ctx ++ int err = 0; ++ ++ list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) { ++- if (family != AF_UNSPEC && table->afi->family != family) +++ if (family != AF_UNSPEC && table->family != family) ++ continue; ++ ++- ctx->family = table->afi->family; +++ ctx->family = table->family; ++ ++ if (!nft_is_active_next(ctx->net, table)) ++ continue; ++@@ -911,7 +830,6 @@ static int nf_tables_deltable(struct net ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_next(net); ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ int family = nfmsg->nfgen_family; ++ struct nft_ctx ctx; ++@@ -920,11 +838,7 @@ static int nf_tables_deltable(struct net ++ if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) ++ return nft_flush(&ctx, family); ++ ++- afi = nf_tables_afinfo_lookup(net, family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -933,7 +847,7 @@ static int nf_tables_deltable(struct net ++ table->use > 0) ++ return -EBUSY; ++ ++- ctx.family = afi->family; +++ ctx.family = family; ++ ctx.table = table; ++ ++ return nft_flush_table(&ctx); ++@@ -945,7 +859,6 @@ static void nf_tables_table_destroy(stru ++ ++ kfree(ctx->table->name); ++ kfree(ctx->table); ++- module_put(ctx->table->afi->owner); ++ } ++ ++ int nft_register_chain_type(const struct nf_chain_type *ctype) ++@@ -1174,7 +1087,7 @@ static int nf_tables_dump_chains(struct ++ cb->seq = net->nft.base_seq; ++ ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++- if (family != NFPROTO_UNSPEC && family != table->afi->family) +++ if (family != NFPROTO_UNSPEC && family != table->family) ++ continue; ++ ++ list_for_each_entry_rcu(chain, &table->chains, list) { ++@@ -1190,7 +1103,7 @@ static int nf_tables_dump_chains(struct ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWCHAIN, ++ NLM_F_MULTI, ++- table->afi->family, table, +++ table->family, table, ++ chain) < 0) ++ goto done; ++ ++@@ -1212,7 +1125,6 @@ static int nf_tables_getchain(struct net ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_cur(net); ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ const struct nft_chain *chain; ++ struct sk_buff *skb2; ++@@ -1226,11 +1138,7 @@ static int nf_tables_getchain(struct net ++ return netlink_dump_start(nlsk, skb, nlh, &c); ++ } ++ ++- afi = nf_tables_afinfo_lookup(net, family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -1612,7 +1520,6 @@ static int nf_tables_newchain(struct net ++ const struct nlattr * uninitialized_var(name); ++ u8 genmask = nft_genmask_next(net); ++ int family = nfmsg->nfgen_family; ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_chain *chain; ++ u8 policy = NF_ACCEPT; ++@@ -1622,11 +1529,7 @@ static int nf_tables_newchain(struct net ++ ++ create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; ++ ++- afi = nf_tables_afinfo_lookup(net, family, true); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -1667,7 +1570,7 @@ static int nf_tables_newchain(struct net ++ } ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); ++ ++ if (chain != NULL) { ++ if (nlh->nlmsg_flags & NLM_F_EXCL) ++@@ -1688,7 +1591,6 @@ static int nf_tables_delchain(struct net ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_next(net); ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_chain *chain; ++ struct nft_rule *rule; ++@@ -1697,11 +1599,7 @@ static int nf_tables_delchain(struct net ++ u32 use; ++ int err; ++ ++- afi = nf_tables_afinfo_lookup(net, family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -1714,7 +1612,7 @@ static int nf_tables_delchain(struct net ++ chain->use > 0) ++ return -EBUSY; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); ++ ++ use = chain->use; ++ list_for_each_entry(rule, &chain->rules, list) { ++@@ -2145,7 +2043,7 @@ static int nf_tables_dump_rules(struct s ++ cb->seq = net->nft.base_seq; ++ ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++- if (family != NFPROTO_UNSPEC && family != table->afi->family) +++ if (family != NFPROTO_UNSPEC && family != table->family) ++ continue; ++ ++ if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0) ++@@ -2168,7 +2066,7 @@ static int nf_tables_dump_rules(struct s ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWRULE, ++ NLM_F_MULTI | NLM_F_APPEND, ++- table->afi->family, +++ table->family, ++ table, chain, rule) < 0) ++ goto done; ++ ++@@ -2204,7 +2102,6 @@ static int nf_tables_getrule(struct net ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_cur(net); ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ const struct nft_chain *chain; ++ const struct nft_rule *rule; ++@@ -2248,11 +2145,7 @@ static int nf_tables_getrule(struct net ++ return netlink_dump_start(nlsk, skb, nlh, &c); ++ } ++ ++- afi = nf_tables_afinfo_lookup(net, family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -2318,7 +2211,7 @@ static int nf_tables_newrule(struct net ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_next(net); ++- struct nft_af_info *afi; +++ int family = nfmsg->nfgen_family; ++ struct nft_table *table; ++ struct nft_chain *chain; ++ struct nft_rule *rule, *old_rule = NULL; ++@@ -2334,11 +2227,7 @@ static int nf_tables_newrule(struct net ++ ++ create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; ++ ++- afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -2378,7 +2267,7 @@ static int nf_tables_newrule(struct net ++ return PTR_ERR(old_rule); ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); ++ ++ n = 0; ++ size = 0; ++@@ -2500,18 +2389,13 @@ static int nf_tables_delrule(struct net ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_next(net); ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_chain *chain = NULL; ++ struct nft_rule *rule; ++ int family = nfmsg->nfgen_family, err = 0; ++ struct nft_ctx ctx; ++ ++- afi = nf_tables_afinfo_lookup(net, family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -2523,7 +2407,7 @@ static int nf_tables_delrule(struct net ++ return PTR_ERR(chain); ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); ++ ++ if (chain) { ++ if (nla[NFTA_RULE_HANDLE]) { ++@@ -2708,26 +2592,17 @@ static int nft_ctx_init_from_setattr(str ++ u8 genmask) ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++- struct nft_af_info *afi = NULL; +++ int family = nfmsg->nfgen_family; ++ struct nft_table *table = NULL; ++ ++- if (nfmsg->nfgen_family != NFPROTO_UNSPEC) { ++- afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- } ++- ++ if (nla[NFTA_SET_TABLE] != NULL) { ++- if (afi == NULL) ++- return -EAFNOSUPPORT; ++- ++ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], ++- afi->family, genmask); +++ family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ } ++ ++- nft_ctx_init(ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla); ++ return 0; ++ } ++ ++@@ -2959,7 +2834,7 @@ static int nf_tables_dump_sets(struct sk ++ ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (ctx->family != NFPROTO_UNSPEC && ++- ctx->family != table->afi->family) +++ ctx->family != table->family) ++ continue; ++ ++ if (ctx->table && ctx->table != table) ++@@ -2980,7 +2855,7 @@ static int nf_tables_dump_sets(struct sk ++ ++ ctx_set = *ctx; ++ ctx_set.table = table; ++- ctx_set.family = table->afi->family; +++ ctx_set.family = table->family; ++ ++ if (nf_tables_fill_set(skb, &ctx_set, set, ++ NFT_MSG_NEWSET, ++@@ -3092,8 +2967,8 @@ static int nf_tables_newset(struct net * ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_next(net); +++ int family = nfmsg->nfgen_family; ++ const struct nft_set_ops *ops; ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_set *set; ++ struct nft_ctx ctx; ++@@ -3203,16 +3078,12 @@ static int nf_tables_newset(struct net * ++ ++ create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; ++ ++- afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); ++ ++ set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask); ++ if (IS_ERR(set)) { ++@@ -3474,19 +3345,15 @@ static int nft_ctx_init_from_elemattr(st ++ u8 genmask) ++ { ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++- struct nft_af_info *afi; +++ int family = nfmsg->nfgen_family; ++ struct nft_table *table; ++ ++- afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++ table = nf_tables_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], ++- afi->family, genmask); +++ family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++- nft_ctx_init(ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla); ++ return 0; ++ } ++ ++@@ -3604,7 +3471,7 @@ static int nf_tables_dump_set(struct sk_ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (dump_ctx->ctx.family != NFPROTO_UNSPEC && ++- dump_ctx->ctx.family != table->afi->family) +++ dump_ctx->ctx.family != table->family) ++ continue; ++ ++ if (table != dump_ctx->ctx.table) ++@@ -3634,7 +3501,7 @@ static int nf_tables_dump_set(struct sk_ ++ goto nla_put_failure; ++ ++ nfmsg = nlmsg_data(nlh); ++- nfmsg->nfgen_family = table->afi->family; +++ nfmsg->nfgen_family = table->family; ++ nfmsg->version = NFNETLINK_V0; ++ nfmsg->res_id = htons(net->nft.base_seq & 0xffff); ++ ++@@ -4522,7 +4389,6 @@ static int nf_tables_newobj(struct net * ++ const struct nft_object_type *type; ++ u8 genmask = nft_genmask_next(net); ++ int family = nfmsg->nfgen_family; ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_object *obj; ++ struct nft_ctx ctx; ++@@ -4534,11 +4400,7 @@ static int nf_tables_newobj(struct net * ++ !nla[NFTA_OBJ_DATA]) ++ return -EINVAL; ++ ++- afi = nf_tables_afinfo_lookup(net, family, true); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -4557,7 +4419,7 @@ static int nf_tables_newobj(struct net * ++ return 0; ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); ++ ++ type = nft_obj_type_get(objtype); ++ if (IS_ERR(type)) ++@@ -4649,7 +4511,7 @@ static int nf_tables_dump_obj(struct sk_ ++ cb->seq = net->nft.base_seq; ++ ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++- if (family != NFPROTO_UNSPEC && family != table->afi->family) +++ if (family != NFPROTO_UNSPEC && family != table->family) ++ continue; ++ ++ list_for_each_entry_rcu(obj, &table->objects, list) { ++@@ -4672,7 +4534,7 @@ static int nf_tables_dump_obj(struct sk_ ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWOBJ, ++ NLM_F_MULTI | NLM_F_APPEND, ++- table->afi->family, table, +++ table->family, table, ++ obj, reset) < 0) ++ goto done; ++ ++@@ -4730,7 +4592,6 @@ static int nf_tables_getobj(struct net * ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_cur(net); ++ int family = nfmsg->nfgen_family; ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ struct nft_object *obj; ++ struct sk_buff *skb2; ++@@ -4761,11 +4622,7 @@ static int nf_tables_getobj(struct net * ++ !nla[NFTA_OBJ_TYPE]) ++ return -EINVAL; ++ ++- afi = nf_tables_afinfo_lookup(net, family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -4812,7 +4669,6 @@ static int nf_tables_delobj(struct net * ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_next(net); ++ int family = nfmsg->nfgen_family; ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_object *obj; ++ struct nft_ctx ctx; ++@@ -4822,11 +4678,7 @@ static int nf_tables_delobj(struct net * ++ !nla[NFTA_OBJ_NAME]) ++ return -EINVAL; ++ ++- afi = nf_tables_afinfo_lookup(net, family, true); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++- table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, +++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++@@ -4838,7 +4690,7 @@ static int nf_tables_delobj(struct net * ++ if (obj->use > 0) ++ return -EBUSY; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); ++ ++ return nft_delobj(&ctx, obj); ++ } ++@@ -5023,33 +4875,31 @@ err1: ++ return err; ++ } ++ ++-static const struct nf_flowtable_type * ++-__nft_flowtable_type_get(const struct nft_af_info *afi) +++static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family) ++ { ++ const struct nf_flowtable_type *type; ++ ++ list_for_each_entry(type, &nf_tables_flowtables, list) { ++- if (afi->family == type->family) +++ if (family == type->family) ++ return type; ++ } ++ return NULL; ++ } ++ ++-static const struct nf_flowtable_type * ++-nft_flowtable_type_get(const struct nft_af_info *afi) +++static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family) ++ { ++ const struct nf_flowtable_type *type; ++ ++- type = __nft_flowtable_type_get(afi); +++ type = __nft_flowtable_type_get(family); ++ if (type != NULL && try_module_get(type->owner)) ++ return type; ++ ++ #ifdef CONFIG_MODULES ++ if (type == NULL) { ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++- request_module("nf-flowtable-%u", afi->family); +++ request_module("nf-flowtable-%u", family); ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- if (__nft_flowtable_type_get(afi)) +++ if (__nft_flowtable_type_get(family)) ++ return ERR_PTR(-EAGAIN); ++ } ++ #endif ++@@ -5097,7 +4947,6 @@ static int nf_tables_newflowtable(struct ++ u8 genmask = nft_genmask_next(net); ++ int family = nfmsg->nfgen_family; ++ struct nft_flowtable *flowtable; ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_ctx ctx; ++ int err, i, k; ++@@ -5107,12 +4956,8 @@ static int nf_tables_newflowtable(struct ++ !nla[NFTA_FLOWTABLE_HOOK]) ++ return -EINVAL; ++ ++- afi = nf_tables_afinfo_lookup(net, family, true); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], ++- afi->family, genmask); +++ family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -5129,7 +4974,7 @@ static int nf_tables_newflowtable(struct ++ return 0; ++ } ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); ++ ++ flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL); ++ if (!flowtable) ++@@ -5142,7 +4987,7 @@ static int nf_tables_newflowtable(struct ++ goto err1; ++ } ++ ++- type = nft_flowtable_type_get(afi); +++ type = nft_flowtable_type_get(family); ++ if (IS_ERR(type)) { ++ err = PTR_ERR(type); ++ goto err2; ++@@ -5202,16 +5047,11 @@ static int nf_tables_delflowtable(struct ++ u8 genmask = nft_genmask_next(net); ++ int family = nfmsg->nfgen_family; ++ struct nft_flowtable *flowtable; ++- struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_ctx ctx; ++ ++- afi = nf_tables_afinfo_lookup(net, family, true); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], ++- afi->family, genmask); +++ family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -5222,7 +5062,7 @@ static int nf_tables_delflowtable(struct ++ if (flowtable->use > 0) ++ return -EBUSY; ++ ++- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); +++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); ++ ++ return nft_delflowtable(&ctx, flowtable); ++ } ++@@ -5297,7 +5137,7 @@ static int nf_tables_dump_flowtable(stru ++ cb->seq = net->nft.base_seq; ++ ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++- if (family != NFPROTO_UNSPEC && family != table->afi->family) +++ if (family != NFPROTO_UNSPEC && family != table->family) ++ continue; ++ ++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++@@ -5316,7 +5156,7 @@ static int nf_tables_dump_flowtable(stru ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWFLOWTABLE, ++ NLM_F_MULTI | NLM_F_APPEND, ++- table->afi->family, flowtable) < 0) +++ table->family, flowtable) < 0) ++ goto done; ++ ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++@@ -5376,7 +5216,6 @@ static int nf_tables_getflowtable(struct ++ u8 genmask = nft_genmask_cur(net); ++ int family = nfmsg->nfgen_family; ++ struct nft_flowtable *flowtable; ++- const struct nft_af_info *afi; ++ const struct nft_table *table; ++ struct sk_buff *skb2; ++ int err; ++@@ -5402,12 +5241,8 @@ static int nf_tables_getflowtable(struct ++ if (!nla[NFTA_FLOWTABLE_NAME]) ++ return -EINVAL; ++ ++- afi = nf_tables_afinfo_lookup(net, family, false); ++- if (IS_ERR(afi)) ++- return PTR_ERR(afi); ++- ++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], ++- afi->family, genmask); +++ family, genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -6578,7 +6413,7 @@ int __nft_release_basechain(struct nft_c ++ } ++ EXPORT_SYMBOL_GPL(__nft_release_basechain); ++ ++-static void __nft_release_afinfo(struct net *net) +++static void __nft_release_tables(struct net *net) ++ { ++ struct nft_flowtable *flowtable, *nf; ++ struct nft_table *table, *nt; ++@@ -6591,7 +6426,7 @@ static void __nft_release_afinfo(struct ++ }; ++ ++ list_for_each_entry_safe(table, nt, &net->nft.tables, list) { ++- ctx.family = table->afi->family; +++ ctx.family = table->family; ++ ++ list_for_each_entry(chain, &table->chains, list) ++ nf_tables_unregister_hook(net, table, chain); ++@@ -6643,7 +6478,7 @@ static int __net_init nf_tables_init_net ++ ++ static void __net_exit nf_tables_exit_net(struct net *net) ++ { ++- __nft_release_afinfo(net); +++ __nft_release_tables(net); ++ WARN_ON_ONCE(!list_empty(&net->nft.tables)); ++ WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); ++ } ++--- a/net/netfilter/nf_tables_inet.c +++++ b/net/netfilter/nf_tables_inet.c ++@@ -38,11 +38,6 @@ static unsigned int nft_do_chain_inet(vo ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static struct nft_af_info nft_af_inet __read_mostly = { ++- .family = NFPROTO_INET, ++- .owner = THIS_MODULE, ++-}; ++- ++ static const struct nf_chain_type filter_inet = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -64,26 +59,12 @@ static const struct nf_chain_type filter ++ ++ static int __init nf_tables_inet_init(void) ++ { ++- int ret; ++- ++- if (nft_register_afinfo(&nft_af_inet) < 0) ++- return ret; ++- ++- ret = nft_register_chain_type(&filter_inet); ++- if (ret < 0) ++- goto err_register_chain; ++- ++- return ret; ++- ++-err_register_chain: ++- nft_unregister_afinfo(&nft_af_inet); ++- return ret; +++ return nft_register_chain_type(&filter_inet); ++ } ++ ++ static void __exit nf_tables_inet_exit(void) ++ { ++ nft_unregister_chain_type(&filter_inet); ++- nft_unregister_afinfo(&nft_af_inet); ++ } ++ ++ module_init(nf_tables_inet_init); ++@@ -91,4 +72,4 @@ module_exit(nf_tables_inet_exit); ++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Patrick McHardy "); ++-MODULE_ALIAS_NFT_FAMILY(1); +++MODULE_ALIAS_NFT_CHAIN(1, "filter"); ++--- a/net/netfilter/nf_tables_netdev.c +++++ b/net/netfilter/nf_tables_netdev.c ++@@ -38,11 +38,6 @@ nft_do_chain_netdev(void *priv, struct s ++ return nft_do_chain(&pkt, priv); ++ } ++ ++-static struct nft_af_info nft_af_netdev __read_mostly = { ++- .family = NFPROTO_NETDEV, ++- .owner = THIS_MODULE, ++-}; ++- ++ static const struct nf_chain_type nft_filter_chain_netdev = { ++ .name = "filter", ++ .type = NFT_CHAIN_T_DEFAULT, ++@@ -91,10 +86,10 @@ static int nf_tables_netdev_event(struct ++ ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++ list_for_each_entry(table, &ctx.net->nft.tables, list) { ++- if (table->afi->family != NFPROTO_NETDEV) +++ if (table->family != NFPROTO_NETDEV) ++ continue; ++ ++- ctx.family = table->afi->family; +++ ctx.family = table->family; ++ ctx.table = table; ++ list_for_each_entry_safe(chain, nr, &table->chains, list) { ++ if (!nft_is_base_chain(chain)) ++@@ -117,12 +112,9 @@ static int __init nf_tables_netdev_init( ++ { ++ int ret; ++ ++- if (nft_register_afinfo(&nft_af_netdev) < 0) ++- return ret; ++- ++ ret = nft_register_chain_type(&nft_filter_chain_netdev); ++ if (ret) ++- goto err_register_chain_type; +++ return ret; ++ ++ ret = register_netdevice_notifier(&nf_tables_netdev_notifier); ++ if (ret) ++@@ -132,8 +124,6 @@ static int __init nf_tables_netdev_init( ++ ++ err_register_netdevice_notifier: ++ nft_unregister_chain_type(&nft_filter_chain_netdev); ++-err_register_chain_type: ++- nft_unregister_afinfo(&nft_af_netdev); ++ ++ return ret; ++ } ++@@ -142,7 +132,6 @@ static void __exit nf_tables_netdev_exit ++ { ++ unregister_netdevice_notifier(&nf_tables_netdev_notifier); ++ nft_unregister_chain_type(&nft_filter_chain_netdev); ++- nft_unregister_afinfo(&nft_af_netdev); ++ } ++ ++ module_init(nf_tables_netdev_init); ++@@ -150,4 +139,4 @@ module_exit(nf_tables_netdev_exit); ++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Pablo Neira Ayuso "); ++-MODULE_ALIAS_NFT_FAMILY(5); /* NFPROTO_NETDEV */ +++MODULE_ALIAS_NFT_CHAIN(5, "filter"); /* NFPROTO_NETDEV */ +diff --git a/target/linux/generic/backport-4.14/339-v4.16-netfilter-nft_flow_offload-wait-for-garbage-collecto.patch b/target/linux/generic/backport-4.14/339-v4.16-netfilter-nft_flow_offload-wait-for-garbage-collecto.patch +new file mode 100644 +index 0000000000..5ae917ff51 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/339-v4.16-netfilter-nft_flow_offload-wait-for-garbage-collecto.patch +@@ -0,0 +1,47 @@ ++From: Pablo Neira Ayuso ++Date: Thu, 1 Feb 2018 18:49:00 +0100 ++Subject: [PATCH] netfilter: nft_flow_offload: wait for garbage collector ++ to run after cleanup ++ ++If netdevice goes down, then flowtable entries are scheduled to be ++removed. Wait for garbage collector to have a chance to run so it can ++delete them from the hashtable. ++ ++The flush call might sleep, so hold the nfnl mutex from ++nft_flow_table_iterate() instead of rcu read side lock. The use of the ++nfnl mutex is also implicitly fixing races between updates via nfnetlink ++and netdevice event. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -4913,13 +4913,13 @@ void nft_flow_table_iterate(struct net * ++ struct nft_flowtable *flowtable; ++ const struct nft_table *table; ++ ++- rcu_read_lock(); ++- list_for_each_entry_rcu(table, &net->nft.tables, list) { ++- list_for_each_entry_rcu(flowtable, &table->flowtables, list) { +++ nfnl_lock(NFNL_SUBSYS_NFTABLES); +++ list_for_each_entry(table, &net->nft.tables, list) { +++ list_for_each_entry(flowtable, &table->flowtables, list) { ++ iter(&flowtable->data, data); ++ } ++ } ++- rcu_read_unlock(); +++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++ } ++ EXPORT_SYMBOL_GPL(nft_flow_table_iterate); ++ ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -208,6 +208,7 @@ static void nft_flow_offload_iterate_cle ++ void *data) ++ { ++ nf_flow_table_iterate(flowtable, flow_offload_iterate_cleanup, data); +++ flush_delayed_work(&flowtable->gc_work); ++ } ++ ++ static int flow_offload_netdev_event(struct notifier_block *this, +diff --git a/target/linux/generic/backport-4.14/340-v4.16-netfilter-nft_flow_offload-no-need-to-flush-entries-.patch b/target/linux/generic/backport-4.14/340-v4.16-netfilter-nft_flow_offload-no-need-to-flush-entries-.patch +new file mode 100644 +index 0000000000..539550d542 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/340-v4.16-netfilter-nft_flow_offload-no-need-to-flush-entries-.patch +@@ -0,0 +1,29 @@ ++From: Pablo Neira Ayuso ++Date: Thu, 1 Feb 2018 18:49:01 +0100 ++Subject: [PATCH] netfilter: nft_flow_offload: no need to flush entries on ++ module removal ++ ++nft_flow_offload module removal does not require to flush existing ++flowtables, it is valid to remove this module while keeping flowtables ++around. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -247,14 +247,8 @@ register_expr: ++ ++ static void __exit nft_flow_offload_module_exit(void) ++ { ++- struct net *net; ++- ++ nft_unregister_expr(&nft_flow_offload_type); ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++- rtnl_lock(); ++- for_each_net(net) ++- nft_flow_table_iterate(net, nft_flow_offload_iterate_cleanup, NULL); ++- rtnl_unlock(); ++ } ++ ++ module_init(nft_flow_offload_module_init); +diff --git a/target/linux/generic/backport-4.14/341-v4.16-netfilter-nft_flow_offload-move-flowtable-cleanup-ro.patch b/target/linux/generic/backport-4.14/341-v4.16-netfilter-nft_flow_offload-move-flowtable-cleanup-ro.patch +new file mode 100644 +index 0000000000..9ee0ad5936 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/341-v4.16-netfilter-nft_flow_offload-move-flowtable-cleanup-ro.patch +@@ -0,0 +1,97 @@ ++From: Pablo Neira Ayuso ++Date: Tue, 23 Jan 2018 17:46:09 +0100 ++Subject: [PATCH] netfilter: nft_flow_offload: move flowtable cleanup ++ routines to nf_flow_table ++ ++Move the flowtable cleanup routines to nf_flow_table and expose the ++nf_flow_table_cleanup() helper function. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -95,6 +95,9 @@ struct flow_offload_tuple_rhash *flow_of ++ int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct flow_offload *flow, void *data), ++ void *data); +++ +++void nf_flow_table_cleanup(struct net *net, struct net_device *dev); +++ ++ void nf_flow_offload_work_gc(struct work_struct *work); ++ extern const struct rhashtable_params nf_flow_offload_rhash_params; ++ ++--- a/net/netfilter/nf_flow_table.c +++++ b/net/netfilter/nf_flow_table.c ++@@ -4,6 +4,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -425,5 +426,28 @@ int nf_flow_dnat_port(const struct flow_ ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_dnat_port); ++ +++static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) +++{ +++ struct net_device *dev = data; +++ +++ if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) +++ return; +++ +++ flow_offload_dead(flow); +++} +++ +++static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, +++ void *data) +++{ +++ nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, data); +++ flush_delayed_work(&flowtable->gc_work); +++} +++ +++void nf_flow_table_cleanup(struct net *net, struct net_device *dev) +++{ +++ nft_flow_table_iterate(net, nf_flow_table_iterate_cleanup, dev); +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); +++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Pablo Neira Ayuso "); ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -194,23 +194,6 @@ static struct nft_expr_type nft_flow_off ++ .owner = THIS_MODULE, ++ }; ++ ++-static void flow_offload_iterate_cleanup(struct flow_offload *flow, void *data) ++-{ ++- struct net_device *dev = data; ++- ++- if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) ++- return; ++- ++- flow_offload_dead(flow); ++-} ++- ++-static void nft_flow_offload_iterate_cleanup(struct nf_flowtable *flowtable, ++- void *data) ++-{ ++- nf_flow_table_iterate(flowtable, flow_offload_iterate_cleanup, data); ++- flush_delayed_work(&flowtable->gc_work); ++-} ++- ++ static int flow_offload_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++ { ++@@ -219,7 +202,7 @@ static int flow_offload_netdev_event(str ++ if (event != NETDEV_DOWN) ++ return NOTIFY_DONE; ++ ++- nft_flow_table_iterate(dev_net(dev), nft_flow_offload_iterate_cleanup, dev); +++ nf_flow_table_cleanup(dev_net(dev), dev); ++ ++ return NOTIFY_DONE; ++ } +diff --git a/target/linux/generic/backport-4.14/342-v4.16-netfilter-nf_tables-fix-flowtable-free.patch b/target/linux/generic/backport-4.14/342-v4.16-netfilter-nf_tables-fix-flowtable-free.patch +new file mode 100644 +index 0000000000..b8c85fc2a7 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/342-v4.16-netfilter-nf_tables-fix-flowtable-free.patch +@@ -0,0 +1,140 @@ ++From: Pablo Neira Ayuso ++Date: Mon, 5 Feb 2018 21:44:50 +0100 ++Subject: [PATCH] netfilter: nf_tables: fix flowtable free ++ ++Every flow_offload entry is added into the table twice. Because of this, ++rhashtable_free_and_destroy can't be used, since it would call kfree for ++each flow_offload object twice. ++ ++This patch adds a call to nf_flow_table_iterate_cleanup() to schedule ++removal of entries, then there is an explicitly invocation of the ++garbage collector to clean up resources. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -14,6 +14,7 @@ struct nf_flowtable_type { ++ struct list_head list; ++ int family; ++ void (*gc)(struct work_struct *work); +++ void (*free)(struct nf_flowtable *ft); ++ const struct rhashtable_params *params; ++ nf_hookfn *hook; ++ struct module *owner; ++@@ -98,6 +99,7 @@ int nf_flow_table_iterate(struct nf_flow ++ ++ void nf_flow_table_cleanup(struct net *net, struct net_device *dev); ++ +++void nf_flow_table_free(struct nf_flowtable *flow_table); ++ void nf_flow_offload_work_gc(struct work_struct *work); ++ extern const struct rhashtable_params nf_flow_offload_rhash_params; ++ ++--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c +++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c ++@@ -260,6 +260,7 @@ static struct nf_flowtable_type flowtabl ++ .family = NFPROTO_IPV4, ++ .params = &nf_flow_offload_rhash_params, ++ .gc = nf_flow_offload_work_gc, +++ .free = nf_flow_table_free, ++ .hook = nf_flow_offload_ip_hook, ++ .owner = THIS_MODULE, ++ }; ++--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c +++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c ++@@ -254,6 +254,7 @@ static struct nf_flowtable_type flowtabl ++ .family = NFPROTO_IPV6, ++ .params = &nf_flow_offload_rhash_params, ++ .gc = nf_flow_offload_work_gc, +++ .free = nf_flow_table_free, ++ .hook = nf_flow_offload_ipv6_hook, ++ .owner = THIS_MODULE, ++ }; ++--- a/net/netfilter/nf_flow_table.c +++++ b/net/netfilter/nf_flow_table.c ++@@ -232,19 +232,16 @@ static inline bool nf_flow_is_dying(cons ++ return flow->flags & FLOW_OFFLOAD_DYING; ++ } ++ ++-void nf_flow_offload_work_gc(struct work_struct *work) +++static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) ++ { ++ struct flow_offload_tuple_rhash *tuplehash; ++- struct nf_flowtable *flow_table; ++ struct rhashtable_iter hti; ++ struct flow_offload *flow; ++ int err; ++ ++- flow_table = container_of(work, struct nf_flowtable, gc_work.work); ++- ++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); ++ if (err) ++- goto schedule; +++ return 0; ++ ++ rhashtable_walk_start(&hti); ++ ++@@ -270,7 +267,16 @@ void nf_flow_offload_work_gc(struct work ++ out: ++ rhashtable_walk_stop(&hti); ++ rhashtable_walk_exit(&hti); ++-schedule: +++ +++ return 1; +++} +++ +++void nf_flow_offload_work_gc(struct work_struct *work) +++{ +++ struct nf_flowtable *flow_table; +++ +++ flow_table = container_of(work, struct nf_flowtable, gc_work.work); +++ nf_flow_offload_gc_step(flow_table); ++ queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); ++@@ -449,5 +455,12 @@ void nf_flow_table_cleanup(struct net *n ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); ++ +++void nf_flow_table_free(struct nf_flowtable *flow_table) +++{ +++ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); +++ WARN_ON(!nf_flow_offload_gc_step(flow_table)); +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_free); +++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Pablo Neira Ayuso "); ++--- a/net/netfilter/nf_flow_table_inet.c +++++ b/net/netfilter/nf_flow_table_inet.c ++@@ -24,6 +24,7 @@ static struct nf_flowtable_type flowtabl ++ .family = NFPROTO_INET, ++ .params = &nf_flow_offload_rhash_params, ++ .gc = nf_flow_offload_work_gc, +++ .free = nf_flow_table_free, ++ .hook = nf_flow_offload_inet_hook, ++ .owner = THIS_MODULE, ++ }; ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -5298,17 +5298,12 @@ err: ++ nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS); ++ } ++ ++-static void nft_flowtable_destroy(void *ptr, void *arg) ++-{ ++- kfree(ptr); ++-} ++- ++ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) ++ { ++ cancel_delayed_work_sync(&flowtable->data.gc_work); ++ kfree(flowtable->name); ++- rhashtable_free_and_destroy(&flowtable->data.rhashtable, ++- nft_flowtable_destroy, NULL); +++ flowtable->data.type->free(&flowtable->data); +++ rhashtable_destroy(&flowtable->data.rhashtable); ++ module_put(flowtable->data.type->owner); ++ } ++ +diff --git a/target/linux/generic/backport-4.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/backport-4.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +new file mode 100644 +index 0000000000..7f35cd7c60 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +@@ -0,0 +1,96 @@ ++From: Pablo Neira Ayuso ++Date: Thu, 25 Jan 2018 12:58:55 +0100 ++Subject: [PATCH] netfilter: nft_flow_offload: handle netdevice events from ++ nf_flow_table ++ ++Move the code that deals with device events to the core. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nf_flow_table.c +++++ b/net/netfilter/nf_flow_table.c ++@@ -462,5 +462,35 @@ void nf_flow_table_free(struct nf_flowta ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_table_free); ++ +++static int nf_flow_table_netdev_event(struct notifier_block *this, +++ unsigned long event, void *ptr) +++{ +++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); +++ +++ if (event != NETDEV_DOWN) +++ return NOTIFY_DONE; +++ +++ nf_flow_table_cleanup(dev_net(dev), dev); +++ +++ return NOTIFY_DONE; +++} +++ +++static struct notifier_block flow_offload_netdev_notifier = { +++ .notifier_call = nf_flow_table_netdev_event, +++}; +++ +++static int __init nf_flow_table_module_init(void) +++{ +++ return register_netdevice_notifier(&flow_offload_netdev_notifier); +++} +++ +++static void __exit nf_flow_table_module_exit(void) +++{ +++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); +++} +++ +++module_init(nf_flow_table_module_init); +++module_exit(nf_flow_table_module_exit); +++ ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("Pablo Neira Ayuso "); ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -194,44 +194,14 @@ static struct nft_expr_type nft_flow_off ++ .owner = THIS_MODULE, ++ }; ++ ++-static int flow_offload_netdev_event(struct notifier_block *this, ++- unsigned long event, void *ptr) ++-{ ++- struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++- ++- if (event != NETDEV_DOWN) ++- return NOTIFY_DONE; ++- ++- nf_flow_table_cleanup(dev_net(dev), dev); ++- ++- return NOTIFY_DONE; ++-} ++- ++-static struct notifier_block flow_offload_netdev_notifier = { ++- .notifier_call = flow_offload_netdev_event, ++-}; ++- ++ static int __init nft_flow_offload_module_init(void) ++ { ++- int err; ++- ++- register_netdevice_notifier(&flow_offload_netdev_notifier); ++- ++- err = nft_register_expr(&nft_flow_offload_type); ++- if (err < 0) ++- goto register_expr; ++- ++- return 0; ++- ++-register_expr: ++- unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++- return err; +++ return nft_register_expr(&nft_flow_offload_type); ++ } ++ ++ static void __exit nft_flow_offload_module_exit(void) ++ { ++ nft_unregister_expr(&nft_flow_offload_type); ++- unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++ } ++ ++ module_init(nft_flow_offload_module_init); +diff --git a/target/linux/generic/backport-4.14/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch b/target/linux/generic/backport-4.14/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch +new file mode 100644 +index 0000000000..e6c9fd2f74 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch +@@ -0,0 +1,468 @@ ++From: Harsha Sharma ++Date: Wed, 27 Dec 2017 00:59:00 +0530 ++Subject: [PATCH] netfilter: nf_tables: allocate handle and delete objects via ++ handle ++ ++This patch allows deletion of objects via unique handle which can be ++listed via '-a' option. ++ ++Signed-off-by: Harsha Sharma ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -370,6 +370,7 @@ void nft_unregister_set(struct nft_set_t ++ * @list: table set list node ++ * @bindings: list of set bindings ++ * @name: name of the set +++ * @handle: unique handle of the set ++ * @ktype: key type (numeric type defined by userspace, not used in the kernel) ++ * @dtype: data type (verdict or numeric type defined by userspace) ++ * @objtype: object type (see NFT_OBJECT_* definitions) ++@@ -392,6 +393,7 @@ struct nft_set { ++ struct list_head list; ++ struct list_head bindings; ++ char *name; +++ u64 handle; ++ u32 ktype; ++ u32 dtype; ++ u32 objtype; ++@@ -942,6 +944,7 @@ unsigned int nft_do_chain(struct nft_pkt ++ * @objects: stateful objects in the table ++ * @flowtables: flow tables in the table ++ * @hgenerator: handle generator state +++ * @handle: table handle ++ * @use: number of chain references to this table ++ * @flags: table flag (see enum nft_table_flags) ++ * @genmask: generation mask ++@@ -955,6 +958,7 @@ struct nft_table { ++ struct list_head objects; ++ struct list_head flowtables; ++ u64 hgenerator; +++ u64 handle; ++ u32 use; ++ u16 family:6, ++ flags:8, ++@@ -979,9 +983,9 @@ int nft_verdict_dump(struct sk_buff *skb ++ * @name: name of this stateful object ++ * @genmask: generation mask ++ * @use: number of references to this stateful object ++- * @data: object data, layout depends on type +++ * @handle: unique object handle ++ * @ops: object operations ++- * @data: pointer to object data +++ * @data: object data, layout depends on type ++ */ ++ struct nft_object { ++ struct list_head list; ++@@ -989,6 +993,7 @@ struct nft_object { ++ struct nft_table *table; ++ u32 genmask:2, ++ use:30; +++ u64 handle; ++ /* runtime data below here */ ++ const struct nft_object_ops *ops ____cacheline_aligned; ++ unsigned char data[] ++@@ -1070,6 +1075,7 @@ void nft_unregister_obj(struct nft_objec ++ * @ops_len: number of hooks in array ++ * @genmask: generation mask ++ * @use: number of references to this flow table +++ * @handle: unique object handle ++ * @data: rhashtable and garbage collector ++ * @ops: array of hooks ++ */ ++@@ -1082,6 +1088,7 @@ struct nft_flowtable { ++ int ops_len; ++ u32 genmask:2, ++ use:30; +++ u64 handle; ++ /* runtime data below here */ ++ struct nf_hook_ops *ops ____cacheline_aligned; ++ struct nf_flowtable data; ++--- a/include/uapi/linux/netfilter/nf_tables.h +++++ b/include/uapi/linux/netfilter/nf_tables.h ++@@ -174,6 +174,8 @@ enum nft_table_attributes { ++ NFTA_TABLE_NAME, ++ NFTA_TABLE_FLAGS, ++ NFTA_TABLE_USE, +++ NFTA_TABLE_HANDLE, +++ NFTA_TABLE_PAD, ++ __NFTA_TABLE_MAX ++ }; ++ #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1) ++@@ -317,6 +319,7 @@ enum nft_set_desc_attributes { ++ * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) ++ * @NFTA_SET_USERDATA: user data (NLA_BINARY) ++ * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) +++ * @NFTA_SET_HANDLE: set handle (NLA_U64) ++ */ ++ enum nft_set_attributes { ++ NFTA_SET_UNSPEC, ++@@ -335,6 +338,7 @@ enum nft_set_attributes { ++ NFTA_SET_USERDATA, ++ NFTA_SET_PAD, ++ NFTA_SET_OBJ_TYPE, +++ NFTA_SET_HANDLE, ++ __NFTA_SET_MAX ++ }; ++ #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) ++@@ -1314,6 +1318,7 @@ enum nft_ct_helper_attributes { ++ * @NFTA_OBJ_TYPE: stateful object type (NLA_U32) ++ * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) ++ * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) +++ * @NFTA_OBJ_HANDLE: object handle (NLA_U64) ++ */ ++ enum nft_object_attributes { ++ NFTA_OBJ_UNSPEC, ++@@ -1322,6 +1327,8 @@ enum nft_object_attributes { ++ NFTA_OBJ_TYPE, ++ NFTA_OBJ_DATA, ++ NFTA_OBJ_USE, +++ NFTA_OBJ_HANDLE, +++ NFTA_OBJ_PAD, ++ __NFTA_OBJ_MAX ++ }; ++ #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) ++@@ -1333,6 +1340,7 @@ enum nft_object_attributes { ++ * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) ++ * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) ++ * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) +++ * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) ++ */ ++ enum nft_flowtable_attributes { ++ NFTA_FLOWTABLE_UNSPEC, ++@@ -1340,6 +1348,8 @@ enum nft_flowtable_attributes { ++ NFTA_FLOWTABLE_NAME, ++ NFTA_FLOWTABLE_HOOK, ++ NFTA_FLOWTABLE_USE, +++ NFTA_FLOWTABLE_HANDLE, +++ NFTA_FLOWTABLE_PAD, ++ __NFTA_FLOWTABLE_MAX ++ }; ++ #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -26,6 +26,7 @@ ++ static LIST_HEAD(nf_tables_expressions); ++ static LIST_HEAD(nf_tables_objects); ++ static LIST_HEAD(nf_tables_flowtables); +++static u64 table_handle; ++ ++ static void nft_ctx_init(struct nft_ctx *ctx, ++ struct net *net, ++@@ -376,6 +377,20 @@ static struct nft_table *nft_table_looku ++ return NULL; ++ } ++ +++static struct nft_table *nft_table_lookup_byhandle(const struct net *net, +++ const struct nlattr *nla, +++ u8 genmask) +++{ +++ struct nft_table *table; +++ +++ list_for_each_entry(table, &net->nft.tables, list) { +++ if (be64_to_cpu(nla_get_be64(nla)) == table->handle && +++ nft_active_genmask(table, genmask)) +++ return table; +++ } +++ return NULL; +++} +++ ++ static struct nft_table *nf_tables_table_lookup(const struct net *net, ++ const struct nlattr *nla, ++ u8 family, u8 genmask) ++@@ -392,6 +407,22 @@ static struct nft_table *nf_tables_table ++ return ERR_PTR(-ENOENT); ++ } ++ +++static struct nft_table *nf_tables_table_lookup_byhandle(const struct net *net, +++ const struct nlattr *nla, +++ u8 genmask) +++{ +++ struct nft_table *table; +++ +++ if (nla == NULL) +++ return ERR_PTR(-EINVAL); +++ +++ table = nft_table_lookup_byhandle(net, nla, genmask); +++ if (table != NULL) +++ return table; +++ +++ return ERR_PTR(-ENOENT); +++} +++ ++ static inline u64 nf_tables_alloc_handle(struct nft_table *table) ++ { ++ return ++table->hgenerator; ++@@ -438,6 +469,7 @@ static const struct nla_policy nft_table ++ [NFTA_TABLE_NAME] = { .type = NLA_STRING, ++ .len = NFT_TABLE_MAXNAMELEN - 1 }, ++ [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, +++ [NFTA_TABLE_HANDLE] = { .type = NLA_U64 }, ++ }; ++ ++ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, ++@@ -459,7 +491,9 @@ static int nf_tables_fill_table_info(str ++ ++ if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || ++ nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || ++- nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use))) +++ nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) || +++ nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle), +++ NFTA_TABLE_PAD)) ++ goto nla_put_failure; ++ ++ nlmsg_end(skb, nlh); ++@@ -718,6 +752,7 @@ static int nf_tables_newtable(struct net ++ INIT_LIST_HEAD(&table->flowtables); ++ table->family = family; ++ table->flags = flags; +++ table->handle = ++table_handle; ++ ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); ++ err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); ++@@ -835,11 +870,18 @@ static int nf_tables_deltable(struct net ++ struct nft_ctx ctx; ++ ++ nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); ++- if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) +++ if (family == AF_UNSPEC || +++ (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE])) ++ return nft_flush(&ctx, family); ++ ++- table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, ++- genmask); +++ if (nla[NFTA_TABLE_HANDLE]) +++ table = nf_tables_table_lookup_byhandle(net, +++ nla[NFTA_TABLE_HANDLE], +++ genmask); +++ else +++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], +++ family, genmask); +++ ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++@@ -1596,6 +1638,7 @@ static int nf_tables_delchain(struct net ++ struct nft_rule *rule; ++ int family = nfmsg->nfgen_family; ++ struct nft_ctx ctx; +++ u64 handle; ++ u32 use; ++ int err; ++ ++@@ -1604,7 +1647,12 @@ static int nf_tables_delchain(struct net ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++- chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); +++ if (nla[NFTA_CHAIN_HANDLE]) { +++ handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); +++ chain = nf_tables_chain_lookup_byhandle(table, handle, genmask); +++ } else { +++ chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); +++ } ++ if (IS_ERR(chain)) ++ return PTR_ERR(chain); ++ ++@@ -2579,6 +2627,7 @@ static const struct nla_policy nft_set_p ++ [NFTA_SET_USERDATA] = { .type = NLA_BINARY, ++ .len = NFT_USERDATA_MAXLEN }, ++ [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 }, +++ [NFTA_SET_HANDLE] = { .type = NLA_U64 }, ++ }; ++ ++ static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { ++@@ -2622,6 +2671,22 @@ static struct nft_set *nf_tables_set_loo ++ return ERR_PTR(-ENOENT); ++ } ++ +++static struct nft_set *nf_tables_set_lookup_byhandle(const struct nft_table *table, +++ const struct nlattr *nla, u8 genmask) +++{ +++ struct nft_set *set; +++ +++ if (nla == NULL) +++ return ERR_PTR(-EINVAL); +++ +++ list_for_each_entry(set, &table->sets, list) { +++ if (be64_to_cpu(nla_get_be64(nla)) == set->handle && +++ nft_active_genmask(set, genmask)) +++ return set; +++ } +++ return ERR_PTR(-ENOENT); +++} +++ ++ static struct nft_set *nf_tables_set_lookup_byid(const struct net *net, ++ const struct nlattr *nla, ++ u8 genmask) ++@@ -2738,6 +2803,9 @@ static int nf_tables_fill_set(struct sk_ ++ goto nla_put_failure; ++ if (nla_put_string(skb, NFTA_SET_NAME, set->name)) ++ goto nla_put_failure; +++ if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle), +++ NFTA_SET_PAD)) +++ goto nla_put_failure; ++ if (set->flags != 0) ++ if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags))) ++ goto nla_put_failure; ++@@ -3149,6 +3217,7 @@ static int nf_tables_newset(struct net * ++ set->udata = udata; ++ set->timeout = timeout; ++ set->gc_int = gc_int; +++ set->handle = nf_tables_alloc_handle(table); ++ ++ err = ops->init(set, &desc, nla); ++ if (err < 0) ++@@ -3208,7 +3277,10 @@ static int nf_tables_delset(struct net * ++ if (err < 0) ++ return err; ++ ++- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); +++ if (nla[NFTA_SET_HANDLE]) +++ set = nf_tables_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], genmask); +++ else +++ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); ++ if (IS_ERR(set)) ++ return PTR_ERR(set); ++ ++@@ -4277,6 +4349,21 @@ struct nft_object *nf_tables_obj_lookup( ++ } ++ EXPORT_SYMBOL_GPL(nf_tables_obj_lookup); ++ +++struct nft_object *nf_tables_obj_lookup_byhandle(const struct nft_table *table, +++ const struct nlattr *nla, +++ u32 objtype, u8 genmask) +++{ +++ struct nft_object *obj; +++ +++ list_for_each_entry(obj, &table->objects, list) { +++ if (be64_to_cpu(nla_get_be64(nla)) == obj->handle && +++ objtype == obj->ops->type->type && +++ nft_active_genmask(obj, genmask)) +++ return obj; +++ } +++ return ERR_PTR(-ENOENT); +++} +++ ++ static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { ++ [NFTA_OBJ_TABLE] = { .type = NLA_STRING, ++ .len = NFT_TABLE_MAXNAMELEN - 1 }, ++@@ -4284,6 +4371,7 @@ static const struct nla_policy nft_obj_p ++ .len = NFT_OBJ_MAXNAMELEN - 1 }, ++ [NFTA_OBJ_TYPE] = { .type = NLA_U32 }, ++ [NFTA_OBJ_DATA] = { .type = NLA_NESTED }, +++ [NFTA_OBJ_HANDLE] = { .type = NLA_U64}, ++ }; ++ ++ static struct nft_object *nft_obj_init(const struct nft_ctx *ctx, ++@@ -4431,6 +4519,8 @@ static int nf_tables_newobj(struct net * ++ goto err1; ++ } ++ obj->table = table; +++ obj->handle = nf_tables_alloc_handle(table); +++ ++ obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL); ++ if (!obj->name) { ++ err = -ENOMEM; ++@@ -4477,7 +4567,9 @@ static int nf_tables_fill_obj_info(struc ++ nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || ++ nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || ++ nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || ++- nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) +++ nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) || +++ nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle), +++ NFTA_OBJ_PAD)) ++ goto nla_put_failure; ++ ++ nlmsg_end(skb, nlh); ++@@ -4675,7 +4767,7 @@ static int nf_tables_delobj(struct net * ++ u32 objtype; ++ ++ if (!nla[NFTA_OBJ_TYPE] || ++- !nla[NFTA_OBJ_NAME]) +++ (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE])) ++ return -EINVAL; ++ ++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, ++@@ -4684,7 +4776,12 @@ static int nf_tables_delobj(struct net * ++ return PTR_ERR(table); ++ ++ objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); ++- obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); +++ if (nla[NFTA_OBJ_HANDLE]) +++ obj = nf_tables_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE], +++ objtype, genmask); +++ else +++ obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], +++ objtype, genmask); ++ if (IS_ERR(obj)) ++ return PTR_ERR(obj); ++ if (obj->use > 0) ++@@ -4756,6 +4853,7 @@ static const struct nla_policy nft_flowt ++ [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, ++ .len = NFT_NAME_MAXLEN - 1 }, ++ [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, +++ [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 }, ++ }; ++ ++ struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, ++@@ -4773,6 +4871,20 @@ struct nft_flowtable *nf_tables_flowtabl ++ } ++ EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); ++ +++struct nft_flowtable * +++nf_tables_flowtable_lookup_byhandle(const struct nft_table *table, +++ const struct nlattr *nla, u8 genmask) +++{ +++ struct nft_flowtable *flowtable; +++ +++ list_for_each_entry(flowtable, &table->flowtables, list) { +++ if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle && +++ nft_active_genmask(flowtable, genmask)) +++ return flowtable; +++ } +++ return ERR_PTR(-ENOENT); +++} +++ ++ #define NFT_FLOWTABLE_DEVICE_MAX 8 ++ ++ static int nf_tables_parse_devices(const struct nft_ctx *ctx, ++@@ -4981,6 +5093,8 @@ static int nf_tables_newflowtable(struct ++ return -ENOMEM; ++ ++ flowtable->table = table; +++ flowtable->handle = nf_tables_alloc_handle(table); +++ ++ flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); ++ if (!flowtable->name) { ++ err = -ENOMEM; ++@@ -5055,8 +5169,14 @@ static int nf_tables_delflowtable(struct ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++- flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], ++- genmask); +++ if (nla[NFTA_FLOWTABLE_HANDLE]) +++ flowtable = nf_tables_flowtable_lookup_byhandle(table, +++ nla[NFTA_FLOWTABLE_HANDLE], +++ genmask); +++ else +++ flowtable = nf_tables_flowtable_lookup(table, +++ nla[NFTA_FLOWTABLE_NAME], +++ genmask); ++ if (IS_ERR(flowtable)) ++ return PTR_ERR(flowtable); ++ if (flowtable->use > 0) ++@@ -5089,7 +5209,9 @@ static int nf_tables_fill_flowtable_info ++ ++ if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || ++ nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || ++- nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use))) +++ nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || +++ nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), +++ NFTA_FLOWTABLE_PAD)) ++ goto nla_put_failure; ++ ++ nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); +diff --git a/target/linux/generic/backport-4.14/345-v4.16-netfilter-nf_flow_offload-fix-use-after-free-and-a-r.patch b/target/linux/generic/backport-4.14/345-v4.16-netfilter-nf_flow_offload-fix-use-after-free-and-a-r.patch +new file mode 100644 +index 0000000000..331f22d19a +--- /dev/null ++++ b/target/linux/generic/backport-4.14/345-v4.16-netfilter-nf_flow_offload-fix-use-after-free-and-a-r.patch +@@ -0,0 +1,95 @@ ++From: Felix Fietkau ++Date: Wed, 7 Feb 2018 09:23:25 +0100 ++Subject: [PATCH] netfilter: nf_flow_offload: fix use-after-free and a resource ++ leak ++ ++flow_offload_del frees the flow, so all associated resource must be ++freed before. ++ ++Since the ct entry in struct flow_offload_entry was allocated by ++flow_offload_alloc, it should be freed by flow_offload_free to take care ++of the error handling path when flow_offload_add fails. ++ ++While at it, make flow_offload_del static, since it should never be ++called directly, only from the gc step ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -90,7 +90,6 @@ struct flow_offload *flow_offload_alloc( ++ void flow_offload_free(struct flow_offload *flow); ++ ++ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); ++-void flow_offload_del(struct nf_flowtable *flow_table, struct flow_offload *flow); ++ struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table, ++ struct flow_offload_tuple *tuple); ++ int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++--- a/net/netfilter/nf_flow_table.c +++++ b/net/netfilter/nf_flow_table.c ++@@ -125,7 +125,9 @@ void flow_offload_free(struct flow_offlo ++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); ++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); ++ e = container_of(flow, struct flow_offload_entry, flow); ++- kfree(e); +++ nf_ct_delete(e->ct, 0, 0); +++ nf_ct_put(e->ct); +++ kfree_rcu(e, rcu_head); ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_free); ++ ++@@ -149,11 +151,9 @@ int flow_offload_add(struct nf_flowtable ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_add); ++ ++-void flow_offload_del(struct nf_flowtable *flow_table, ++- struct flow_offload *flow) +++static void flow_offload_del(struct nf_flowtable *flow_table, +++ struct flow_offload *flow) ++ { ++- struct flow_offload_entry *e; ++- ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++ *flow_table->type->params); ++@@ -161,10 +161,8 @@ void flow_offload_del(struct nf_flowtabl ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++ *flow_table->type->params); ++ ++- e = container_of(flow, struct flow_offload_entry, flow); ++- kfree_rcu(e, rcu_head); +++ flow_offload_free(flow); ++ } ++-EXPORT_SYMBOL_GPL(flow_offload_del); ++ ++ struct flow_offload_tuple_rhash * ++ flow_offload_lookup(struct nf_flowtable *flow_table, ++@@ -175,15 +173,6 @@ flow_offload_lookup(struct nf_flowtable ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_lookup); ++ ++-static void nf_flow_release_ct(const struct flow_offload *flow) ++-{ ++- struct flow_offload_entry *e; ++- ++- e = container_of(flow, struct flow_offload_entry, flow); ++- nf_ct_delete(e->ct, 0, 0); ++- nf_ct_put(e->ct); ++-} ++- ++ int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct flow_offload *flow, void *data), ++ void *data) ++@@ -259,10 +248,8 @@ static int nf_flow_offload_gc_step(struc ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++ ++ if (nf_flow_has_expired(flow) || ++- nf_flow_is_dying(flow)) { +++ nf_flow_is_dying(flow)) ++ flow_offload_del(flow_table, flow); ++- nf_flow_release_ct(flow); ++- } ++ } ++ out: ++ rhashtable_walk_stop(&hti); +diff --git a/target/linux/generic/backport-4.14/346-v4.16-netfilter-flowtable-infrastructure-depends-on-NETFIL.patch b/target/linux/generic/backport-4.14/346-v4.16-netfilter-flowtable-infrastructure-depends-on-NETFIL.patch +new file mode 100644 +index 0000000000..bb8c2d3e5a +--- /dev/null ++++ b/target/linux/generic/backport-4.14/346-v4.16-netfilter-flowtable-infrastructure-depends-on-NETFIL.patch +@@ -0,0 +1,73 @@ ++From: Pablo Neira Ayuso ++Date: Wed, 31 Jan 2018 18:13:39 +0100 ++Subject: [PATCH] netfilter: flowtable infrastructure depends on ++ NETFILTER_INGRESS ++ ++config NF_FLOW_TABLE depends on NETFILTER_INGRESS. If users forget to ++enable this toggle, flowtable registration fails with EOPNOTSUPP. ++ ++Moreover, turn 'select NF_FLOW_TABLE' in every flowtable family flavour ++into dependency instead, otherwise this new dependency on ++NETFILTER_INGRESS causes a warning. This also allows us to remove the ++explicit dependency between family flowtables <-> NF_TABLES and ++NF_CONNTRACK, given they depend on the NF_FLOW_TABLE core that already ++expresses the general dependencies for this new infrastructure. ++ ++Moreover, NF_FLOW_TABLE_INET depends on NF_FLOW_TABLE_IPV4 and ++NF_FLOWTABLE_IPV6, which already depends on NF_FLOW_TABLE. So we can get ++rid of direct dependency with NF_FLOW_TABLE. ++ ++In general, let's avoid 'select', it just makes things more complicated. ++ ++Reported-by: John Crispin ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/ipv4/netfilter/Kconfig +++++ b/net/ipv4/netfilter/Kconfig ++@@ -80,8 +80,7 @@ endif # NF_TABLES ++ ++ config NF_FLOW_TABLE_IPV4 ++ tristate "Netfilter flow table IPv4 module" ++- depends on NF_CONNTRACK && NF_TABLES ++- select NF_FLOW_TABLE +++ depends on NF_FLOW_TABLE ++ help ++ This option adds the flow table IPv4 support. ++ ++--- a/net/ipv6/netfilter/Kconfig +++++ b/net/ipv6/netfilter/Kconfig ++@@ -101,8 +101,7 @@ endif # NF_TABLES ++ ++ config NF_FLOW_TABLE_IPV6 ++ tristate "Netfilter flow table IPv6 module" ++- depends on NF_CONNTRACK && NF_TABLES ++- select NF_FLOW_TABLE +++ depends on NF_FLOW_TABLE ++ help ++ This option adds the flow table IPv6 support. ++ ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -676,8 +676,8 @@ endif # NF_TABLES ++ ++ config NF_FLOW_TABLE_INET ++ tristate "Netfilter flow table mixed IPv4/IPv6 module" ++- depends on NF_FLOW_TABLE_IPV4 && NF_FLOW_TABLE_IPV6 ++- select NF_FLOW_TABLE +++ depends on NF_FLOW_TABLE_IPV4 +++ depends on NF_FLOW_TABLE_IPV6 ++ help ++ This option adds the flow table mixed IPv4/IPv6 support. ++ ++@@ -685,7 +685,9 @@ config NF_FLOW_TABLE_INET ++ ++ config NF_FLOW_TABLE ++ tristate "Netfilter flow table module" ++- depends on NF_CONNTRACK && NF_TABLES +++ depends on NETFILTER_INGRESS +++ depends on NF_CONNTRACK +++ depends on NF_TABLES ++ help ++ This option adds the flow table core infrastructure. ++ +diff --git a/target/linux/generic/backport-4.14/347-v4.16-netfilter-remove-duplicated-include.patch b/target/linux/generic/backport-4.14/347-v4.16-netfilter-remove-duplicated-include.patch +new file mode 100644 +index 0000000000..c8a0972725 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/347-v4.16-netfilter-remove-duplicated-include.patch +@@ -0,0 +1,29 @@ ++From: Wei Yongjun ++Date: Wed, 10 Jan 2018 13:06:46 +0000 ++Subject: [PATCH] netfilter: remove duplicated include ++ ++Signed-off-by: Wei Yongjun ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c +++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c ++@@ -5,7 +5,6 @@ ++ #include ++ #include ++ #include ++-#include ++ #include ++ #include ++ #include ++--- a/net/netfilter/nf_queue.c +++++ b/net/netfilter/nf_queue.c ++@@ -15,8 +15,6 @@ ++ #include ++ #include ++ #include ++-#include ++-#include ++ #include ++ #include ++ #include +diff --git a/target/linux/generic/backport-4.14/348-v4.18-netfilter-nf_flow_table-use-IP_CT_DIR_-values-for-FL.patch b/target/linux/generic/backport-4.14/348-v4.18-netfilter-nf_flow_table-use-IP_CT_DIR_-values-for-FL.patch +new file mode 100644 +index 0000000000..382b33c078 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/348-v4.18-netfilter-nf_flow_table-use-IP_CT_DIR_-values-for-FL.patch +@@ -0,0 +1,35 @@ ++From: Felix Fietkau ++Date: Fri, 16 Feb 2018 09:41:18 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: use IP_CT_DIR_* values for ++ FLOW_OFFLOAD_DIR_* ++ ++Simplifies further code cleanups ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -6,6 +6,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ struct nf_flowtable; ++@@ -27,11 +28,10 @@ struct nf_flowtable { ++ }; ++ ++ enum flow_offload_tuple_dir { ++- FLOW_OFFLOAD_DIR_ORIGINAL, ++- FLOW_OFFLOAD_DIR_REPLY, ++- __FLOW_OFFLOAD_DIR_MAX = FLOW_OFFLOAD_DIR_REPLY, +++ FLOW_OFFLOAD_DIR_ORIGINAL = IP_CT_DIR_ORIGINAL, +++ FLOW_OFFLOAD_DIR_REPLY = IP_CT_DIR_REPLY, +++ FLOW_OFFLOAD_DIR_MAX = IP_CT_DIR_MAX ++ }; ++-#define FLOW_OFFLOAD_DIR_MAX (__FLOW_OFFLOAD_DIR_MAX + 1) ++ ++ struct flow_offload_tuple { ++ union { +diff --git a/target/linux/generic/backport-4.14/349-v4.18-netfilter-nf_flow_table-clean-up-flow_offload_alloc.patch b/target/linux/generic/backport-4.14/349-v4.18-netfilter-nf_flow_table-clean-up-flow_offload_alloc.patch +new file mode 100644 +index 0000000000..39ea757f04 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/349-v4.18-netfilter-nf_flow_table-clean-up-flow_offload_alloc.patch +@@ -0,0 +1,118 @@ ++From: Felix Fietkau ++Date: Fri, 16 Feb 2018 09:42:32 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: clean up flow_offload_alloc ++ ++Reduce code duplication and make it much easier to read ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table.c +++++ b/net/netfilter/nf_flow_table.c ++@@ -16,6 +16,38 @@ struct flow_offload_entry { ++ struct rcu_head rcu_head; ++ }; ++ +++static void +++flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, +++ struct nf_flow_route *route, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; +++ struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; +++ +++ ft->dir = dir; +++ +++ switch (ctt->src.l3num) { +++ case NFPROTO_IPV4: +++ ft->src_v4 = ctt->src.u3.in; +++ ft->dst_v4 = ctt->dst.u3.in; +++ break; +++ case NFPROTO_IPV6: +++ ft->src_v6 = ctt->src.u3.in6; +++ ft->dst_v6 = ctt->dst.u3.in6; +++ break; +++ } +++ +++ ft->l3proto = ctt->src.l3num; +++ ft->l4proto = ctt->dst.protonum; +++ ft->src_port = ctt->src.u.tcp.port; +++ ft->dst_port = ctt->dst.u.tcp.port; +++ +++ ft->iifidx = route->tuple[dir].ifindex; +++ ft->oifidx = route->tuple[!dir].ifindex; +++ +++ ft->dst_cache = route->tuple[dir].dst; +++} +++ ++ struct flow_offload * ++ flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) ++ { ++@@ -40,65 +72,8 @@ flow_offload_alloc(struct nf_conn *ct, s ++ ++ entry->ct = ct; ++ ++- switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) { ++- case NFPROTO_IPV4: ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4 = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4 = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4 = ++- ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4 = ++- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in; ++- break; ++- case NFPROTO_IPV6: ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6 = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in6; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6 = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6 = ++- ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in6; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6 = ++- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in6; ++- break; ++- } ++- ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l3proto = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l4proto = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.l3proto = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.l4proto = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; ++- ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache = ++- route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache = ++- route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst; ++- ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port = ++- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port = ++- ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.tcp.port; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port = ++- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; ++- ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dir = ++- FLOW_OFFLOAD_DIR_ORIGINAL; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dir = ++- FLOW_OFFLOAD_DIR_REPLY; ++- ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.iifidx = ++- route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].ifindex; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.oifidx = ++- route->tuple[FLOW_OFFLOAD_DIR_REPLY].ifindex; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.iifidx = ++- route->tuple[FLOW_OFFLOAD_DIR_REPLY].ifindex; ++- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.oifidx = ++- route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].ifindex; +++ flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_ORIGINAL); +++ flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_REPLY); ++ ++ if (ct->status & IPS_SRC_NAT) ++ flow->flags |= FLOW_OFFLOAD_SNAT; +diff --git a/target/linux/generic/backport-4.14/350-v4.18-ipv6-make-ip6_dst_mtu_forward-inline.patch b/target/linux/generic/backport-4.14/350-v4.18-ipv6-make-ip6_dst_mtu_forward-inline.patch +new file mode 100644 +index 0000000000..1c52cf51c6 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/350-v4.18-ipv6-make-ip6_dst_mtu_forward-inline.patch +@@ -0,0 +1,80 @@ ++From: Felix Fietkau ++Date: Fri, 16 Feb 2018 10:54:24 +0100 ++Subject: [PATCH] ipv6: make ip6_dst_mtu_forward inline ++ ++Removes a direct dependency on ipv6.ko ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/ip6_route.h +++++ b/include/net/ip6_route.h ++@@ -253,4 +253,26 @@ static inline bool rt6_duplicate_nexthop ++ ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) && ++ !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate); ++ } +++ +++static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) +++{ +++ unsigned int mtu; +++ struct inet6_dev *idev; +++ +++ if (dst_metric_locked(dst, RTAX_MTU)) { +++ mtu = dst_metric_raw(dst, RTAX_MTU); +++ if (mtu) +++ return mtu; +++ } +++ +++ mtu = IPV6_MIN_MTU; +++ rcu_read_lock(); +++ idev = __in6_dev_get(dst->dev); +++ if (idev) +++ mtu = idev->cnf.mtu6; +++ rcu_read_unlock(); +++ +++ return mtu; +++} +++ ++ #endif ++--- a/include/net/ipv6.h +++++ b/include/net/ipv6.h ++@@ -860,8 +860,6 @@ static inline struct sk_buff *ip6_finish ++ &inet6_sk(sk)->cork); ++ } ++ ++-unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst); ++- ++ int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst, ++ struct flowi6 *fl6); ++ struct dst_entry *ip6_dst_lookup_flow(struct net *net, const struct sock *sk, struct flowi6 *fl6, ++--- a/net/ipv6/ip6_output.c +++++ b/net/ipv6/ip6_output.c ++@@ -381,28 +381,6 @@ static inline int ip6_forward_finish(str ++ return dst_output(net, sk, skb); ++ } ++ ++-unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) ++-{ ++- unsigned int mtu; ++- struct inet6_dev *idev; ++- ++- if (dst_metric_locked(dst, RTAX_MTU)) { ++- mtu = dst_metric_raw(dst, RTAX_MTU); ++- if (mtu) ++- return mtu; ++- } ++- ++- mtu = IPV6_MIN_MTU; ++- rcu_read_lock(); ++- idev = __in6_dev_get(dst->dev); ++- if (idev) ++- mtu = idev->cnf.mtu6; ++- rcu_read_unlock(); ++- ++- return mtu; ++-} ++-EXPORT_SYMBOL_GPL(ip6_dst_mtu_forward); ++- ++ static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) ++ { ++ if (skb->len <= mtu) +diff --git a/target/linux/generic/backport-4.14/351-v4.18-netfilter-nf_flow_table-cache-mtu-in-struct-flow_off.patch b/target/linux/generic/backport-4.14/351-v4.18-netfilter-nf_flow_table-cache-mtu-in-struct-flow_off.patch +new file mode 100644 +index 0000000000..e2015e72ac +--- /dev/null ++++ b/target/linux/generic/backport-4.14/351-v4.18-netfilter-nf_flow_table-cache-mtu-in-struct-flow_off.patch +@@ -0,0 +1,145 @@ ++From: Felix Fietkau ++Date: Fri, 16 Feb 2018 10:57:23 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: cache mtu in struct ++ flow_offload_tuple ++ ++Reduces the number of cache lines touched in the offload forwarding path ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -55,6 +55,8 @@ struct flow_offload_tuple { ++ ++ int oifidx; ++ +++ u16 mtu; +++ ++ struct dst_entry *dst_cache; ++ }; ++ ++--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c +++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c ++@@ -177,7 +177,7 @@ static int nf_flow_tuple_ip(struct sk_bu ++ } ++ ++ /* Based on ip_exceeds_mtu(). */ ++-static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +++static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++ { ++ if (skb->len <= mtu) ++ return false; ++@@ -191,17 +191,6 @@ static bool __nf_flow_exceeds_mtu(const ++ return true; ++ } ++ ++-static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rtable *rt) ++-{ ++- u32 mtu; ++- ++- mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); ++- if (__nf_flow_exceeds_mtu(skb, mtu)) ++- return true; ++- ++- return false; ++-} ++- ++ unsigned int ++ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++@@ -232,9 +221,9 @@ nf_flow_offload_ip_hook(void *priv, stru ++ ++ dir = tuplehash->tuple.dir; ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++- ++ rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; ++- if (unlikely(nf_flow_exceeds_mtu(skb, rt))) +++ +++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ return NF_ACCEPT; ++ ++ if (skb_try_make_writable(skb, sizeof(*iph))) ++--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c +++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c ++@@ -173,7 +173,7 @@ static int nf_flow_tuple_ipv6(struct sk_ ++ } ++ ++ /* Based on ip_exceeds_mtu(). */ ++-static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +++static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++ { ++ if (skb->len <= mtu) ++ return false; ++@@ -184,17 +184,6 @@ static bool __nf_flow_exceeds_mtu(const ++ return true; ++ } ++ ++-static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rt6_info *rt) ++-{ ++- u32 mtu; ++- ++- mtu = ip6_dst_mtu_forward(&rt->dst); ++- if (__nf_flow_exceeds_mtu(skb, mtu)) ++- return true; ++- ++- return false; ++-} ++- ++ unsigned int ++ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++@@ -225,9 +214,9 @@ nf_flow_offload_ipv6_hook(void *priv, st ++ ++ dir = tuplehash->tuple.dir; ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++- ++ rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; ++- if (unlikely(nf_flow_exceeds_mtu(skb, rt))) +++ +++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ return NF_ACCEPT; ++ ++ if (skb_try_make_writable(skb, sizeof(*ip6h))) ++--- a/net/netfilter/nf_flow_table.c +++++ b/net/netfilter/nf_flow_table.c ++@@ -4,6 +4,8 @@ ++ #include ++ #include ++ #include +++#include +++#include ++ #include ++ #include ++ #include ++@@ -23,6 +25,7 @@ flow_offload_fill_dir(struct flow_offloa ++ { ++ struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; ++ struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; +++ struct dst_entry *dst = route->tuple[dir].dst; ++ ++ ft->dir = dir; ++ ++@@ -30,10 +33,12 @@ flow_offload_fill_dir(struct flow_offloa ++ case NFPROTO_IPV4: ++ ft->src_v4 = ctt->src.u3.in; ++ ft->dst_v4 = ctt->dst.u3.in; +++ ft->mtu = ip_dst_mtu_maybe_forward(dst, true); ++ break; ++ case NFPROTO_IPV6: ++ ft->src_v6 = ctt->src.u3.in6; ++ ft->dst_v6 = ctt->dst.u3.in6; +++ ft->mtu = ip6_dst_mtu_forward(dst); ++ break; ++ } ++ ++@@ -44,8 +49,7 @@ flow_offload_fill_dir(struct flow_offloa ++ ++ ft->iifidx = route->tuple[dir].ifindex; ++ ft->oifidx = route->tuple[!dir].ifindex; ++- ++- ft->dst_cache = route->tuple[dir].dst; +++ ft->dst_cache = dst; ++ } ++ ++ struct flow_offload * +diff --git a/target/linux/generic/backport-4.14/352-v4.18-netfilter-nf_flow_table-rename-nf_flow_table.c-to-nf.patch b/target/linux/generic/backport-4.14/352-v4.18-netfilter-nf_flow_table-rename-nf_flow_table.c-to-nf.patch +new file mode 100644 +index 0000000000..5df56dd643 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/352-v4.18-netfilter-nf_flow_table-rename-nf_flow_table.c-to-nf.patch +@@ -0,0 +1,952 @@ ++From: Felix Fietkau ++Date: Fri, 16 Feb 2018 11:08:47 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: rename nf_flow_table.c to ++ nf_flow_table_core.c ++ ++Preparation for adding more code to the same module ++ ++Signed-off-by: Felix Fietkau ++--- ++ rename net/netfilter/{nf_flow_table.c => nf_flow_table_core.c} (100%) ++ ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -113,6 +113,8 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_ ++ ++ # flow table infrastructure ++ obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o +++nf_flow_table-objs := nf_flow_table_core.o +++ ++ obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o ++ ++ # generic X tables ++--- a/net/netfilter/nf_flow_table.c +++++ /dev/null ++@@ -1,462 +0,0 @@ ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++- ++-struct flow_offload_entry { ++- struct flow_offload flow; ++- struct nf_conn *ct; ++- struct rcu_head rcu_head; ++-}; ++- ++-static void ++-flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, ++- struct nf_flow_route *route, ++- enum flow_offload_tuple_dir dir) ++-{ ++- struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; ++- struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; ++- struct dst_entry *dst = route->tuple[dir].dst; ++- ++- ft->dir = dir; ++- ++- switch (ctt->src.l3num) { ++- case NFPROTO_IPV4: ++- ft->src_v4 = ctt->src.u3.in; ++- ft->dst_v4 = ctt->dst.u3.in; ++- ft->mtu = ip_dst_mtu_maybe_forward(dst, true); ++- break; ++- case NFPROTO_IPV6: ++- ft->src_v6 = ctt->src.u3.in6; ++- ft->dst_v6 = ctt->dst.u3.in6; ++- ft->mtu = ip6_dst_mtu_forward(dst); ++- break; ++- } ++- ++- ft->l3proto = ctt->src.l3num; ++- ft->l4proto = ctt->dst.protonum; ++- ft->src_port = ctt->src.u.tcp.port; ++- ft->dst_port = ctt->dst.u.tcp.port; ++- ++- ft->iifidx = route->tuple[dir].ifindex; ++- ft->oifidx = route->tuple[!dir].ifindex; ++- ft->dst_cache = dst; ++-} ++- ++-struct flow_offload * ++-flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) ++-{ ++- struct flow_offload_entry *entry; ++- struct flow_offload *flow; ++- ++- if (unlikely(nf_ct_is_dying(ct) || ++- !atomic_inc_not_zero(&ct->ct_general.use))) ++- return NULL; ++- ++- entry = kzalloc(sizeof(*entry), GFP_ATOMIC); ++- if (!entry) ++- goto err_ct_refcnt; ++- ++- flow = &entry->flow; ++- ++- if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst)) ++- goto err_dst_cache_original; ++- ++- if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst)) ++- goto err_dst_cache_reply; ++- ++- entry->ct = ct; ++- ++- flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_ORIGINAL); ++- flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_REPLY); ++- ++- if (ct->status & IPS_SRC_NAT) ++- flow->flags |= FLOW_OFFLOAD_SNAT; ++- else if (ct->status & IPS_DST_NAT) ++- flow->flags |= FLOW_OFFLOAD_DNAT; ++- ++- return flow; ++- ++-err_dst_cache_reply: ++- dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst); ++-err_dst_cache_original: ++- kfree(entry); ++-err_ct_refcnt: ++- nf_ct_put(ct); ++- ++- return NULL; ++-} ++-EXPORT_SYMBOL_GPL(flow_offload_alloc); ++- ++-void flow_offload_free(struct flow_offload *flow) ++-{ ++- struct flow_offload_entry *e; ++- ++- dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); ++- dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); ++- e = container_of(flow, struct flow_offload_entry, flow); ++- nf_ct_delete(e->ct, 0, 0); ++- nf_ct_put(e->ct); ++- kfree_rcu(e, rcu_head); ++-} ++-EXPORT_SYMBOL_GPL(flow_offload_free); ++- ++-void flow_offload_dead(struct flow_offload *flow) ++-{ ++- flow->flags |= FLOW_OFFLOAD_DYING; ++-} ++-EXPORT_SYMBOL_GPL(flow_offload_dead); ++- ++-int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) ++-{ ++- flow->timeout = (u32)jiffies; ++- ++- rhashtable_insert_fast(&flow_table->rhashtable, ++- &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++- *flow_table->type->params); ++- rhashtable_insert_fast(&flow_table->rhashtable, ++- &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++- *flow_table->type->params); ++- return 0; ++-} ++-EXPORT_SYMBOL_GPL(flow_offload_add); ++- ++-static void flow_offload_del(struct nf_flowtable *flow_table, ++- struct flow_offload *flow) ++-{ ++- rhashtable_remove_fast(&flow_table->rhashtable, ++- &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++- *flow_table->type->params); ++- rhashtable_remove_fast(&flow_table->rhashtable, ++- &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++- *flow_table->type->params); ++- ++- flow_offload_free(flow); ++-} ++- ++-struct flow_offload_tuple_rhash * ++-flow_offload_lookup(struct nf_flowtable *flow_table, ++- struct flow_offload_tuple *tuple) ++-{ ++- return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, ++- *flow_table->type->params); ++-} ++-EXPORT_SYMBOL_GPL(flow_offload_lookup); ++- ++-int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++- void (*iter)(struct flow_offload *flow, void *data), ++- void *data) ++-{ ++- struct flow_offload_tuple_rhash *tuplehash; ++- struct rhashtable_iter hti; ++- struct flow_offload *flow; ++- int err; ++- ++- err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); ++- if (err) ++- return err; ++- ++- rhashtable_walk_start(&hti); ++- ++- while ((tuplehash = rhashtable_walk_next(&hti))) { ++- if (IS_ERR(tuplehash)) { ++- err = PTR_ERR(tuplehash); ++- if (err != -EAGAIN) ++- goto out; ++- ++- continue; ++- } ++- if (tuplehash->tuple.dir) ++- continue; ++- ++- flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++- ++- iter(flow, data); ++- } ++-out: ++- rhashtable_walk_stop(&hti); ++- rhashtable_walk_exit(&hti); ++- ++- return err; ++-} ++-EXPORT_SYMBOL_GPL(nf_flow_table_iterate); ++- ++-static inline bool nf_flow_has_expired(const struct flow_offload *flow) ++-{ ++- return (__s32)(flow->timeout - (u32)jiffies) <= 0; ++-} ++- ++-static inline bool nf_flow_is_dying(const struct flow_offload *flow) ++-{ ++- return flow->flags & FLOW_OFFLOAD_DYING; ++-} ++- ++-static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) ++-{ ++- struct flow_offload_tuple_rhash *tuplehash; ++- struct rhashtable_iter hti; ++- struct flow_offload *flow; ++- int err; ++- ++- err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); ++- if (err) ++- return 0; ++- ++- rhashtable_walk_start(&hti); ++- ++- while ((tuplehash = rhashtable_walk_next(&hti))) { ++- if (IS_ERR(tuplehash)) { ++- err = PTR_ERR(tuplehash); ++- if (err != -EAGAIN) ++- goto out; ++- ++- continue; ++- } ++- if (tuplehash->tuple.dir) ++- continue; ++- ++- flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++- ++- if (nf_flow_has_expired(flow) || ++- nf_flow_is_dying(flow)) ++- flow_offload_del(flow_table, flow); ++- } ++-out: ++- rhashtable_walk_stop(&hti); ++- rhashtable_walk_exit(&hti); ++- ++- return 1; ++-} ++- ++-void nf_flow_offload_work_gc(struct work_struct *work) ++-{ ++- struct nf_flowtable *flow_table; ++- ++- flow_table = container_of(work, struct nf_flowtable, gc_work.work); ++- nf_flow_offload_gc_step(flow_table); ++- queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); ++-} ++-EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); ++- ++-static u32 flow_offload_hash(const void *data, u32 len, u32 seed) ++-{ ++- const struct flow_offload_tuple *tuple = data; ++- ++- return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); ++-} ++- ++-static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) ++-{ ++- const struct flow_offload_tuple_rhash *tuplehash = data; ++- ++- return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); ++-} ++- ++-static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, ++- const void *ptr) ++-{ ++- const struct flow_offload_tuple *tuple = arg->key; ++- const struct flow_offload_tuple_rhash *x = ptr; ++- ++- if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) ++- return 1; ++- ++- return 0; ++-} ++- ++-const struct rhashtable_params nf_flow_offload_rhash_params = { ++- .head_offset = offsetof(struct flow_offload_tuple_rhash, node), ++- .hashfn = flow_offload_hash, ++- .obj_hashfn = flow_offload_hash_obj, ++- .obj_cmpfn = flow_offload_hash_cmp, ++- .automatic_shrinking = true, ++-}; ++-EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); ++- ++-static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, ++- __be16 port, __be16 new_port) ++-{ ++- struct tcphdr *tcph; ++- ++- if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++- skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++- return -1; ++- ++- tcph = (void *)(skb_network_header(skb) + thoff); ++- inet_proto_csum_replace2(&tcph->check, skb, port, new_port, true); ++- ++- return 0; ++-} ++- ++-static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, ++- __be16 port, __be16 new_port) ++-{ ++- struct udphdr *udph; ++- ++- if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++- skb_try_make_writable(skb, thoff + sizeof(*udph))) ++- return -1; ++- ++- udph = (void *)(skb_network_header(skb) + thoff); ++- if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++- inet_proto_csum_replace2(&udph->check, skb, port, ++- new_port, true); ++- if (!udph->check) ++- udph->check = CSUM_MANGLED_0; ++- } ++- ++- return 0; ++-} ++- ++-static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, ++- u8 protocol, __be16 port, __be16 new_port) ++-{ ++- switch (protocol) { ++- case IPPROTO_TCP: ++- if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0) ++- return NF_DROP; ++- break; ++- case IPPROTO_UDP: ++- if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0) ++- return NF_DROP; ++- break; ++- } ++- ++- return 0; ++-} ++- ++-int nf_flow_snat_port(const struct flow_offload *flow, ++- struct sk_buff *skb, unsigned int thoff, ++- u8 protocol, enum flow_offload_tuple_dir dir) ++-{ ++- struct flow_ports *hdr; ++- __be16 port, new_port; ++- ++- if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || ++- skb_try_make_writable(skb, thoff + sizeof(*hdr))) ++- return -1; ++- ++- hdr = (void *)(skb_network_header(skb) + thoff); ++- ++- switch (dir) { ++- case FLOW_OFFLOAD_DIR_ORIGINAL: ++- port = hdr->source; ++- new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port; ++- hdr->source = new_port; ++- break; ++- case FLOW_OFFLOAD_DIR_REPLY: ++- port = hdr->dest; ++- new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; ++- hdr->dest = new_port; ++- break; ++- default: ++- return -1; ++- } ++- ++- return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ++-} ++-EXPORT_SYMBOL_GPL(nf_flow_snat_port); ++- ++-int nf_flow_dnat_port(const struct flow_offload *flow, ++- struct sk_buff *skb, unsigned int thoff, ++- u8 protocol, enum flow_offload_tuple_dir dir) ++-{ ++- struct flow_ports *hdr; ++- __be16 port, new_port; ++- ++- if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || ++- skb_try_make_writable(skb, thoff + sizeof(*hdr))) ++- return -1; ++- ++- hdr = (void *)(skb_network_header(skb) + thoff); ++- ++- switch (dir) { ++- case FLOW_OFFLOAD_DIR_ORIGINAL: ++- port = hdr->dest; ++- new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port; ++- hdr->dest = new_port; ++- break; ++- case FLOW_OFFLOAD_DIR_REPLY: ++- port = hdr->source; ++- new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port; ++- hdr->source = new_port; ++- break; ++- default: ++- return -1; ++- } ++- ++- return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ++-} ++-EXPORT_SYMBOL_GPL(nf_flow_dnat_port); ++- ++-static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) ++-{ ++- struct net_device *dev = data; ++- ++- if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) ++- return; ++- ++- flow_offload_dead(flow); ++-} ++- ++-static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, ++- void *data) ++-{ ++- nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, data); ++- flush_delayed_work(&flowtable->gc_work); ++-} ++- ++-void nf_flow_table_cleanup(struct net *net, struct net_device *dev) ++-{ ++- nft_flow_table_iterate(net, nf_flow_table_iterate_cleanup, dev); ++-} ++-EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); ++- ++-void nf_flow_table_free(struct nf_flowtable *flow_table) ++-{ ++- nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); ++- WARN_ON(!nf_flow_offload_gc_step(flow_table)); ++-} ++-EXPORT_SYMBOL_GPL(nf_flow_table_free); ++- ++-static int nf_flow_table_netdev_event(struct notifier_block *this, ++- unsigned long event, void *ptr) ++-{ ++- struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++- ++- if (event != NETDEV_DOWN) ++- return NOTIFY_DONE; ++- ++- nf_flow_table_cleanup(dev_net(dev), dev); ++- ++- return NOTIFY_DONE; ++-} ++- ++-static struct notifier_block flow_offload_netdev_notifier = { ++- .notifier_call = nf_flow_table_netdev_event, ++-}; ++- ++-static int __init nf_flow_table_module_init(void) ++-{ ++- return register_netdevice_notifier(&flow_offload_netdev_notifier); ++-} ++- ++-static void __exit nf_flow_table_module_exit(void) ++-{ ++- unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++-} ++- ++-module_init(nf_flow_table_module_init); ++-module_exit(nf_flow_table_module_exit); ++- ++-MODULE_LICENSE("GPL"); ++-MODULE_AUTHOR("Pablo Neira Ayuso "); ++--- /dev/null +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -0,0 +1,462 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++struct flow_offload_entry { +++ struct flow_offload flow; +++ struct nf_conn *ct; +++ struct rcu_head rcu_head; +++}; +++ +++static void +++flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, +++ struct nf_flow_route *route, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; +++ struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; +++ struct dst_entry *dst = route->tuple[dir].dst; +++ +++ ft->dir = dir; +++ +++ switch (ctt->src.l3num) { +++ case NFPROTO_IPV4: +++ ft->src_v4 = ctt->src.u3.in; +++ ft->dst_v4 = ctt->dst.u3.in; +++ ft->mtu = ip_dst_mtu_maybe_forward(dst, true); +++ break; +++ case NFPROTO_IPV6: +++ ft->src_v6 = ctt->src.u3.in6; +++ ft->dst_v6 = ctt->dst.u3.in6; +++ ft->mtu = ip6_dst_mtu_forward(dst); +++ break; +++ } +++ +++ ft->l3proto = ctt->src.l3num; +++ ft->l4proto = ctt->dst.protonum; +++ ft->src_port = ctt->src.u.tcp.port; +++ ft->dst_port = ctt->dst.u.tcp.port; +++ +++ ft->iifidx = route->tuple[dir].ifindex; +++ ft->oifidx = route->tuple[!dir].ifindex; +++ ft->dst_cache = dst; +++} +++ +++struct flow_offload * +++flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) +++{ +++ struct flow_offload_entry *entry; +++ struct flow_offload *flow; +++ +++ if (unlikely(nf_ct_is_dying(ct) || +++ !atomic_inc_not_zero(&ct->ct_general.use))) +++ return NULL; +++ +++ entry = kzalloc(sizeof(*entry), GFP_ATOMIC); +++ if (!entry) +++ goto err_ct_refcnt; +++ +++ flow = &entry->flow; +++ +++ if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst)) +++ goto err_dst_cache_original; +++ +++ if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst)) +++ goto err_dst_cache_reply; +++ +++ entry->ct = ct; +++ +++ flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_ORIGINAL); +++ flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_REPLY); +++ +++ if (ct->status & IPS_SRC_NAT) +++ flow->flags |= FLOW_OFFLOAD_SNAT; +++ else if (ct->status & IPS_DST_NAT) +++ flow->flags |= FLOW_OFFLOAD_DNAT; +++ +++ return flow; +++ +++err_dst_cache_reply: +++ dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst); +++err_dst_cache_original: +++ kfree(entry); +++err_ct_refcnt: +++ nf_ct_put(ct); +++ +++ return NULL; +++} +++EXPORT_SYMBOL_GPL(flow_offload_alloc); +++ +++void flow_offload_free(struct flow_offload *flow) +++{ +++ struct flow_offload_entry *e; +++ +++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); +++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); +++ e = container_of(flow, struct flow_offload_entry, flow); +++ nf_ct_delete(e->ct, 0, 0); +++ nf_ct_put(e->ct); +++ kfree_rcu(e, rcu_head); +++} +++EXPORT_SYMBOL_GPL(flow_offload_free); +++ +++void flow_offload_dead(struct flow_offload *flow) +++{ +++ flow->flags |= FLOW_OFFLOAD_DYING; +++} +++EXPORT_SYMBOL_GPL(flow_offload_dead); +++ +++int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) +++{ +++ flow->timeout = (u32)jiffies; +++ +++ rhashtable_insert_fast(&flow_table->rhashtable, +++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +++ *flow_table->type->params); +++ rhashtable_insert_fast(&flow_table->rhashtable, +++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, +++ *flow_table->type->params); +++ return 0; +++} +++EXPORT_SYMBOL_GPL(flow_offload_add); +++ +++static void flow_offload_del(struct nf_flowtable *flow_table, +++ struct flow_offload *flow) +++{ +++ rhashtable_remove_fast(&flow_table->rhashtable, +++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +++ *flow_table->type->params); +++ rhashtable_remove_fast(&flow_table->rhashtable, +++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, +++ *flow_table->type->params); +++ +++ flow_offload_free(flow); +++} +++ +++struct flow_offload_tuple_rhash * +++flow_offload_lookup(struct nf_flowtable *flow_table, +++ struct flow_offload_tuple *tuple) +++{ +++ return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, +++ *flow_table->type->params); +++} +++EXPORT_SYMBOL_GPL(flow_offload_lookup); +++ +++int nf_flow_table_iterate(struct nf_flowtable *flow_table, +++ void (*iter)(struct flow_offload *flow, void *data), +++ void *data) +++{ +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct rhashtable_iter hti; +++ struct flow_offload *flow; +++ int err; +++ +++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); +++ if (err) +++ return err; +++ +++ rhashtable_walk_start(&hti); +++ +++ while ((tuplehash = rhashtable_walk_next(&hti))) { +++ if (IS_ERR(tuplehash)) { +++ err = PTR_ERR(tuplehash); +++ if (err != -EAGAIN) +++ goto out; +++ +++ continue; +++ } +++ if (tuplehash->tuple.dir) +++ continue; +++ +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); +++ +++ iter(flow, data); +++ } +++out: +++ rhashtable_walk_stop(&hti); +++ rhashtable_walk_exit(&hti); +++ +++ return err; +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_iterate); +++ +++static inline bool nf_flow_has_expired(const struct flow_offload *flow) +++{ +++ return (__s32)(flow->timeout - (u32)jiffies) <= 0; +++} +++ +++static inline bool nf_flow_is_dying(const struct flow_offload *flow) +++{ +++ return flow->flags & FLOW_OFFLOAD_DYING; +++} +++ +++static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) +++{ +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct rhashtable_iter hti; +++ struct flow_offload *flow; +++ int err; +++ +++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); +++ if (err) +++ return 0; +++ +++ rhashtable_walk_start(&hti); +++ +++ while ((tuplehash = rhashtable_walk_next(&hti))) { +++ if (IS_ERR(tuplehash)) { +++ err = PTR_ERR(tuplehash); +++ if (err != -EAGAIN) +++ goto out; +++ +++ continue; +++ } +++ if (tuplehash->tuple.dir) +++ continue; +++ +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); +++ +++ if (nf_flow_has_expired(flow) || +++ nf_flow_is_dying(flow)) +++ flow_offload_del(flow_table, flow); +++ } +++out: +++ rhashtable_walk_stop(&hti); +++ rhashtable_walk_exit(&hti); +++ +++ return 1; +++} +++ +++void nf_flow_offload_work_gc(struct work_struct *work) +++{ +++ struct nf_flowtable *flow_table; +++ +++ flow_table = container_of(work, struct nf_flowtable, gc_work.work); +++ nf_flow_offload_gc_step(flow_table); +++ queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); +++} +++EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); +++ +++static u32 flow_offload_hash(const void *data, u32 len, u32 seed) +++{ +++ const struct flow_offload_tuple *tuple = data; +++ +++ return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); +++} +++ +++static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) +++{ +++ const struct flow_offload_tuple_rhash *tuplehash = data; +++ +++ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); +++} +++ +++static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, +++ const void *ptr) +++{ +++ const struct flow_offload_tuple *tuple = arg->key; +++ const struct flow_offload_tuple_rhash *x = ptr; +++ +++ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) +++ return 1; +++ +++ return 0; +++} +++ +++const struct rhashtable_params nf_flow_offload_rhash_params = { +++ .head_offset = offsetof(struct flow_offload_tuple_rhash, node), +++ .hashfn = flow_offload_hash, +++ .obj_hashfn = flow_offload_hash_obj, +++ .obj_cmpfn = flow_offload_hash_cmp, +++ .automatic_shrinking = true, +++}; +++EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); +++ +++static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, +++ __be16 port, __be16 new_port) +++{ +++ struct tcphdr *tcph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) +++ return -1; +++ +++ tcph = (void *)(skb_network_header(skb) + thoff); +++ inet_proto_csum_replace2(&tcph->check, skb, port, new_port, true); +++ +++ return 0; +++} +++ +++static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, +++ __be16 port, __be16 new_port) +++{ +++ struct udphdr *udph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*udph))) +++ return -1; +++ +++ udph = (void *)(skb_network_header(skb) + thoff); +++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +++ inet_proto_csum_replace2(&udph->check, skb, port, +++ new_port, true); +++ if (!udph->check) +++ udph->check = CSUM_MANGLED_0; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, +++ u8 protocol, __be16 port, __be16 new_port) +++{ +++ switch (protocol) { +++ case IPPROTO_TCP: +++ if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0) +++ return NF_DROP; +++ break; +++ case IPPROTO_UDP: +++ if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0) +++ return NF_DROP; +++ break; +++ } +++ +++ return 0; +++} +++ +++int nf_flow_snat_port(const struct flow_offload *flow, +++ struct sk_buff *skb, unsigned int thoff, +++ u8 protocol, enum flow_offload_tuple_dir dir) +++{ +++ struct flow_ports *hdr; +++ __be16 port, new_port; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || +++ skb_try_make_writable(skb, thoff + sizeof(*hdr))) +++ return -1; +++ +++ hdr = (void *)(skb_network_header(skb) + thoff); +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ port = hdr->source; +++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port; +++ hdr->source = new_port; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ port = hdr->dest; +++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; +++ hdr->dest = new_port; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_port(skb, thoff, protocol, port, new_port); +++} +++EXPORT_SYMBOL_GPL(nf_flow_snat_port); +++ +++int nf_flow_dnat_port(const struct flow_offload *flow, +++ struct sk_buff *skb, unsigned int thoff, +++ u8 protocol, enum flow_offload_tuple_dir dir) +++{ +++ struct flow_ports *hdr; +++ __be16 port, new_port; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || +++ skb_try_make_writable(skb, thoff + sizeof(*hdr))) +++ return -1; +++ +++ hdr = (void *)(skb_network_header(skb) + thoff); +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ port = hdr->dest; +++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port; +++ hdr->dest = new_port; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ port = hdr->source; +++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port; +++ hdr->source = new_port; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_port(skb, thoff, protocol, port, new_port); +++} +++EXPORT_SYMBOL_GPL(nf_flow_dnat_port); +++ +++static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) +++{ +++ struct net_device *dev = data; +++ +++ if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) +++ return; +++ +++ flow_offload_dead(flow); +++} +++ +++static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, +++ void *data) +++{ +++ nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, data); +++ flush_delayed_work(&flowtable->gc_work); +++} +++ +++void nf_flow_table_cleanup(struct net *net, struct net_device *dev) +++{ +++ nft_flow_table_iterate(net, nf_flow_table_iterate_cleanup, dev); +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); +++ +++void nf_flow_table_free(struct nf_flowtable *flow_table) +++{ +++ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); +++ WARN_ON(!nf_flow_offload_gc_step(flow_table)); +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_free); +++ +++static int nf_flow_table_netdev_event(struct notifier_block *this, +++ unsigned long event, void *ptr) +++{ +++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); +++ +++ if (event != NETDEV_DOWN) +++ return NOTIFY_DONE; +++ +++ nf_flow_table_cleanup(dev_net(dev), dev); +++ +++ return NOTIFY_DONE; +++} +++ +++static struct notifier_block flow_offload_netdev_notifier = { +++ .notifier_call = nf_flow_table_netdev_event, +++}; +++ +++static int __init nf_flow_table_module_init(void) +++{ +++ return register_netdevice_notifier(&flow_offload_netdev_notifier); +++} +++ +++static void __exit nf_flow_table_module_exit(void) +++{ +++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); +++} +++ +++module_init(nf_flow_table_module_init); +++module_exit(nf_flow_table_module_exit); +++ +++MODULE_LICENSE("GPL"); +++MODULE_AUTHOR("Pablo Neira Ayuso "); +diff --git a/target/linux/generic/backport-4.14/353-v4.18-netfilter-nf_flow_table-move-ipv4-offload-hook-code-.patch b/target/linux/generic/backport-4.14/353-v4.18-netfilter-nf_flow_table-move-ipv4-offload-hook-code-.patch +new file mode 100644 +index 0000000000..e25a66f934 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/353-v4.18-netfilter-nf_flow_table-move-ipv4-offload-hook-code-.patch +@@ -0,0 +1,522 @@ ++From: Felix Fietkau ++Date: Sat, 17 Feb 2018 11:49:44 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: move ipv4 offload hook code to ++ nf_flow_table ++ ++Allows some minor code sharing with the ipv6 hook code and is also ++useful as preparation for adding iptables support for offload ++ ++Signed-off-by: Felix Fietkau ++--- ++ create mode 100644 net/netfilter/nf_flow_table_ip.c ++ ++--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c +++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c ++@@ -2,248 +2,8 @@ ++ #include ++ #include ++ #include ++-#include ++-#include ++-#include ++-#include ++-#include ++ #include ++ #include ++-/* For layer 4 checksum field offset. */ ++-#include ++-#include ++- ++-static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, ++- __be32 addr, __be32 new_addr) ++-{ ++- struct tcphdr *tcph; ++- ++- if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++- skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++- return -1; ++- ++- tcph = (void *)(skb_network_header(skb) + thoff); ++- inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); ++- ++- return 0; ++-} ++- ++-static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, ++- __be32 addr, __be32 new_addr) ++-{ ++- struct udphdr *udph; ++- ++- if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++- skb_try_make_writable(skb, thoff + sizeof(*udph))) ++- return -1; ++- ++- udph = (void *)(skb_network_header(skb) + thoff); ++- if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++- inet_proto_csum_replace4(&udph->check, skb, addr, ++- new_addr, true); ++- if (!udph->check) ++- udph->check = CSUM_MANGLED_0; ++- } ++- ++- return 0; ++-} ++- ++-static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, ++- unsigned int thoff, __be32 addr, ++- __be32 new_addr) ++-{ ++- switch (iph->protocol) { ++- case IPPROTO_TCP: ++- if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0) ++- return NF_DROP; ++- break; ++- case IPPROTO_UDP: ++- if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0) ++- return NF_DROP; ++- break; ++- } ++- ++- return 0; ++-} ++- ++-static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++- struct iphdr *iph, unsigned int thoff, ++- enum flow_offload_tuple_dir dir) ++-{ ++- __be32 addr, new_addr; ++- ++- switch (dir) { ++- case FLOW_OFFLOAD_DIR_ORIGINAL: ++- addr = iph->saddr; ++- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr; ++- iph->saddr = new_addr; ++- break; ++- case FLOW_OFFLOAD_DIR_REPLY: ++- addr = iph->daddr; ++- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; ++- iph->daddr = new_addr; ++- break; ++- default: ++- return -1; ++- } ++- csum_replace4(&iph->check, addr, new_addr); ++- ++- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++-} ++- ++-static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++- struct iphdr *iph, unsigned int thoff, ++- enum flow_offload_tuple_dir dir) ++-{ ++- __be32 addr, new_addr; ++- ++- switch (dir) { ++- case FLOW_OFFLOAD_DIR_ORIGINAL: ++- addr = iph->daddr; ++- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr; ++- iph->daddr = new_addr; ++- break; ++- case FLOW_OFFLOAD_DIR_REPLY: ++- addr = iph->saddr; ++- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; ++- iph->saddr = new_addr; ++- break; ++- default: ++- return -1; ++- } ++- ++- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++-} ++- ++-static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++- enum flow_offload_tuple_dir dir) ++-{ ++- struct iphdr *iph = ip_hdr(skb); ++- unsigned int thoff = iph->ihl * 4; ++- ++- if (flow->flags & FLOW_OFFLOAD_SNAT && ++- (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || ++- nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) ++- return -1; ++- if (flow->flags & FLOW_OFFLOAD_DNAT && ++- (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || ++- nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) ++- return -1; ++- ++- return 0; ++-} ++- ++-static bool ip_has_options(unsigned int thoff) ++-{ ++- return thoff != sizeof(struct iphdr); ++-} ++- ++-static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, ++- struct flow_offload_tuple *tuple) ++-{ ++- struct flow_ports *ports; ++- unsigned int thoff; ++- struct iphdr *iph; ++- ++- if (!pskb_may_pull(skb, sizeof(*iph))) ++- return -1; ++- ++- iph = ip_hdr(skb); ++- thoff = iph->ihl * 4; ++- ++- if (ip_is_fragment(iph) || ++- unlikely(ip_has_options(thoff))) ++- return -1; ++- ++- if (iph->protocol != IPPROTO_TCP && ++- iph->protocol != IPPROTO_UDP) ++- return -1; ++- ++- thoff = iph->ihl * 4; ++- if (!pskb_may_pull(skb, thoff + sizeof(*ports))) ++- return -1; ++- ++- ports = (struct flow_ports *)(skb_network_header(skb) + thoff); ++- ++- tuple->src_v4.s_addr = iph->saddr; ++- tuple->dst_v4.s_addr = iph->daddr; ++- tuple->src_port = ports->source; ++- tuple->dst_port = ports->dest; ++- tuple->l3proto = AF_INET; ++- tuple->l4proto = iph->protocol; ++- tuple->iifidx = dev->ifindex; ++- ++- return 0; ++-} ++- ++-/* Based on ip_exceeds_mtu(). */ ++-static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++-{ ++- if (skb->len <= mtu) ++- return false; ++- ++- if ((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ++- return false; ++- ++- if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) ++- return false; ++- ++- return true; ++-} ++- ++-unsigned int ++-nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, ++- const struct nf_hook_state *state) ++-{ ++- struct flow_offload_tuple_rhash *tuplehash; ++- struct nf_flowtable *flow_table = priv; ++- struct flow_offload_tuple tuple = {}; ++- enum flow_offload_tuple_dir dir; ++- struct flow_offload *flow; ++- struct net_device *outdev; ++- const struct rtable *rt; ++- struct iphdr *iph; ++- __be32 nexthop; ++- ++- if (skb->protocol != htons(ETH_P_IP)) ++- return NF_ACCEPT; ++- ++- if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) ++- return NF_ACCEPT; ++- ++- tuplehash = flow_offload_lookup(flow_table, &tuple); ++- if (tuplehash == NULL) ++- return NF_ACCEPT; ++- ++- outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); ++- if (!outdev) ++- return NF_ACCEPT; ++- ++- dir = tuplehash->tuple.dir; ++- flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++- rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; ++- ++- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++- return NF_ACCEPT; ++- ++- if (skb_try_make_writable(skb, sizeof(*iph))) ++- return NF_DROP; ++- ++- if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && ++- nf_flow_nat_ip(flow, skb, dir) < 0) ++- return NF_DROP; ++- ++- flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; ++- iph = ip_hdr(skb); ++- ip_decrease_ttl(iph); ++- ++- skb->dev = outdev; ++- nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); ++- neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); ++- ++- return NF_STOLEN; ++-} ++-EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); ++ ++ static struct nf_flowtable_type flowtable_ipv4 = { ++ .family = NFPROTO_IPV4, ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -113,7 +113,7 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_ ++ ++ # flow table infrastructure ++ obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o ++-nf_flow_table-objs := nf_flow_table_core.o +++nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o ++ ++ obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o ++ ++--- /dev/null +++++ b/net/netfilter/nf_flow_table_ip.c ++@@ -0,0 +1,245 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++/* For layer 4 checksum field offset. */ +++#include +++#include +++ +++static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, +++ __be32 addr, __be32 new_addr) +++{ +++ struct tcphdr *tcph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) +++ return -1; +++ +++ tcph = (void *)(skb_network_header(skb) + thoff); +++ inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); +++ +++ return 0; +++} +++ +++static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, +++ __be32 addr, __be32 new_addr) +++{ +++ struct udphdr *udph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*udph))) +++ return -1; +++ +++ udph = (void *)(skb_network_header(skb) + thoff); +++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +++ inet_proto_csum_replace4(&udph->check, skb, addr, +++ new_addr, true); +++ if (!udph->check) +++ udph->check = CSUM_MANGLED_0; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, +++ unsigned int thoff, __be32 addr, +++ __be32 new_addr) +++{ +++ switch (iph->protocol) { +++ case IPPROTO_TCP: +++ if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0) +++ return NF_DROP; +++ break; +++ case IPPROTO_UDP: +++ if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0) +++ return NF_DROP; +++ break; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb, +++ struct iphdr *iph, unsigned int thoff, +++ enum flow_offload_tuple_dir dir) +++{ +++ __be32 addr, new_addr; +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ addr = iph->saddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr; +++ iph->saddr = new_addr; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ addr = iph->daddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; +++ iph->daddr = new_addr; +++ break; +++ default: +++ return -1; +++ } +++ csum_replace4(&iph->check, addr, new_addr); +++ +++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); +++} +++ +++static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, +++ struct iphdr *iph, unsigned int thoff, +++ enum flow_offload_tuple_dir dir) +++{ +++ __be32 addr, new_addr; +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ addr = iph->daddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr; +++ iph->daddr = new_addr; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ addr = iph->saddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; +++ iph->saddr = new_addr; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); +++} +++ +++static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct iphdr *iph = ip_hdr(skb); +++ unsigned int thoff = iph->ihl * 4; +++ +++ if (flow->flags & FLOW_OFFLOAD_SNAT && +++ (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +++ nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) +++ return -1; +++ if (flow->flags & FLOW_OFFLOAD_DNAT && +++ (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +++ nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) +++ return -1; +++ +++ return 0; +++} +++ +++static bool ip_has_options(unsigned int thoff) +++{ +++ return thoff != sizeof(struct iphdr); +++} +++ +++static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, +++ struct flow_offload_tuple *tuple) +++{ +++ struct flow_ports *ports; +++ unsigned int thoff; +++ struct iphdr *iph; +++ +++ if (!pskb_may_pull(skb, sizeof(*iph))) +++ return -1; +++ +++ iph = ip_hdr(skb); +++ thoff = iph->ihl * 4; +++ +++ if (ip_is_fragment(iph) || +++ unlikely(ip_has_options(thoff))) +++ return -1; +++ +++ if (iph->protocol != IPPROTO_TCP && +++ iph->protocol != IPPROTO_UDP) +++ return -1; +++ +++ thoff = iph->ihl * 4; +++ if (!pskb_may_pull(skb, thoff + sizeof(*ports))) +++ return -1; +++ +++ ports = (struct flow_ports *)(skb_network_header(skb) + thoff); +++ +++ tuple->src_v4.s_addr = iph->saddr; +++ tuple->dst_v4.s_addr = iph->daddr; +++ tuple->src_port = ports->source; +++ tuple->dst_port = ports->dest; +++ tuple->l3proto = AF_INET; +++ tuple->l4proto = iph->protocol; +++ tuple->iifidx = dev->ifindex; +++ +++ return 0; +++} +++ +++/* Based on ip_exceeds_mtu(). */ +++static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +++{ +++ if (skb->len <= mtu) +++ return false; +++ +++ if ((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) +++ return false; +++ +++ if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) +++ return false; +++ +++ return true; +++} +++ +++unsigned int +++nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct nf_flowtable *flow_table = priv; +++ struct flow_offload_tuple tuple = {}; +++ enum flow_offload_tuple_dir dir; +++ struct flow_offload *flow; +++ struct net_device *outdev; +++ const struct rtable *rt; +++ struct iphdr *iph; +++ __be32 nexthop; +++ +++ if (skb->protocol != htons(ETH_P_IP)) +++ return NF_ACCEPT; +++ +++ if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) +++ return NF_ACCEPT; +++ +++ tuplehash = flow_offload_lookup(flow_table, &tuple); +++ if (tuplehash == NULL) +++ return NF_ACCEPT; +++ +++ outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); +++ if (!outdev) +++ return NF_ACCEPT; +++ +++ dir = tuplehash->tuple.dir; +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +++ rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; +++ +++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) +++ return NF_ACCEPT; +++ +++ if (skb_try_make_writable(skb, sizeof(*iph))) +++ return NF_DROP; +++ +++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && +++ nf_flow_nat_ip(flow, skb, dir) < 0) +++ return NF_DROP; +++ +++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; +++ iph = ip_hdr(skb); +++ ip_decrease_ttl(iph); +++ +++ skb->dev = outdev; +++ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); +++ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); +++ +++ return NF_STOLEN; +++} +++EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); +diff --git a/target/linux/generic/backport-4.14/354-v4.18-netfilter-nf_flow_table-move-ip-header-check-out-of-.patch b/target/linux/generic/backport-4.14/354-v4.18-netfilter-nf_flow_table-move-ip-header-check-out-of-.patch +new file mode 100644 +index 0000000000..4ee5532438 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/354-v4.18-netfilter-nf_flow_table-move-ip-header-check-out-of-.patch +@@ -0,0 +1,32 @@ ++From: Felix Fietkau ++Date: Sat, 17 Feb 2018 11:51:20 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: move ip header check out of ++ nf_flow_exceeds_mtu ++ ++Allows the function to be shared with the IPv6 hook code ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table_ip.c +++++ b/net/netfilter/nf_flow_table_ip.c ++@@ -181,9 +181,6 @@ static bool nf_flow_exceeds_mtu(const st ++ if (skb->len <= mtu) ++ return false; ++ ++- if ((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ++- return false; ++- ++ if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) ++ return false; ++ ++@@ -222,7 +219,8 @@ nf_flow_offload_ip_hook(void *priv, stru ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++ rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; ++ ++- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) +++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)) && +++ (ip_hdr(skb)->frag_off & htons(IP_DF)) != 0) ++ return NF_ACCEPT; ++ ++ if (skb_try_make_writable(skb, sizeof(*iph))) +diff --git a/target/linux/generic/backport-4.14/355-v4.18-netfilter-nf_flow_table-move-ipv6-offload-hook-code-.patch b/target/linux/generic/backport-4.14/355-v4.18-netfilter-nf_flow_table-move-ipv6-offload-hook-code-.patch +new file mode 100644 +index 0000000000..20ab0ed504 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/355-v4.18-netfilter-nf_flow_table-move-ipv6-offload-hook-code-.patch +@@ -0,0 +1,483 @@ ++From: Felix Fietkau ++Date: Sat, 17 Feb 2018 11:55:51 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: move ipv6 offload hook code to ++ nf_flow_table ++ ++Useful as preparation for adding iptables support for offload ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c +++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c ++@@ -3,240 +3,8 @@ ++ #include ++ #include ++ #include ++-#include ++-#include ++-#include ++-#include ++-#include ++ #include ++ #include ++-/* For layer 4 checksum field offset. */ ++-#include ++-#include ++- ++-static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, ++- struct in6_addr *addr, ++- struct in6_addr *new_addr) ++-{ ++- struct tcphdr *tcph; ++- ++- if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++- skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++- return -1; ++- ++- tcph = (void *)(skb_network_header(skb) + thoff); ++- inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, ++- new_addr->s6_addr32, true); ++- ++- return 0; ++-} ++- ++-static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, ++- struct in6_addr *addr, ++- struct in6_addr *new_addr) ++-{ ++- struct udphdr *udph; ++- ++- if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++- skb_try_make_writable(skb, thoff + sizeof(*udph))) ++- return -1; ++- ++- udph = (void *)(skb_network_header(skb) + thoff); ++- if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++- inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, ++- new_addr->s6_addr32, true); ++- if (!udph->check) ++- udph->check = CSUM_MANGLED_0; ++- } ++- ++- return 0; ++-} ++- ++-static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, ++- unsigned int thoff, struct in6_addr *addr, ++- struct in6_addr *new_addr) ++-{ ++- switch (ip6h->nexthdr) { ++- case IPPROTO_TCP: ++- if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0) ++- return NF_DROP; ++- break; ++- case IPPROTO_UDP: ++- if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0) ++- return NF_DROP; ++- break; ++- } ++- ++- return 0; ++-} ++- ++-static int nf_flow_snat_ipv6(const struct flow_offload *flow, ++- struct sk_buff *skb, struct ipv6hdr *ip6h, ++- unsigned int thoff, ++- enum flow_offload_tuple_dir dir) ++-{ ++- struct in6_addr addr, new_addr; ++- ++- switch (dir) { ++- case FLOW_OFFLOAD_DIR_ORIGINAL: ++- addr = ip6h->saddr; ++- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6; ++- ip6h->saddr = new_addr; ++- break; ++- case FLOW_OFFLOAD_DIR_REPLY: ++- addr = ip6h->daddr; ++- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; ++- ip6h->daddr = new_addr; ++- break; ++- default: ++- return -1; ++- } ++- ++- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); ++-} ++- ++-static int nf_flow_dnat_ipv6(const struct flow_offload *flow, ++- struct sk_buff *skb, struct ipv6hdr *ip6h, ++- unsigned int thoff, ++- enum flow_offload_tuple_dir dir) ++-{ ++- struct in6_addr addr, new_addr; ++- ++- switch (dir) { ++- case FLOW_OFFLOAD_DIR_ORIGINAL: ++- addr = ip6h->daddr; ++- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6; ++- ip6h->daddr = new_addr; ++- break; ++- case FLOW_OFFLOAD_DIR_REPLY: ++- addr = ip6h->saddr; ++- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; ++- ip6h->saddr = new_addr; ++- break; ++- default: ++- return -1; ++- } ++- ++- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); ++-} ++- ++-static int nf_flow_nat_ipv6(const struct flow_offload *flow, ++- struct sk_buff *skb, ++- enum flow_offload_tuple_dir dir) ++-{ ++- struct ipv6hdr *ip6h = ipv6_hdr(skb); ++- unsigned int thoff = sizeof(*ip6h); ++- ++- if (flow->flags & FLOW_OFFLOAD_SNAT && ++- (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || ++- nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) ++- return -1; ++- if (flow->flags & FLOW_OFFLOAD_DNAT && ++- (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || ++- nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) ++- return -1; ++- ++- return 0; ++-} ++- ++-static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, ++- struct flow_offload_tuple *tuple) ++-{ ++- struct flow_ports *ports; ++- struct ipv6hdr *ip6h; ++- unsigned int thoff; ++- ++- if (!pskb_may_pull(skb, sizeof(*ip6h))) ++- return -1; ++- ++- ip6h = ipv6_hdr(skb); ++- ++- if (ip6h->nexthdr != IPPROTO_TCP && ++- ip6h->nexthdr != IPPROTO_UDP) ++- return -1; ++- ++- thoff = sizeof(*ip6h); ++- if (!pskb_may_pull(skb, thoff + sizeof(*ports))) ++- return -1; ++- ++- ports = (struct flow_ports *)(skb_network_header(skb) + thoff); ++- ++- tuple->src_v6 = ip6h->saddr; ++- tuple->dst_v6 = ip6h->daddr; ++- tuple->src_port = ports->source; ++- tuple->dst_port = ports->dest; ++- tuple->l3proto = AF_INET6; ++- tuple->l4proto = ip6h->nexthdr; ++- tuple->iifidx = dev->ifindex; ++- ++- return 0; ++-} ++- ++-/* Based on ip_exceeds_mtu(). */ ++-static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++-{ ++- if (skb->len <= mtu) ++- return false; ++- ++- if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) ++- return false; ++- ++- return true; ++-} ++- ++-unsigned int ++-nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ++- const struct nf_hook_state *state) ++-{ ++- struct flow_offload_tuple_rhash *tuplehash; ++- struct nf_flowtable *flow_table = priv; ++- struct flow_offload_tuple tuple = {}; ++- enum flow_offload_tuple_dir dir; ++- struct flow_offload *flow; ++- struct net_device *outdev; ++- struct in6_addr *nexthop; ++- struct ipv6hdr *ip6h; ++- struct rt6_info *rt; ++- ++- if (skb->protocol != htons(ETH_P_IPV6)) ++- return NF_ACCEPT; ++- ++- if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) ++- return NF_ACCEPT; ++- ++- tuplehash = flow_offload_lookup(flow_table, &tuple); ++- if (tuplehash == NULL) ++- return NF_ACCEPT; ++- ++- outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); ++- if (!outdev) ++- return NF_ACCEPT; ++- ++- dir = tuplehash->tuple.dir; ++- flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++- rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; ++- ++- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++- return NF_ACCEPT; ++- ++- if (skb_try_make_writable(skb, sizeof(*ip6h))) ++- return NF_DROP; ++- ++- if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && ++- nf_flow_nat_ipv6(flow, skb, dir) < 0) ++- return NF_DROP; ++- ++- flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; ++- ip6h = ipv6_hdr(skb); ++- ip6h->hop_limit--; ++- ++- skb->dev = outdev; ++- nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); ++- neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); ++- ++- return NF_STOLEN; ++-} ++-EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook); ++ ++ static struct nf_flowtable_type flowtable_ipv6 = { ++ .family = NFPROTO_IPV6, ++--- a/net/netfilter/nf_flow_table_ip.c +++++ b/net/netfilter/nf_flow_table_ip.c ++@@ -4,8 +4,11 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include +++#include +++#include ++ #include ++ #include ++ /* For layer 4 checksum field offset. */ ++@@ -241,3 +244,215 @@ nf_flow_offload_ip_hook(void *priv, stru ++ return NF_STOLEN; ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); +++ +++static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, +++ struct in6_addr *addr, +++ struct in6_addr *new_addr) +++{ +++ struct tcphdr *tcph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) +++ return -1; +++ +++ tcph = (void *)(skb_network_header(skb) + thoff); +++ inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, +++ new_addr->s6_addr32, true); +++ +++ return 0; +++} +++ +++static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, +++ struct in6_addr *addr, +++ struct in6_addr *new_addr) +++{ +++ struct udphdr *udph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +++ skb_try_make_writable(skb, thoff + sizeof(*udph))) +++ return -1; +++ +++ udph = (void *)(skb_network_header(skb) + thoff); +++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +++ inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, +++ new_addr->s6_addr32, true); +++ if (!udph->check) +++ udph->check = CSUM_MANGLED_0; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, +++ unsigned int thoff, struct in6_addr *addr, +++ struct in6_addr *new_addr) +++{ +++ switch (ip6h->nexthdr) { +++ case IPPROTO_TCP: +++ if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0) +++ return NF_DROP; +++ break; +++ case IPPROTO_UDP: +++ if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0) +++ return NF_DROP; +++ break; +++ } +++ +++ return 0; +++} +++ +++static int nf_flow_snat_ipv6(const struct flow_offload *flow, +++ struct sk_buff *skb, struct ipv6hdr *ip6h, +++ unsigned int thoff, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct in6_addr addr, new_addr; +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ addr = ip6h->saddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6; +++ ip6h->saddr = new_addr; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ addr = ip6h->daddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; +++ ip6h->daddr = new_addr; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); +++} +++ +++static int nf_flow_dnat_ipv6(const struct flow_offload *flow, +++ struct sk_buff *skb, struct ipv6hdr *ip6h, +++ unsigned int thoff, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct in6_addr addr, new_addr; +++ +++ switch (dir) { +++ case FLOW_OFFLOAD_DIR_ORIGINAL: +++ addr = ip6h->daddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6; +++ ip6h->daddr = new_addr; +++ break; +++ case FLOW_OFFLOAD_DIR_REPLY: +++ addr = ip6h->saddr; +++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; +++ ip6h->saddr = new_addr; +++ break; +++ default: +++ return -1; +++ } +++ +++ return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); +++} +++ +++static int nf_flow_nat_ipv6(const struct flow_offload *flow, +++ struct sk_buff *skb, +++ enum flow_offload_tuple_dir dir) +++{ +++ struct ipv6hdr *ip6h = ipv6_hdr(skb); +++ unsigned int thoff = sizeof(*ip6h); +++ +++ if (flow->flags & FLOW_OFFLOAD_SNAT && +++ (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +++ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) +++ return -1; +++ if (flow->flags & FLOW_OFFLOAD_DNAT && +++ (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +++ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) +++ return -1; +++ +++ return 0; +++} +++ +++static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, +++ struct flow_offload_tuple *tuple) +++{ +++ struct flow_ports *ports; +++ struct ipv6hdr *ip6h; +++ unsigned int thoff; +++ +++ if (!pskb_may_pull(skb, sizeof(*ip6h))) +++ return -1; +++ +++ ip6h = ipv6_hdr(skb); +++ +++ if (ip6h->nexthdr != IPPROTO_TCP && +++ ip6h->nexthdr != IPPROTO_UDP) +++ return -1; +++ +++ thoff = sizeof(*ip6h); +++ if (!pskb_may_pull(skb, thoff + sizeof(*ports))) +++ return -1; +++ +++ ports = (struct flow_ports *)(skb_network_header(skb) + thoff); +++ +++ tuple->src_v6 = ip6h->saddr; +++ tuple->dst_v6 = ip6h->daddr; +++ tuple->src_port = ports->source; +++ tuple->dst_port = ports->dest; +++ tuple->l3proto = AF_INET6; +++ tuple->l4proto = ip6h->nexthdr; +++ tuple->iifidx = dev->ifindex; +++ +++ return 0; +++} +++ +++unsigned int +++nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct nf_flowtable *flow_table = priv; +++ struct flow_offload_tuple tuple = {}; +++ enum flow_offload_tuple_dir dir; +++ struct flow_offload *flow; +++ struct net_device *outdev; +++ struct in6_addr *nexthop; +++ struct ipv6hdr *ip6h; +++ struct rt6_info *rt; +++ +++ if (skb->protocol != htons(ETH_P_IPV6)) +++ return NF_ACCEPT; +++ +++ if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) +++ return NF_ACCEPT; +++ +++ tuplehash = flow_offload_lookup(flow_table, &tuple); +++ if (tuplehash == NULL) +++ return NF_ACCEPT; +++ +++ outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); +++ if (!outdev) +++ return NF_ACCEPT; +++ +++ dir = tuplehash->tuple.dir; +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +++ rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; +++ +++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) +++ return NF_ACCEPT; +++ +++ if (skb_try_make_writable(skb, sizeof(*ip6h))) +++ return NF_DROP; +++ +++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && +++ nf_flow_nat_ipv6(flow, skb, dir) < 0) +++ return NF_DROP; +++ +++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; +++ ip6h = ipv6_hdr(skb); +++ ip6h->hop_limit--; +++ +++ skb->dev = outdev; +++ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); +++ neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); +++ +++ return NF_STOLEN; +++} +++EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook); +diff --git a/target/linux/generic/backport-4.14/356-v4.18-netfilter-nf_flow_table-relax-mixed-ipv4-ipv6-flowta.patch b/target/linux/generic/backport-4.14/356-v4.18-netfilter-nf_flow_table-relax-mixed-ipv4-ipv6-flowta.patch +new file mode 100644 +index 0000000000..b5fe25a1d6 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/356-v4.18-netfilter-nf_flow_table-relax-mixed-ipv4-ipv6-flowta.patch +@@ -0,0 +1,23 @@ ++From: Felix Fietkau ++Date: Sat, 17 Feb 2018 12:02:28 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: relax mixed ipv4/ipv6 flowtable ++ dependencies ++ ++Since the offload hook code was moved, this table no longer depends on ++the IPv4 and IPv6 flowtable modules ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -676,8 +676,7 @@ endif # NF_TABLES ++ ++ config NF_FLOW_TABLE_INET ++ tristate "Netfilter flow table mixed IPv4/IPv6 module" ++- depends on NF_FLOW_TABLE_IPV4 ++- depends on NF_FLOW_TABLE_IPV6 +++ depends on NF_FLOW_TABLE ++ help ++ This option adds the flow table mixed IPv4/IPv6 support. ++ +diff --git a/target/linux/generic/backport-4.14/357-v4.18-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch b/target/linux/generic/backport-4.14/357-v4.18-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch +new file mode 100644 +index 0000000000..96acb6887e +--- /dev/null ++++ b/target/linux/generic/backport-4.14/357-v4.18-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch +@@ -0,0 +1,298 @@ ++From: Felix Fietkau ++Date: Sun, 18 Feb 2018 18:16:31 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: move init code to ++ nf_flow_table_core.c ++ ++Reduces duplication of .gc and .params in flowtable type definitions and ++makes the API clearer ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -14,9 +14,8 @@ struct nf_flowtable; ++ struct nf_flowtable_type { ++ struct list_head list; ++ int family; ++- void (*gc)(struct work_struct *work); +++ int (*init)(struct nf_flowtable *ft); ++ void (*free)(struct nf_flowtable *ft); ++- const struct rhashtable_params *params; ++ nf_hookfn *hook; ++ struct module *owner; ++ }; ++@@ -100,9 +99,8 @@ int nf_flow_table_iterate(struct nf_flow ++ ++ void nf_flow_table_cleanup(struct net *net, struct net_device *dev); ++ +++int nf_flow_table_init(struct nf_flowtable *flow_table); ++ void nf_flow_table_free(struct nf_flowtable *flow_table); ++-void nf_flow_offload_work_gc(struct work_struct *work); ++-extern const struct rhashtable_params nf_flow_offload_rhash_params; ++ ++ void flow_offload_dead(struct flow_offload *flow); ++ ++--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c +++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c ++@@ -7,8 +7,7 @@ ++ ++ static struct nf_flowtable_type flowtable_ipv4 = { ++ .family = NFPROTO_IPV4, ++- .params = &nf_flow_offload_rhash_params, ++- .gc = nf_flow_offload_work_gc, +++ .init = nf_flow_table_init, ++ .free = nf_flow_table_free, ++ .hook = nf_flow_offload_ip_hook, ++ .owner = THIS_MODULE, ++--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c +++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c ++@@ -8,8 +8,7 @@ ++ ++ static struct nf_flowtable_type flowtable_ipv6 = { ++ .family = NFPROTO_IPV6, ++- .params = &nf_flow_offload_rhash_params, ++- .gc = nf_flow_offload_work_gc, +++ .init = nf_flow_table_init, ++ .free = nf_flow_table_free, ++ .hook = nf_flow_offload_ipv6_hook, ++ .owner = THIS_MODULE, ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -116,16 +116,50 @@ void flow_offload_dead(struct flow_offlo ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_dead); ++ +++static u32 flow_offload_hash(const void *data, u32 len, u32 seed) +++{ +++ const struct flow_offload_tuple *tuple = data; +++ +++ return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); +++} +++ +++static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) +++{ +++ const struct flow_offload_tuple_rhash *tuplehash = data; +++ +++ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); +++} +++ +++static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, +++ const void *ptr) +++{ +++ const struct flow_offload_tuple *tuple = arg->key; +++ const struct flow_offload_tuple_rhash *x = ptr; +++ +++ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) +++ return 1; +++ +++ return 0; +++} +++ +++static const struct rhashtable_params nf_flow_offload_rhash_params = { +++ .head_offset = offsetof(struct flow_offload_tuple_rhash, node), +++ .hashfn = flow_offload_hash, +++ .obj_hashfn = flow_offload_hash_obj, +++ .obj_cmpfn = flow_offload_hash_cmp, +++ .automatic_shrinking = true, +++}; +++ ++ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) ++ { ++ flow->timeout = (u32)jiffies; ++ ++ rhashtable_insert_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++- *flow_table->type->params); +++ nf_flow_offload_rhash_params); ++ rhashtable_insert_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++- *flow_table->type->params); +++ nf_flow_offload_rhash_params); ++ return 0; ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_add); ++@@ -135,10 +169,10 @@ static void flow_offload_del(struct nf_f ++ { ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++- *flow_table->type->params); +++ nf_flow_offload_rhash_params); ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++- *flow_table->type->params); +++ nf_flow_offload_rhash_params); ++ ++ flow_offload_free(flow); ++ } ++@@ -148,7 +182,7 @@ flow_offload_lookup(struct nf_flowtable ++ struct flow_offload_tuple *tuple) ++ { ++ return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, ++- *flow_table->type->params); +++ nf_flow_offload_rhash_params); ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_lookup); ++ ++@@ -237,7 +271,7 @@ out: ++ return 1; ++ } ++ ++-void nf_flow_offload_work_gc(struct work_struct *work) +++static void nf_flow_offload_work_gc(struct work_struct *work) ++ { ++ struct nf_flowtable *flow_table; ++ ++@@ -245,42 +279,6 @@ void nf_flow_offload_work_gc(struct work ++ nf_flow_offload_gc_step(flow_table); ++ queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); ++ } ++-EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); ++- ++-static u32 flow_offload_hash(const void *data, u32 len, u32 seed) ++-{ ++- const struct flow_offload_tuple *tuple = data; ++- ++- return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); ++-} ++- ++-static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) ++-{ ++- const struct flow_offload_tuple_rhash *tuplehash = data; ++- ++- return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); ++-} ++- ++-static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, ++- const void *ptr) ++-{ ++- const struct flow_offload_tuple *tuple = arg->key; ++- const struct flow_offload_tuple_rhash *x = ptr; ++- ++- if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) ++- return 1; ++- ++- return 0; ++-} ++- ++-const struct rhashtable_params nf_flow_offload_rhash_params = { ++- .head_offset = offsetof(struct flow_offload_tuple_rhash, node), ++- .hashfn = flow_offload_hash, ++- .obj_hashfn = flow_offload_hash_obj, ++- .obj_cmpfn = flow_offload_hash_cmp, ++- .automatic_shrinking = true, ++-}; ++-EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); ++ ++ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, ++ __be16 port, __be16 new_port) ++@@ -398,6 +396,24 @@ int nf_flow_dnat_port(const struct flow_ ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_dnat_port); ++ +++int nf_flow_table_init(struct nf_flowtable *flowtable) +++{ +++ int err; +++ +++ INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc); +++ +++ err = rhashtable_init(&flowtable->rhashtable, +++ &nf_flow_offload_rhash_params); +++ if (err < 0) +++ return err; +++ +++ queue_delayed_work(system_power_efficient_wq, +++ &flowtable->gc_work, HZ); +++ +++ return 0; +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_init); +++ ++ static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) ++ { ++ struct net_device *dev = data; ++@@ -423,8 +439,10 @@ EXPORT_SYMBOL_GPL(nf_flow_table_cleanup) ++ ++ void nf_flow_table_free(struct nf_flowtable *flow_table) ++ { +++ cancel_delayed_work_sync(&flow_table->gc_work); ++ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); ++ WARN_ON(!nf_flow_offload_gc_step(flow_table)); +++ rhashtable_destroy(&flow_table->rhashtable); ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_table_free); ++ ++--- a/net/netfilter/nf_flow_table_inet.c +++++ b/net/netfilter/nf_flow_table_inet.c ++@@ -22,8 +22,7 @@ nf_flow_offload_inet_hook(void *priv, st ++ ++ static struct nf_flowtable_type flowtable_inet = { ++ .family = NFPROTO_INET, ++- .params = &nf_flow_offload_rhash_params, ++- .gc = nf_flow_offload_work_gc, +++ .init = nf_flow_table_init, ++ .free = nf_flow_table_free, ++ .hook = nf_flow_offload_inet_hook, ++ .owner = THIS_MODULE, ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -5108,40 +5108,38 @@ static int nf_tables_newflowtable(struct ++ } ++ ++ flowtable->data.type = type; ++- err = rhashtable_init(&flowtable->data.rhashtable, type->params); +++ err = type->init(&flowtable->data); ++ if (err < 0) ++ goto err3; ++ ++ err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK], ++ flowtable); ++ if (err < 0) ++- goto err3; +++ goto err4; ++ ++ for (i = 0; i < flowtable->ops_len; i++) { ++ err = nf_register_net_hook(net, &flowtable->ops[i]); ++ if (err < 0) ++- goto err4; +++ goto err5; ++ } ++ ++ err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable); ++ if (err < 0) ++- goto err5; ++- ++- INIT_DEFERRABLE_WORK(&flowtable->data.gc_work, type->gc); ++- queue_delayed_work(system_power_efficient_wq, ++- &flowtable->data.gc_work, HZ); +++ goto err6; ++ ++ list_add_tail_rcu(&flowtable->list, &table->flowtables); ++ table->use++; ++ ++ return 0; ++-err5: +++err6: ++ i = flowtable->ops_len; ++-err4: +++err5: ++ for (k = i - 1; k >= 0; k--) ++ nf_unregister_net_hook(net, &flowtable->ops[i]); ++ ++ kfree(flowtable->ops); +++err4: +++ flowtable->data.type->free(&flowtable->data); ++ err3: ++ module_put(type->owner); ++ err2: ++@@ -5422,10 +5420,8 @@ err: ++ ++ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) ++ { ++- cancel_delayed_work_sync(&flowtable->data.gc_work); ++ kfree(flowtable->name); ++ flowtable->data.type->free(&flowtable->data); ++- rhashtable_destroy(&flowtable->data.rhashtable); ++ module_put(flowtable->data.type->owner); ++ } ++ +diff --git a/target/linux/generic/backport-4.14/358-v4.18-netfilter-nf_flow_table-fix-priv-pointer-for-netdev-.patch b/target/linux/generic/backport-4.14/358-v4.18-netfilter-nf_flow_table-fix-priv-pointer-for-netdev-.patch +new file mode 100644 +index 0000000000..ea86e761d7 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/358-v4.18-netfilter-nf_flow_table-fix-priv-pointer-for-netdev-.patch +@@ -0,0 +1,22 @@ ++From: Felix Fietkau ++Date: Tue, 20 Feb 2018 14:48:51 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: fix priv pointer for netdev hook ++ ++The offload ip hook expects a pointer to the flowtable, not to the ++rhashtable. Since the rhashtable is the first member, this is safe for ++the moment, but breaks as soon as the structure layout changes ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -4974,7 +4974,7 @@ static int nf_tables_flowtable_parse_hoo ++ flowtable->ops[i].pf = NFPROTO_NETDEV; ++ flowtable->ops[i].hooknum = hooknum; ++ flowtable->ops[i].priority = priority; ++- flowtable->ops[i].priv = &flowtable->data.rhashtable; +++ flowtable->ops[i].priv = &flowtable->data; ++ flowtable->ops[i].hook = flowtable->data.type->hook; ++ flowtable->ops[i].dev = dev_array[i]; ++ } +diff --git a/target/linux/generic/backport-4.14/359-v4.18-netfilter-nf_flow_table-track-flow-tables-in-nf_flow.patch b/target/linux/generic/backport-4.14/359-v4.18-netfilter-nf_flow_table-track-flow-tables-in-nf_flow.patch +new file mode 100644 +index 0000000000..643189b5c0 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/359-v4.18-netfilter-nf_flow_table-track-flow-tables-in-nf_flow.patch +@@ -0,0 +1,114 @@ ++From: Felix Fietkau ++Date: Tue, 20 Feb 2018 14:08:14 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: track flow tables in nf_flow_table ++ directly ++ ++Avoids having nf_flow_table depend on nftables (useful for future ++iptables backport work) ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -21,6 +21,7 @@ struct nf_flowtable_type { ++ }; ++ ++ struct nf_flowtable { +++ struct list_head list; ++ struct rhashtable rhashtable; ++ const struct nf_flowtable_type *type; ++ struct delayed_work gc_work; ++--- a/include/net/netfilter/nf_tables.h +++++ b/include/net/netfilter/nf_tables.h ++@@ -1097,9 +1097,6 @@ struct nft_flowtable { ++ struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, ++ const struct nlattr *nla, ++ u8 genmask); ++-void nft_flow_table_iterate(struct net *net, ++- void (*iter)(struct nf_flowtable *flowtable, void *data), ++- void *data); ++ ++ void nft_register_flowtable_type(struct nf_flowtable_type *type); ++ void nft_unregister_flowtable_type(struct nf_flowtable_type *type); ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -18,6 +18,9 @@ struct flow_offload_entry { ++ struct rcu_head rcu_head; ++ }; ++ +++static DEFINE_MUTEX(flowtable_lock); +++static LIST_HEAD(flowtables); +++ ++ static void ++ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, ++ struct nf_flow_route *route, ++@@ -410,6 +413,10 @@ int nf_flow_table_init(struct nf_flowtab ++ queue_delayed_work(system_power_efficient_wq, ++ &flowtable->gc_work, HZ); ++ +++ mutex_lock(&flowtable_lock); +++ list_add(&flowtable->list, &flowtables); +++ mutex_unlock(&flowtable_lock); +++ ++ return 0; ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_table_init); ++@@ -425,20 +432,28 @@ static void nf_flow_table_do_cleanup(str ++ } ++ ++ static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, ++- void *data) +++ struct net_device *dev) ++ { ++- nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, data); +++ nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev); ++ flush_delayed_work(&flowtable->gc_work); ++ } ++ ++ void nf_flow_table_cleanup(struct net *net, struct net_device *dev) ++ { ++- nft_flow_table_iterate(net, nf_flow_table_iterate_cleanup, dev); +++ struct nf_flowtable *flowtable; +++ +++ mutex_lock(&flowtable_lock); +++ list_for_each_entry(flowtable, &flowtables, list) +++ nf_flow_table_iterate_cleanup(flowtable, dev); +++ mutex_unlock(&flowtable_lock); ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); ++ ++ void nf_flow_table_free(struct nf_flowtable *flow_table) ++ { +++ mutex_lock(&flowtable_lock); +++ list_del(&flow_table->list); +++ mutex_unlock(&flowtable_lock); ++ cancel_delayed_work_sync(&flow_table->gc_work); ++ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); ++ WARN_ON(!nf_flow_offload_gc_step(flow_table)); ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -5018,23 +5018,6 @@ static const struct nf_flowtable_type *n ++ return ERR_PTR(-ENOENT); ++ } ++ ++-void nft_flow_table_iterate(struct net *net, ++- void (*iter)(struct nf_flowtable *flowtable, void *data), ++- void *data) ++-{ ++- struct nft_flowtable *flowtable; ++- const struct nft_table *table; ++- ++- nfnl_lock(NFNL_SUBSYS_NFTABLES); ++- list_for_each_entry(table, &net->nft.tables, list) { ++- list_for_each_entry(flowtable, &table->flowtables, list) { ++- iter(&flowtable->data, data); ++- } ++- } ++- nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++-} ++-EXPORT_SYMBOL_GPL(nft_flow_table_iterate); ++- ++ static void nft_unregister_flowtable_net_hooks(struct net *net, ++ struct nft_flowtable *flowtable) ++ { +diff --git a/target/linux/generic/backport-4.14/360-v4.18-netfilter-nf_flow_table-make-flow_offload_dead-inlin.patch b/target/linux/generic/backport-4.14/360-v4.18-netfilter-nf_flow_table-make-flow_offload_dead-inlin.patch +new file mode 100644 +index 0000000000..d33400c729 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/360-v4.18-netfilter-nf_flow_table-make-flow_offload_dead-inlin.patch +@@ -0,0 +1,38 @@ ++From: Felix Fietkau ++Date: Sun, 25 Feb 2018 15:37:27 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: make flow_offload_dead inline ++ ++It is too trivial to keep as a separate exported function ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -103,7 +103,10 @@ void nf_flow_table_cleanup(struct net *n ++ int nf_flow_table_init(struct nf_flowtable *flow_table); ++ void nf_flow_table_free(struct nf_flowtable *flow_table); ++ ++-void flow_offload_dead(struct flow_offload *flow); +++static inline void flow_offload_dead(struct flow_offload *flow) +++{ +++ flow->flags |= FLOW_OFFLOAD_DYING; +++} ++ ++ int nf_flow_snat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -113,12 +113,6 @@ void flow_offload_free(struct flow_offlo ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_free); ++ ++-void flow_offload_dead(struct flow_offload *flow) ++-{ ++- flow->flags |= FLOW_OFFLOAD_DYING; ++-} ++-EXPORT_SYMBOL_GPL(flow_offload_dead); ++- ++ static u32 flow_offload_hash(const void *data, u32 len, u32 seed) ++ { ++ const struct flow_offload_tuple *tuple = data; +diff --git a/target/linux/generic/backport-4.14/361-v4.18-netfilter-nf_flow_table-add-a-new-flow-state-for-tea.patch b/target/linux/generic/backport-4.14/361-v4.18-netfilter-nf_flow_table-add-a-new-flow-state-for-tea.patch +new file mode 100644 +index 0000000000..30cebfac60 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/361-v4.18-netfilter-nf_flow_table-add-a-new-flow-state-for-tea.patch +@@ -0,0 +1,83 @@ ++From: Felix Fietkau ++Date: Sun, 25 Feb 2018 15:38:31 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: add a new flow state for ++ tearing down offloading ++ ++Will be used to tear down the offload entry while keeping the conntrack ++entry alive. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -68,6 +68,7 @@ struct flow_offload_tuple_rhash { ++ #define FLOW_OFFLOAD_SNAT 0x1 ++ #define FLOW_OFFLOAD_DNAT 0x2 ++ #define FLOW_OFFLOAD_DYING 0x4 +++#define FLOW_OFFLOAD_TEARDOWN 0x8 ++ ++ struct flow_offload { ++ struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; ++@@ -103,6 +104,7 @@ void nf_flow_table_cleanup(struct net *n ++ int nf_flow_table_init(struct nf_flowtable *flow_table); ++ void nf_flow_table_free(struct nf_flowtable *flow_table); ++ +++void flow_offload_teardown(struct flow_offload *flow); ++ static inline void flow_offload_dead(struct flow_offload *flow) ++ { ++ flow->flags |= FLOW_OFFLOAD_DYING; ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -174,6 +174,12 @@ static void flow_offload_del(struct nf_f ++ flow_offload_free(flow); ++ } ++ +++void flow_offload_teardown(struct flow_offload *flow) +++{ +++ flow->flags |= FLOW_OFFLOAD_TEARDOWN; +++} +++EXPORT_SYMBOL_GPL(flow_offload_teardown); +++ ++ struct flow_offload_tuple_rhash * ++ flow_offload_lookup(struct nf_flowtable *flow_table, ++ struct flow_offload_tuple *tuple) ++@@ -226,11 +232,6 @@ static inline bool nf_flow_has_expired(c ++ return (__s32)(flow->timeout - (u32)jiffies) <= 0; ++ } ++ ++-static inline bool nf_flow_is_dying(const struct flow_offload *flow) ++-{ ++- return flow->flags & FLOW_OFFLOAD_DYING; ++-} ++- ++ static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) ++ { ++ struct flow_offload_tuple_rhash *tuplehash; ++@@ -258,7 +259,8 @@ static int nf_flow_offload_gc_step(struc ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++ ++ if (nf_flow_has_expired(flow) || ++- nf_flow_is_dying(flow)) +++ (flow->flags & (FLOW_OFFLOAD_DYING | +++ FLOW_OFFLOAD_TEARDOWN))) ++ flow_offload_del(flow_table, flow); ++ } ++ out: ++@@ -419,10 +421,14 @@ static void nf_flow_table_do_cleanup(str ++ { ++ struct net_device *dev = data; ++ ++- if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) +++ if (!dev) { +++ flow_offload_teardown(flow); ++ return; +++ } ++ ++- flow_offload_dead(flow); +++ if (flow->tuplehash[0].tuple.iifidx == dev->ifindex || +++ flow->tuplehash[1].tuple.iifidx == dev->ifindex) +++ flow_offload_dead(flow); ++ } ++ ++ static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, +diff --git a/target/linux/generic/backport-4.14/362-v4.18-netfilter-nf_flow_table-in-flow_offload_lookup-skip-.patch b/target/linux/generic/backport-4.14/362-v4.18-netfilter-nf_flow_table-in-flow_offload_lookup-skip-.patch +new file mode 100644 +index 0000000000..d14ac97a59 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/362-v4.18-netfilter-nf_flow_table-in-flow_offload_lookup-skip-.patch +@@ -0,0 +1,36 @@ ++From: Felix Fietkau ++Date: Sun, 25 Feb 2018 15:39:56 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: in flow_offload_lookup, skip ++ entries being deleted ++ ++Preparation for sending flows back to the slow path ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -184,8 +184,21 @@ struct flow_offload_tuple_rhash * ++ flow_offload_lookup(struct nf_flowtable *flow_table, ++ struct flow_offload_tuple *tuple) ++ { ++- return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, ++- nf_flow_offload_rhash_params); +++ struct flow_offload_tuple_rhash *tuplehash; +++ struct flow_offload *flow; +++ int dir; +++ +++ tuplehash = rhashtable_lookup_fast(&flow_table->rhashtable, tuple, +++ nf_flow_offload_rhash_params); +++ if (!tuplehash) +++ return NULL; +++ +++ dir = tuplehash->tuple.dir; +++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +++ if (flow->flags & (FLOW_OFFLOAD_DYING | FLOW_OFFLOAD_TEARDOWN)) +++ return NULL; +++ +++ return tuplehash; ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_lookup); ++ +diff --git a/target/linux/generic/backport-4.14/363-v4.18-netfilter-nf_flow_table-add-support-for-sending-flow.patch b/target/linux/generic/backport-4.14/363-v4.18-netfilter-nf_flow_table-add-support-for-sending-flow.patch +new file mode 100644 +index 0000000000..905880fead +--- /dev/null ++++ b/target/linux/generic/backport-4.14/363-v4.18-netfilter-nf_flow_table-add-support-for-sending-flow.patch +@@ -0,0 +1,99 @@ ++From: Felix Fietkau ++Date: Sun, 25 Feb 2018 15:41:11 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: add support for sending flows ++ back to the slow path ++ ++Reset the timeout. For TCP, also set the state to indicate to use the ++next incoming packets to reset window tracking. ++This allows the slow path to take over again once the offload state has ++been torn down ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -100,6 +100,43 @@ err_ct_refcnt: ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_alloc); ++ +++static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp) +++{ +++ tcp->state = TCP_CONNTRACK_ESTABLISHED; +++ tcp->seen[0].td_maxwin = 0; +++ tcp->seen[1].td_maxwin = 0; +++} +++ +++static void flow_offload_fixup_ct_state(struct nf_conn *ct) +++{ +++ const struct nf_conntrack_l4proto *l4proto; +++ struct net *net = nf_ct_net(ct); +++ unsigned int *timeouts; +++ unsigned int timeout; +++ int l4num; +++ +++ l4num = nf_ct_protonum(ct); +++ if (l4num == IPPROTO_TCP) +++ flow_offload_fixup_tcp(&ct->proto.tcp); +++ +++ l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), l4num); +++ if (!l4proto) +++ return; +++ +++ timeouts = l4proto->get_timeouts(net); +++ if (!timeouts) +++ return; +++ +++ if (l4num == IPPROTO_TCP) +++ timeout = timeouts[TCP_CONNTRACK_ESTABLISHED]; +++ else if (l4num == IPPROTO_UDP) +++ timeout = timeouts[UDP_CT_REPLIED]; +++ else +++ return; +++ +++ ct->timeout = nfct_time_stamp + timeout; +++} +++ ++ void flow_offload_free(struct flow_offload *flow) ++ { ++ struct flow_offload_entry *e; ++@@ -107,7 +144,8 @@ void flow_offload_free(struct flow_offlo ++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); ++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); ++ e = container_of(flow, struct flow_offload_entry, flow); ++- nf_ct_delete(e->ct, 0, 0); +++ if (flow->flags & FLOW_OFFLOAD_DYING) +++ nf_ct_delete(e->ct, 0, 0); ++ nf_ct_put(e->ct); ++ kfree_rcu(e, rcu_head); ++ } ++@@ -164,6 +202,8 @@ EXPORT_SYMBOL_GPL(flow_offload_add); ++ static void flow_offload_del(struct nf_flowtable *flow_table, ++ struct flow_offload *flow) ++ { +++ struct flow_offload_entry *e; +++ ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++ nf_flow_offload_rhash_params); ++@@ -171,12 +211,20 @@ static void flow_offload_del(struct nf_f ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++ nf_flow_offload_rhash_params); ++ +++ e = container_of(flow, struct flow_offload_entry, flow); +++ clear_bit(IPS_OFFLOAD_BIT, &e->ct->status); +++ ++ flow_offload_free(flow); ++ } ++ ++ void flow_offload_teardown(struct flow_offload *flow) ++ { +++ struct flow_offload_entry *e; +++ ++ flow->flags |= FLOW_OFFLOAD_TEARDOWN; +++ +++ e = container_of(flow, struct flow_offload_entry, flow); +++ flow_offload_fixup_ct_state(e->ct); ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_teardown); ++ +diff --git a/target/linux/generic/backport-4.14/364-v4.18-netfilter-nf_flow_table-tear-down-TCP-flows-if-RST-o.patch b/target/linux/generic/backport-4.14/364-v4.18-netfilter-nf_flow_table-tear-down-TCP-flows-if-RST-o.patch +new file mode 100644 +index 0000000000..8b0024cd8d +--- /dev/null ++++ b/target/linux/generic/backport-4.14/364-v4.18-netfilter-nf_flow_table-tear-down-TCP-flows-if-RST-o.patch +@@ -0,0 +1,81 @@ ++From: Felix Fietkau ++Date: Sun, 25 Feb 2018 15:42:58 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: tear down TCP flows if RST or ++ FIN was seen ++ ++Allow the slow path to handle the shutdown of the connection with proper ++timeouts ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table_ip.c +++++ b/net/netfilter/nf_flow_table_ip.c ++@@ -15,6 +15,23 @@ ++ #include ++ #include ++ +++static int nf_flow_tcp_state_check(struct flow_offload *flow, +++ struct sk_buff *skb, unsigned int thoff) +++{ +++ struct tcphdr *tcph; +++ +++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph))) +++ return -1; +++ +++ tcph = (void *)(skb_network_header(skb) + thoff); +++ if (unlikely(tcph->fin || tcph->rst)) { +++ flow_offload_teardown(flow); +++ return -1; +++ } +++ +++ return 0; +++} +++ ++ static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, ++ __be32 addr, __be32 new_addr) ++ { ++@@ -118,10 +135,9 @@ static int nf_flow_dnat_ip(const struct ++ } ++ ++ static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++- enum flow_offload_tuple_dir dir) +++ unsigned int thoff, enum flow_offload_tuple_dir dir) ++ { ++ struct iphdr *iph = ip_hdr(skb); ++- unsigned int thoff = iph->ihl * 4; ++ ++ if (flow->flags & FLOW_OFFLOAD_SNAT && ++ (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || ++@@ -201,6 +217,7 @@ nf_flow_offload_ip_hook(void *priv, stru ++ struct flow_offload *flow; ++ struct net_device *outdev; ++ const struct rtable *rt; +++ unsigned int thoff; ++ struct iphdr *iph; ++ __be32 nexthop; ++ ++@@ -229,8 +246,12 @@ nf_flow_offload_ip_hook(void *priv, stru ++ if (skb_try_make_writable(skb, sizeof(*iph))) ++ return NF_DROP; ++ +++ thoff = ip_hdr(skb)->ihl * 4; +++ if (nf_flow_tcp_state_check(flow, skb, thoff)) +++ return NF_ACCEPT; +++ ++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && ++- nf_flow_nat_ip(flow, skb, dir) < 0) +++ nf_flow_nat_ip(flow, skb, thoff, dir) < 0) ++ return NF_DROP; ++ ++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; ++@@ -438,6 +459,9 @@ nf_flow_offload_ipv6_hook(void *priv, st ++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ return NF_ACCEPT; ++ +++ if (nf_flow_tcp_state_check(flow, skb, sizeof(*ip6h))) +++ return NF_ACCEPT; +++ ++ if (skb_try_make_writable(skb, sizeof(*ip6h))) ++ return NF_DROP; ++ +diff --git a/target/linux/generic/backport-4.14/365-v4.16-netfilter-nf_flow_table-fix-checksum-when-handling-D.patch b/target/linux/generic/backport-4.14/365-v4.16-netfilter-nf_flow_table-fix-checksum-when-handling-D.patch +new file mode 100644 +index 0000000000..372c8d59ef +--- /dev/null ++++ b/target/linux/generic/backport-4.14/365-v4.16-netfilter-nf_flow_table-fix-checksum-when-handling-D.patch +@@ -0,0 +1,19 @@ ++From: Felix Fietkau ++Date: Sun, 25 Feb 2018 17:22:55 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: fix checksum when handling DNAT ++ ++Add a missing call to csum_replace4 like on SNAT ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table_ip.c +++++ b/net/netfilter/nf_flow_table_ip.c ++@@ -130,6 +130,7 @@ static int nf_flow_dnat_ip(const struct ++ default: ++ return -1; ++ } +++ csum_replace4(&iph->check, addr, new_addr); ++ ++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++ } +diff --git a/target/linux/generic/backport-4.14/366-netfilter-nft_flow_offload-Fix-reverse-route-lookup.patch b/target/linux/generic/backport-4.14/366-netfilter-nft_flow_offload-Fix-reverse-route-lookup.patch +new file mode 100644 +index 0000000000..e91aaa91d7 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/366-netfilter-nft_flow_offload-Fix-reverse-route-lookup.patch +@@ -0,0 +1,39 @@ ++From: wenxu ++Date: Wed, 9 Jan 2019 10:40:11 +0800 ++Subject: [PATCH] netfilter: nft_flow_offload: Fix reverse route lookup ++ ++Using the following example: ++ ++ client 1.1.1.7 ---> 2.2.2.7 which dnat to 10.0.0.7 server ++ ++The first reply packet (ie. syn+ack) uses an incorrect destination ++address for the reverse route lookup since it uses: ++ ++ daddr = ct->tuplehash[!dir].tuple.dst.u3.ip; ++ ++which is 2.2.2.7 in the scenario that is described above, while this ++should be: ++ ++ daddr = ct->tuplehash[dir].tuple.src.u3.ip; ++ ++that is 10.0.0.7. ++ ++Signed-off-by: wenxu ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -29,10 +29,10 @@ static int nft_flow_route(const struct n ++ memset(&fl, 0, sizeof(fl)); ++ switch (nft_pf(pkt)) { ++ case NFPROTO_IPV4: ++- fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip; +++ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; ++ break; ++ case NFPROTO_IPV6: ++- fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6; +++ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; ++ break; ++ } ++ +diff --git a/target/linux/generic/backport-4.14/367-v4.18-netfilter-nf_flow_table-add-missing-condition-for-TC.patch b/target/linux/generic/backport-4.14/367-v4.18-netfilter-nf_flow_table-add-missing-condition-for-TC.patch +new file mode 100644 +index 0000000000..2a470f77e3 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/367-v4.18-netfilter-nf_flow_table-add-missing-condition-for-TC.patch +@@ -0,0 +1,48 @@ ++From: Felix Fietkau ++Date: Fri, 23 Mar 2018 17:15:22 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: add missing condition for TCP state ++ check ++ ++Avoid looking at unrelated fields in UDP packets ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table_ip.c +++++ b/net/netfilter/nf_flow_table_ip.c ++@@ -15,11 +15,14 @@ ++ #include ++ #include ++ ++-static int nf_flow_tcp_state_check(struct flow_offload *flow, ++- struct sk_buff *skb, unsigned int thoff) +++static int nf_flow_state_check(struct flow_offload *flow, int proto, +++ struct sk_buff *skb, unsigned int thoff) ++ { ++ struct tcphdr *tcph; ++ +++ if (proto != IPPROTO_TCP) +++ return 0; +++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph))) ++ return -1; ++ ++@@ -248,7 +251,7 @@ nf_flow_offload_ip_hook(void *priv, stru ++ return NF_DROP; ++ ++ thoff = ip_hdr(skb)->ihl * 4; ++- if (nf_flow_tcp_state_check(flow, skb, thoff)) +++ if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff)) ++ return NF_ACCEPT; ++ ++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && ++@@ -460,7 +463,8 @@ nf_flow_offload_ipv6_hook(void *priv, st ++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ return NF_ACCEPT; ++ ++- if (nf_flow_tcp_state_check(flow, skb, sizeof(*ip6h))) +++ if (nf_flow_state_check(flow, ipv6_hdr(skb)->nexthdr, skb, +++ sizeof(*ip6h))) ++ return NF_ACCEPT; ++ ++ if (skb_try_make_writable(skb, sizeof(*ip6h))) +diff --git a/target/linux/generic/backport-4.14/368-v4.18-netfilter-nf_flow_table-fix-offloading-connections-w.patch b/target/linux/generic/backport-4.14/368-v4.18-netfilter-nf_flow_table-fix-offloading-connections-w.patch +new file mode 100644 +index 0000000000..f3d83a1536 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/368-v4.18-netfilter-nf_flow_table-fix-offloading-connections-w.patch +@@ -0,0 +1,23 @@ ++From: Felix Fietkau ++Date: Fri, 23 Mar 2018 19:12:30 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: fix offloading connections with ++ SNAT+DNAT ++ ++Pass all NAT types to the flow offload struct, otherwise parts of the ++address/port pair do not get translated properly, causing connection ++stalls ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -84,7 +84,7 @@ flow_offload_alloc(struct nf_conn *ct, s ++ ++ if (ct->status & IPS_SRC_NAT) ++ flow->flags |= FLOW_OFFLOAD_SNAT; ++- else if (ct->status & IPS_DST_NAT) +++ if (ct->status & IPS_DST_NAT) ++ flow->flags |= FLOW_OFFLOAD_DNAT; ++ ++ return flow; +diff --git a/target/linux/generic/backport-4.14/369-v4.18-netfilter-nf_flow_table-attach-dst-to-skbs.patch b/target/linux/generic/backport-4.14/369-v4.18-netfilter-nf_flow_table-attach-dst-to-skbs.patch +new file mode 100644 +index 0000000000..ad72d65c77 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/369-v4.18-netfilter-nf_flow_table-attach-dst-to-skbs.patch +@@ -0,0 +1,49 @@ ++From: "Jason A. Donenfeld" ++Date: Wed, 30 May 2018 20:43:15 +0200 ++Subject: [PATCH] netfilter: nf_flow_table: attach dst to skbs ++ ++Some drivers, such as vxlan and wireguard, use the skb's dst in order to ++determine things like PMTU. They therefore loose functionality when flow ++offloading is enabled. So, we ensure the skb has it before xmit'ing it ++in the offloading path. ++ ++Signed-off-by: Jason A. Donenfeld ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/net/netfilter/nf_flow_table_ip.c +++++ b/net/netfilter/nf_flow_table_ip.c ++@@ -220,7 +220,7 @@ nf_flow_offload_ip_hook(void *priv, stru ++ enum flow_offload_tuple_dir dir; ++ struct flow_offload *flow; ++ struct net_device *outdev; ++- const struct rtable *rt; +++ struct rtable *rt; ++ unsigned int thoff; ++ struct iphdr *iph; ++ __be32 nexthop; ++@@ -241,7 +241,7 @@ nf_flow_offload_ip_hook(void *priv, stru ++ ++ dir = tuplehash->tuple.dir; ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++- rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; +++ rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache; ++ ++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)) && ++ (ip_hdr(skb)->frag_off & htons(IP_DF)) != 0) ++@@ -264,6 +264,7 @@ nf_flow_offload_ip_hook(void *priv, stru ++ ++ skb->dev = outdev; ++ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); +++ skb_dst_set_noref(skb, &rt->dst); ++ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); ++ ++ return NF_STOLEN; ++@@ -480,6 +481,7 @@ nf_flow_offload_ipv6_hook(void *priv, st ++ ++ skb->dev = outdev; ++ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); +++ skb_dst_set_noref(skb, &rt->dst); ++ neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); ++ ++ return NF_STOLEN; +diff --git a/target/linux/generic/backport-4.14/370-netfilter-nf_flow_table-fix-offloaded-connection-tim.patch b/target/linux/generic/backport-4.14/370-netfilter-nf_flow_table-fix-offloaded-connection-tim.patch +new file mode 100644 +index 0000000000..d82854908f +--- /dev/null ++++ b/target/linux/generic/backport-4.14/370-netfilter-nf_flow_table-fix-offloaded-connection-tim.patch +@@ -0,0 +1,110 @@ ++From: Felix Fietkau ++Date: Wed, 13 Jun 2018 12:33:39 +0200 ++Subject: [PATCH] netfilter: nf_flow_table: fix offloaded connection timeout ++ corner case ++ ++The full teardown of offloaded flows is deferred to a gc work item, ++however processing of packets by netfilter needs to happen immediately ++after a teardown is requested, because the conntrack state needs to be ++fixed up. ++ ++Since the IPS_OFFLOAD_BIT is still kept until the teardown is complete, ++the netfilter conntrack gc can accidentally bump the timeout of a ++connection where offload was just stopped, causing a conntrack entry ++leak. ++ ++Fix this by moving the conntrack timeout bumping from conntrack core to ++the nf_flow_offload and add a check to prevent bogus timeout bumps. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_conntrack_core.c +++++ b/net/netfilter/nf_conntrack_core.c ++@@ -1054,18 +1054,6 @@ static bool gc_worker_can_early_drop(con ++ return false; ++ } ++ ++-#define DAY (86400 * HZ) ++- ++-/* Set an arbitrary timeout large enough not to ever expire, this save ++- * us a check for the IPS_OFFLOAD_BIT from the packet path via ++- * nf_ct_is_expired(). ++- */ ++-static void nf_ct_offload_timeout(struct nf_conn *ct) ++-{ ++- if (nf_ct_expires(ct) < DAY / 2) ++- ct->timeout = nfct_time_stamp + DAY; ++-} ++- ++ static void gc_worker(struct work_struct *work) ++ { ++ unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u); ++@@ -1102,10 +1090,8 @@ static void gc_worker(struct work_struct ++ tmp = nf_ct_tuplehash_to_ctrack(h); ++ ++ scanned++; ++- if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) { ++- nf_ct_offload_timeout(tmp); +++ if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) ++ continue; ++- } ++ ++ if (nf_ct_is_expired(tmp)) { ++ nf_ct_gc_expired(tmp); ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -185,8 +185,27 @@ static const struct rhashtable_params nf ++ .automatic_shrinking = true, ++ }; ++ +++#define DAY (86400 * HZ) +++ +++/* Set an arbitrary timeout large enough not to ever expire, this save +++ * us a check for the IPS_OFFLOAD_BIT from the packet path via +++ * nf_ct_is_expired(). +++ */ +++static void nf_ct_offload_timeout(struct flow_offload *flow) +++{ +++ struct flow_offload_entry *entry; +++ struct nf_conn *ct; +++ +++ entry = container_of(flow, struct flow_offload_entry, flow); +++ ct = entry->ct; +++ +++ if (nf_ct_expires(ct) < DAY / 2) +++ ct->timeout = nfct_time_stamp + DAY; +++} +++ ++ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) ++ { +++ nf_ct_offload_timeout(flow); ++ flow->timeout = (u32)jiffies; ++ ++ rhashtable_insert_fast(&flow_table->rhashtable, ++@@ -307,6 +326,8 @@ static int nf_flow_offload_gc_step(struc ++ rhashtable_walk_start(&hti); ++ ++ while ((tuplehash = rhashtable_walk_next(&hti))) { +++ bool teardown; +++ ++ if (IS_ERR(tuplehash)) { ++ err = PTR_ERR(tuplehash); ++ if (err != -EAGAIN) ++@@ -319,9 +340,13 @@ static int nf_flow_offload_gc_step(struc ++ ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++ ++- if (nf_flow_has_expired(flow) || ++- (flow->flags & (FLOW_OFFLOAD_DYING | ++- FLOW_OFFLOAD_TEARDOWN))) +++ teardown = flow->flags & (FLOW_OFFLOAD_DYING | +++ FLOW_OFFLOAD_TEARDOWN); +++ +++ if (!teardown) +++ nf_ct_offload_timeout(flow); +++ +++ if (nf_flow_has_expired(flow) || teardown) ++ flow_offload_del(flow_table, flow); ++ } ++ out: +diff --git a/target/linux/generic/backport-4.14/371-netfilter-nf_flow_table-fix-up-ct-state-of-flows-aft.patch b/target/linux/generic/backport-4.14/371-netfilter-nf_flow_table-fix-up-ct-state-of-flows-aft.patch +new file mode 100644 +index 0000000000..fb14a284ae +--- /dev/null ++++ b/target/linux/generic/backport-4.14/371-netfilter-nf_flow_table-fix-up-ct-state-of-flows-aft.patch +@@ -0,0 +1,24 @@ ++From: Felix Fietkau ++Date: Thu, 14 Jun 2018 11:20:09 +0200 ++Subject: [PATCH] netfilter: nf_flow_table: fix up ct state of flows after ++ timeout ++ ++If a connection simply times out instead of being torn down, it is left ++active with a long timeout. Fix this by calling flow_offload_fixup_ct_state ++here as well. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -233,6 +233,9 @@ static void flow_offload_del(struct nf_f ++ e = container_of(flow, struct flow_offload_entry, flow); ++ clear_bit(IPS_OFFLOAD_BIT, &e->ct->status); ++ +++ if (!(flow->flags & FLOW_OFFLOAD_TEARDOWN)) +++ flow_offload_fixup_ct_state(e->ct); +++ ++ flow_offload_free(flow); ++ } ++ +diff --git a/target/linux/generic/backport-4.14/372-netfilter-nft_flow_offload-fix-interaction-with-vrf-.patch b/target/linux/generic/backport-4.14/372-netfilter-nft_flow_offload-fix-interaction-with-vrf-.patch +new file mode 100644 +index 0000000000..f0a8b19eec +--- /dev/null ++++ b/target/linux/generic/backport-4.14/372-netfilter-nft_flow_offload-fix-interaction-with-vrf-.patch +@@ -0,0 +1,86 @@ ++From: wenxu ++Date: Thu, 10 Jan 2019 14:51:35 +0800 ++Subject: [PATCH] netfilter: nft_flow_offload: fix interaction with vrf slave ++ device ++ ++In the forward chain, the iif is changed from slave device to master vrf ++device. Thus, flow offload does not find a match on the lower slave ++device. ++ ++This patch uses the cached route, ie. dst->dev, to update the iif and ++oif fields in the flow entry. ++ ++After this patch, the following example works fine: ++ ++ # ip addr add dev eth0 1.1.1.1/24 ++ # ip addr add dev eth1 10.0.0.1/24 ++ # ip link add user1 type vrf table 1 ++ # ip l set user1 up ++ # ip l set dev eth0 master user1 ++ # ip l set dev eth1 master user1 ++ ++ # nft add table firewall ++ # nft add flowtable f fb1 { hook ingress priority 0 \; devices = { eth0, eth1 } \; } ++ # nft add chain f ftb-all {type filter hook forward priority 0 \; policy accept \; } ++ # nft add rule f ftb-all ct zone 1 ip protocol tcp flow offload @fb1 ++ # nft add rule f ftb-all ct zone 1 ip protocol udp flow offload @fb1 ++ ++Signed-off-by: wenxu ++Signed-off-by: Pablo Neira Ayuso ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -84,7 +84,6 @@ struct flow_offload { ++ struct nf_flow_route { ++ struct { ++ struct dst_entry *dst; ++- int ifindex; ++ } tuple[FLOW_OFFLOAD_DIR_MAX]; ++ }; ++ ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -28,6 +28,7 @@ flow_offload_fill_dir(struct flow_offloa ++ { ++ struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; ++ struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; +++ struct dst_entry *other_dst = route->tuple[!dir].dst; ++ struct dst_entry *dst = route->tuple[dir].dst; ++ ++ ft->dir = dir; ++@@ -50,8 +51,8 @@ flow_offload_fill_dir(struct flow_offloa ++ ft->src_port = ctt->src.u.tcp.port; ++ ft->dst_port = ctt->dst.u.tcp.port; ++ ++- ft->iifidx = route->tuple[dir].ifindex; ++- ft->oifidx = route->tuple[!dir].ifindex; +++ ft->iifidx = other_dst->dev->ifindex; +++ ft->oifidx = dst->dev->ifindex; ++ ft->dst_cache = dst; ++ } ++ ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -30,9 +30,11 @@ static int nft_flow_route(const struct n ++ switch (nft_pf(pkt)) { ++ case NFPROTO_IPV4: ++ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; +++ fl.u.ip4.flowi4_oif = nft_in(pkt)->ifindex; ++ break; ++ case NFPROTO_IPV6: ++ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; +++ fl.u.ip6.flowi6_oif = nft_in(pkt)->ifindex; ++ break; ++ } ++ ++@@ -41,9 +43,7 @@ static int nft_flow_route(const struct n ++ return -ENOENT; ++ ++ route->tuple[dir].dst = this_dst; ++- route->tuple[dir].ifindex = nft_in(pkt)->ifindex; ++ route->tuple[!dir].dst = other_dst; ++- route->tuple[!dir].ifindex = nft_out(pkt)->ifindex; ++ ++ return 0; ++ } +diff --git a/target/linux/generic/backport-4.14/380-v5.3-net-sched-Introduce-act_ctinfo-action.patch b/target/linux/generic/backport-4.14/380-v5.3-net-sched-Introduce-act_ctinfo-action.patch +new file mode 100644 +index 0000000000..96f458f9c9 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/380-v5.3-net-sched-Introduce-act_ctinfo-action.patch +@@ -0,0 +1,640 @@ ++From 85fc2a6db8279c5e43c38ef7e715d14e57287997 Mon Sep 17 00:00:00 2001 ++From: Kevin Darbyshire-Bryant ++Date: Wed, 13 Mar 2019 20:54:49 +0000 ++Subject: [PATCH] net: sched: Backport Introduce act_ctinfo action ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++ctinfo is a new tc filter action module. It is designed to restore ++information contained in firewall conntrack marks to other packet fields ++and is typically used on packet ingress paths. At present it has two ++independent sub-functions or operating modes, DSCP restoration mode & ++skb mark restoration mode. ++ ++The DSCP restore mode: ++ ++This mode copies DSCP values that have been placed in the firewall ++conntrack mark back into the IPv4/v6 diffserv fields of relevant ++packets. ++ ++The DSCP restoration is intended for use and has been found useful for ++restoring ingress classifications based on egress classifications across ++links that bleach or otherwise change DSCP, typically home ISP Internet ++links. Restoring DSCP on ingress on the WAN link allows qdiscs such as ++but by no means limited to CAKE to shape inbound packets according to ++policies that are easier to set & mark on egress. ++ ++Ingress classification is traditionally a challenging task since ++iptables rules haven't yet run and tc filter/eBPF programs are pre-NAT ++lookups, hence are unable to see internal IPv4 addresses as used on the ++typical home masquerading gateway. Thus marking the connection in some ++manner on egress for later restoration of classification on ingress is ++easier to implement. ++ ++Parameters related to DSCP restore mode: ++ ++dscpmask - a 32 bit mask of 6 contiguous bits and indicate bits of the ++conntrack mark field contain the DSCP value to be restored. ++ ++statemask - a 32 bit mask of (usually) 1 bit length, outside the area ++specified by dscpmask. This represents a conditional operation flag ++whereby the DSCP is only restored if the flag is set. This is useful to ++implement a 'one shot' iptables based classification where the ++'complicated' iptables rules are only run once to classify the ++connection on initial (egress) packet and subsequent packets are all ++marked/restored with the same DSCP. A mask of zero disables the ++conditional behaviour ie. the conntrack mark DSCP bits are always ++restored to the ip diffserv field (assuming the conntrack entry is found ++& the skb is an ipv4/ipv6 type) ++ ++e.g. dscpmask 0xfc000000 statemask 0x01000000 ++ ++|----0xFC----conntrack mark----000000---| ++| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| ++| DSCP | unused | flag |unused | ++|-----------------------0x01---000000---| ++ | | ++ | | ++ ---| Conditional flag ++ v only restore if set ++|-ip diffserv-| ++| 6 bits | ++|-------------| ++ ++The skb mark restore mode (cpmark): ++ ++This mode copies the firewall conntrack mark to the skb's mark field. ++It is completely the functional equivalent of the existing act_connmark ++action with the additional feature of being able to apply a mask to the ++restored value. ++ ++Parameters related to skb mark restore mode: ++ ++mask - a 32 bit mask applied to the firewall conntrack mark to mask out ++bits unwanted for restoration. This can be useful where the conntrack ++mark is being used for different purposes by different applications. If ++not specified and by default the whole mark field is copied (i.e. ++default mask of 0xffffffff) ++ ++e.g. mask 0x00ffffff to mask out the top 8 bits being used by the ++aforementioned DSCP restore mode. ++ ++|----0x00----conntrack mark----ffffff---| ++| Bits 31-24 | | ++| DSCP & flag| some value here | ++|---------------------------------------| ++ | ++ | ++ v ++|------------skb mark-------------------| ++| | | ++| zeroed | | ++|---------------------------------------| ++ ++Overall parameters: ++ ++zone - conntrack zone ++ ++control - action related control (reclassify | pipe | drop | continue | ++ok | goto chain ) ++ ++Signed-off-by: Kevin Darbyshire-Bryant ++Reviewed-by: Toke Høiland-Jørgensen ++Acked-by: Cong Wang ++Signed-off-by: David S. Miller ++ ++Backport ++Signed-off-by: Kevin Darbyshire-Bryant ++--- ++ include/net/tc_act/tc_ctinfo.h | 33 +++ ++ include/uapi/linux/pkt_cls.h | 3 +- ++ include/uapi/linux/tc_act/tc_ctinfo.h | 29 ++ ++ net/sched/Kconfig | 13 + ++ net/sched/Makefile | 1 + ++ net/sched/act_ctinfo.c | 405 ++++++++++++++++++++++++++ ++ 6 files changed, 482 insertions(+), 1 deletion(-) ++ create mode 100644 include/net/tc_act/tc_ctinfo.h ++ create mode 100644 include/uapi/linux/tc_act/tc_ctinfo.h ++ create mode 100644 net/sched/act_ctinfo.c ++ ++--- /dev/null +++++ b/include/net/tc_act/tc_ctinfo.h ++@@ -0,0 +1,33 @@ +++/* SPDX-License-Identifier: GPL-2.0 */ +++#ifndef __NET_TC_CTINFO_H +++#define __NET_TC_CTINFO_H +++ +++#include +++ +++struct tcf_ctinfo_params { +++ struct rcu_head rcu; +++ struct net *net; +++ u32 dscpmask; +++ u32 dscpstatemask; +++ u32 cpmarkmask; +++ u16 zone; +++ u8 mode; +++ u8 dscpmaskshift; +++}; +++ +++struct tcf_ctinfo { +++ struct tc_action common; +++ struct tcf_ctinfo_params __rcu *params; +++ u64 stats_dscp_set; +++ u64 stats_dscp_error; +++ u64 stats_cpmark_set; +++}; +++ +++enum { +++ CTINFO_MODE_DSCP = BIT(0), +++ CTINFO_MODE_CPMARK = BIT(1) +++}; +++ +++#define to_ctinfo(a) ((struct tcf_ctinfo *)a) +++ +++#endif /* __NET_TC_CTINFO_H */ ++--- a/include/uapi/linux/pkt_cls.h +++++ b/include/uapi/linux/pkt_cls.h ++@@ -66,7 +66,8 @@ enum { ++ TCA_ID_UNSPEC=0, ++ TCA_ID_POLICE=1, ++ /* other actions go here */ ++- __TCA_ID_MAX=255 +++ TCA_ID_CTINFO=27, +++ __TCA_ID_MAX = 255 ++ }; ++ ++ #define TCA_ID_MAX __TCA_ID_MAX ++--- /dev/null +++++ b/include/uapi/linux/tc_act/tc_ctinfo.h ++@@ -0,0 +1,29 @@ +++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +++#ifndef __UAPI_TC_CTINFO_H +++#define __UAPI_TC_CTINFO_H +++ +++#include +++#include +++ +++struct tc_ctinfo { +++ tc_gen; +++}; +++ +++enum { +++ TCA_CTINFO_UNSPEC, +++ TCA_CTINFO_PAD, +++ TCA_CTINFO_TM, +++ TCA_CTINFO_ACT, +++ TCA_CTINFO_ZONE, +++ TCA_CTINFO_PARMS_DSCP_MASK, +++ TCA_CTINFO_PARMS_DSCP_STATEMASK, +++ TCA_CTINFO_PARMS_CPMARK_MASK, +++ TCA_CTINFO_STATS_DSCP_SET, +++ TCA_CTINFO_STATS_DSCP_ERROR, +++ TCA_CTINFO_STATS_CPMARK_SET, +++ __TCA_CTINFO_MAX +++}; +++ +++#define TCA_CTINFO_MAX (__TCA_CTINFO_MAX - 1) +++ +++#endif ++--- a/net/sched/Kconfig +++++ b/net/sched/Kconfig ++@@ -808,6 +808,19 @@ config NET_ACT_CONNMARK ++ To compile this code as a module, choose M here: the ++ module will be called act_connmark. ++ +++config NET_ACT_CTINFO +++ tristate "Netfilter Connmark to DSCP Retriever" +++ depends on NET_CLS_ACT && NETFILTER && IP_NF_IPTABLES +++ depends on NF_CONNTRACK && NF_CONNTRACK_MARK +++ help +++ Say Y here to allow transfer of a connmark stored DSCP into +++ ipv4/v6 diffserv +++ +++ If unsure, say N. +++ +++ To compile this code as a module, choose M here: the +++ module will be called act_ctinfo. +++ ++ config NET_ACT_SKBMOD ++ tristate "skb data modification action" ++ depends on NET_CLS_ACT ++--- a/net/sched/Makefile +++++ b/net/sched/Makefile ++@@ -21,6 +21,7 @@ obj-$(CONFIG_NET_ACT_CSUM) += act_csum.o ++ obj-$(CONFIG_NET_ACT_VLAN) += act_vlan.o ++ obj-$(CONFIG_NET_ACT_BPF) += act_bpf.o ++ obj-$(CONFIG_NET_ACT_CONNMARK) += act_connmark.o +++obj-$(CONFIG_NET_ACT_CTINFO) += act_ctinfo.o ++ obj-$(CONFIG_NET_ACT_SKBMOD) += act_skbmod.o ++ obj-$(CONFIG_NET_ACT_IFE) += act_ife.o ++ obj-$(CONFIG_NET_IFE_SKBMARK) += act_meta_mark.o ++--- /dev/null +++++ b/net/sched/act_ctinfo.c ++@@ -0,0 +1,405 @@ +++// SPDX-License-Identifier: GPL-2.0+ +++/* net/sched/act_ctinfo.c netfilter ctinfo connmark actions +++ * +++ * Copyright (c) 2019 Kevin Darbyshire-Bryant +++ */ +++ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++#include +++#include +++#include +++#include +++ +++static struct tc_action_ops act_ctinfo_ops; +++static unsigned int ctinfo_net_id; +++ +++static void tcf_ctinfo_dscp_set(struct nf_conn *ct, struct tcf_ctinfo *ca, +++ struct tcf_ctinfo_params *cp, +++ struct sk_buff *skb, int wlen, int proto) +++{ +++ u8 dscp,newdscp; +++ +++ newdscp = (((ct->mark & cp->dscpmask) >> cp->dscpmaskshift) << 2) & +++ ~INET_ECN_MASK; +++ +++ /* mark contains DSCP so restore DSCP bits from ct->mark into diffserv */ +++ /* using overlimits stats to count how many DSCP updates */ +++ switch (proto) { +++ case NFPROTO_IPV4: +++ dscp = ipv4_get_dsfield(ip_hdr(skb)) & ~INET_ECN_MASK; +++ if (dscp != newdscp) { +++ if (likely(!skb_try_make_writable(skb, wlen))) { +++ ipv4_change_dsfield(ip_hdr(skb), +++ INET_ECN_MASK, +++ newdscp); +++ ca->stats_dscp_set++; +++ } else { +++ ca->stats_dscp_error++; +++ } +++ } +++ break; +++ case NFPROTO_IPV6: +++ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & ~INET_ECN_MASK; +++ if (dscp != newdscp) { +++ if (likely(!skb_try_make_writable(skb, wlen))) { +++ ipv6_change_dsfield(ipv6_hdr(skb), +++ INET_ECN_MASK, +++ newdscp); +++ ca->stats_dscp_set++; +++ } else { +++ ca->stats_dscp_error++; +++ } +++ } +++ break; +++ default: +++ break; +++ } +++} +++ +++static void tcf_ctinfo_cpmark_set(struct nf_conn *ct, struct tcf_ctinfo *ca, +++ struct tcf_ctinfo_params *cp, +++ struct sk_buff *skb) +++{ +++ ca->stats_cpmark_set++; +++ skb->mark = ct->mark & cp->cpmarkmask; +++} +++ +++static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a, +++ struct tcf_result *res) +++{ +++ const struct nf_conntrack_tuple_hash *thash = NULL; +++ struct tcf_ctinfo *ca = to_ctinfo(a); +++ struct nf_conntrack_tuple tuple; +++ struct nf_conntrack_zone zone; +++ enum ip_conntrack_info ctinfo; +++ struct tcf_ctinfo_params *cp; +++ struct nf_conn *ct; +++ int proto, wlen; +++ int action; +++ +++ cp = rcu_dereference_bh(ca->params); +++ +++ tcf_lastuse_update(&ca->tcf_tm); +++ bstats_update(&ca->tcf_bstats, skb); +++ action = READ_ONCE(ca->tcf_action); +++ +++ wlen = skb_network_offset(skb); +++ if (tc_skb_protocol(skb) == htons(ETH_P_IP)) { +++ wlen += sizeof(struct iphdr); +++ if (!pskb_may_pull(skb, wlen)) +++ goto out; +++ +++ proto = NFPROTO_IPV4; +++ } else if (tc_skb_protocol(skb) == htons(ETH_P_IPV6)) { +++ wlen += sizeof(struct ipv6hdr); +++ if (!pskb_may_pull(skb, wlen)) +++ goto out; +++ +++ proto = NFPROTO_IPV6; +++ } else { +++ goto out; +++ } +++ +++ ct = nf_ct_get(skb, &ctinfo); +++ if (!ct) { /* look harder, usually ingress */ +++ if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), +++ proto, cp->net, &tuple)) +++ goto out; +++ zone.id = cp->zone; +++ zone.dir = NF_CT_DEFAULT_ZONE_DIR; +++ +++ thash = nf_conntrack_find_get(cp->net, &zone, &tuple); +++ if (!thash) +++ goto out; +++ +++ ct = nf_ct_tuplehash_to_ctrack(thash); +++ } +++ +++ if (cp->mode & CTINFO_MODE_DSCP) +++ if (!cp->dscpstatemask || (ct->mark & cp->dscpstatemask)) +++ tcf_ctinfo_dscp_set(ct, ca, cp, skb, wlen, proto); +++ +++ if (cp->mode & CTINFO_MODE_CPMARK) +++ tcf_ctinfo_cpmark_set(ct, ca, cp, skb); +++ +++ if (thash) +++ nf_ct_put(ct); +++out: +++ return action; +++} +++ +++static const struct nla_policy ctinfo_policy[TCA_CTINFO_MAX + 1] = { +++ [TCA_CTINFO_ACT] = { .len = sizeof(struct +++ tc_ctinfo) }, +++ [TCA_CTINFO_ZONE] = { .type = NLA_U16 }, +++ [TCA_CTINFO_PARMS_DSCP_MASK] = { .type = NLA_U32 }, +++ [TCA_CTINFO_PARMS_DSCP_STATEMASK] = { .type = NLA_U32 }, +++ [TCA_CTINFO_PARMS_CPMARK_MASK] = { .type = NLA_U32 }, +++}; +++ +++static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, +++ struct nlattr *est, struct tc_action **a, +++ int ovr, int bind) +++{ +++ struct tc_action_net *tn = net_generic(net, ctinfo_net_id); +++ struct nlattr *tb[TCA_CTINFO_MAX + 1]; +++ struct tcf_ctinfo_params *cp_new; +++/* struct tcf_chain *goto_ch = NULL; */ +++ u32 dscpmask = 0, dscpstatemask; +++ struct tc_ctinfo *actparm; +++ struct tcf_ctinfo *ci; +++ u8 dscpmaskshift; +++ int ret = 0, err; +++ +++ if (!nla) +++ return -EINVAL; +++ +++ err = nla_parse_nested(tb, TCA_CTINFO_MAX, nla, ctinfo_policy, NULL); +++ if (err < 0) +++ return err; +++ +++ if (!tb[TCA_CTINFO_ACT]) +++ return -EINVAL; +++ actparm = nla_data(tb[TCA_CTINFO_ACT]); +++ +++ /* do some basic validation here before dynamically allocating things */ +++ /* that we would otherwise have to clean up. */ +++ if (tb[TCA_CTINFO_PARMS_DSCP_MASK]) { +++ dscpmask = nla_get_u32(tb[TCA_CTINFO_PARMS_DSCP_MASK]); +++ /* need contiguous 6 bit mask */ +++ dscpmaskshift = dscpmask ? __ffs(dscpmask) : 0; +++ if ((~0 & (dscpmask >> dscpmaskshift)) != 0x3f) +++ return -EINVAL; +++ dscpstatemask = tb[TCA_CTINFO_PARMS_DSCP_STATEMASK] ? +++ nla_get_u32(tb[TCA_CTINFO_PARMS_DSCP_STATEMASK]) : 0; +++ /* mask & statemask must not overlap */ +++ if (dscpmask & dscpstatemask) +++ return -EINVAL; +++ } +++ /* done the validation:now to the actual action allocation */ +++ err = tcf_idr_check(tn, actparm->index, a, bind); +++ if (!err) { +++ ret = tcf_idr_create(tn, actparm->index, est, a, +++ &act_ctinfo_ops, bind, false); +++ if (ret) { +++ /* tcf_idr_cleanup(tn, actparm->index); */ +++ return ret; +++ } +++ ret = ACT_P_CREATED; +++ } else if (err > 0) { +++ if (bind) /* don't override defaults */ +++ return 0; +++ if (!ovr) { +++ tcf_idr_release(*a, bind); +++ return -EEXIST; +++ } +++ } else { +++ return err; +++ } +++ +++/* err = tcf_action_check_ctrlact(actparm->action, tp, &goto_ch, extack); +++ if (err < 0) +++ goto release_idr; +++ */ +++ +++ ci = to_ctinfo(*a); +++ +++ cp_new = kzalloc(sizeof(*cp_new), GFP_KERNEL); +++ if (unlikely(!cp_new)) { +++ err = -ENOMEM; +++ goto put_chain; +++ } +++ +++ cp_new->net = net; +++ cp_new->zone = tb[TCA_CTINFO_ZONE] ? +++ nla_get_u16(tb[TCA_CTINFO_ZONE]) : 0; +++ if (dscpmask) { +++ cp_new->dscpmask = dscpmask; +++ cp_new->dscpmaskshift = dscpmaskshift; +++ cp_new->dscpstatemask = dscpstatemask; +++ cp_new->mode |= CTINFO_MODE_DSCP; +++ } +++ +++ if (tb[TCA_CTINFO_PARMS_CPMARK_MASK]) { +++ cp_new->cpmarkmask = nla_get_u32(tb[TCA_CTINFO_PARMS_CPMARK_MASK]); +++ cp_new->mode |= CTINFO_MODE_CPMARK; +++ } +++ +++ spin_lock_bh(&ci->tcf_lock); +++/* goto_ch = tcf_action_set_ctrlact(*a, actparm->action, goto_ch); */ +++ ci->tcf_action = actparm->action; +++ rcu_swap_protected(ci->params, cp_new, +++ lockdep_is_held(&ci->tcf_lock)); +++ spin_unlock_bh(&ci->tcf_lock); +++ +++/* if (goto_ch) +++ tcf_chain_put_by_act(goto_ch); */ +++ if (cp_new) +++ kfree_rcu(cp_new, rcu); +++ +++ if (ret == ACT_P_CREATED) +++ tcf_idr_insert(tn, *a); +++ +++ return ret; +++ +++put_chain: +++/* if (goto_ch) +++ tcf_chain_put_by_act(goto_ch); */ +++/*release_idr:*/ +++ tcf_idr_release(*a, bind); +++ return err; +++} +++ +++static int tcf_ctinfo_dump(struct sk_buff *skb, struct tc_action *a, +++ int bind, int ref) +++{ +++ struct tcf_ctinfo *ci = to_ctinfo(a); +++ struct tc_ctinfo opt = { +++ .index = ci->tcf_index, +++ .refcnt = ci->tcf_refcnt - ref, +++ .bindcnt = ci->tcf_bindcnt - bind, +++ }; +++ unsigned char *b = skb_tail_pointer(skb); +++ struct tcf_ctinfo_params *cp; +++ struct tcf_t t; +++ +++ spin_lock_bh(&ci->tcf_lock); +++ cp = rcu_dereference_protected(ci->params, +++ lockdep_is_held(&ci->tcf_lock)); +++ +++ tcf_tm_dump(&t, &ci->tcf_tm); +++ if (nla_put_64bit(skb, TCA_CTINFO_TM, sizeof(t), &t, TCA_CTINFO_PAD)) +++ goto nla_put_failure; +++ +++ opt.action = ci->tcf_action; +++ if (nla_put(skb, TCA_CTINFO_ACT, sizeof(opt), &opt)) +++ goto nla_put_failure; +++ +++ if (nla_put_u16(skb, TCA_CTINFO_ZONE, cp->zone)) +++ goto nla_put_failure; +++ +++ if (cp->mode & CTINFO_MODE_DSCP) { +++ if (nla_put_u32(skb, TCA_CTINFO_PARMS_DSCP_MASK, +++ cp->dscpmask)) +++ goto nla_put_failure; +++ if (nla_put_u32(skb, TCA_CTINFO_PARMS_DSCP_STATEMASK, +++ cp->dscpstatemask)) +++ goto nla_put_failure; +++ } +++ +++ if (cp->mode & CTINFO_MODE_CPMARK) { +++ if (nla_put_u32(skb, TCA_CTINFO_PARMS_CPMARK_MASK, +++ cp->cpmarkmask)) +++ goto nla_put_failure; +++ } +++ +++ if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_DSCP_SET, +++ ci->stats_dscp_set, TCA_CTINFO_PAD)) +++ goto nla_put_failure; +++ +++ if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_DSCP_ERROR, +++ ci->stats_dscp_error, TCA_CTINFO_PAD)) +++ goto nla_put_failure; +++ +++ if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_CPMARK_SET, +++ ci->stats_cpmark_set, TCA_CTINFO_PAD)) +++ goto nla_put_failure; +++ +++ spin_unlock_bh(&ci->tcf_lock); +++ return skb->len; +++ +++nla_put_failure: +++ spin_unlock_bh(&ci->tcf_lock); +++ nlmsg_trim(skb, b); +++ return -1; +++} +++ +++static int tcf_ctinfo_walker(struct net *net, struct sk_buff *skb, +++ struct netlink_callback *cb, int type, +++ const struct tc_action_ops *ops) +++{ +++ struct tc_action_net *tn = net_generic(net, ctinfo_net_id); +++ +++ return tcf_generic_walker(tn, skb, cb, type, ops); +++} +++ +++static int tcf_ctinfo_search(struct net *net, struct tc_action **a, u32 index) +++{ +++ struct tc_action_net *tn = net_generic(net, ctinfo_net_id); +++ +++ return tcf_idr_search(tn, a, index); +++} +++ +++static void tcf_ctinfo_cleanup(struct tc_action *a, int bind) +++{ +++ struct tcf_ctinfo *ci = to_ctinfo(a); +++ struct tcf_ctinfo_params *cp; +++ +++ cp = rcu_dereference_protected(ci->params, 1); +++ if (cp) +++ kfree_rcu(cp, rcu); +++} +++ +++static struct tc_action_ops act_ctinfo_ops = { +++ .kind = "ctinfo", +++ .type = TCA_ID_CTINFO, +++ .owner = THIS_MODULE, +++ .act = tcf_ctinfo_act, +++ .dump = tcf_ctinfo_dump, +++ .init = tcf_ctinfo_init, +++ .cleanup= tcf_ctinfo_cleanup, +++ .walk = tcf_ctinfo_walker, +++ .lookup = tcf_ctinfo_search, +++ .size = sizeof(struct tcf_ctinfo), +++}; +++ +++static __net_init int ctinfo_init_net(struct net *net) +++{ +++ struct tc_action_net *tn = net_generic(net, ctinfo_net_id); +++ +++ return tc_action_net_init(net, tn, &act_ctinfo_ops); +++} +++ +++static void __net_exit ctinfo_exit_net(struct net *net) +++{ +++ struct tc_action_net *tn = net_generic(net, ctinfo_net_id); +++ +++ tc_action_net_exit(tn); +++} +++ +++static struct pernet_operations ctinfo_net_ops = { +++ .init = ctinfo_init_net, +++ .exit = ctinfo_exit_net, +++ .id = &ctinfo_net_id, +++ .size = sizeof(struct tc_action_net), +++}; +++ +++static int __init ctinfo_init_module(void) +++{ +++ return tcf_register_action(&act_ctinfo_ops, &ctinfo_net_ops); +++} +++ +++static void __exit ctinfo_cleanup_module(void) +++{ +++ tcf_unregister_action(&act_ctinfo_ops, &ctinfo_net_ops); +++} +++ +++module_init(ctinfo_init_module); +++module_exit(ctinfo_cleanup_module); +++MODULE_AUTHOR("Kevin Darbyshire-Bryant "); +++MODULE_DESCRIPTION("Conntrack mark to DSCP restoring"); +++MODULE_LICENSE("GPL"); +diff --git a/target/linux/generic/backport-4.14/400-v4.16-leds-trigger-Introduce-a-NETDEV-trigger.patch b/target/linux/generic/backport-4.14/400-v4.16-leds-trigger-Introduce-a-NETDEV-trigger.patch +new file mode 100644 +index 0000000000..b7d680a11b +--- /dev/null ++++ b/target/linux/generic/backport-4.14/400-v4.16-leds-trigger-Introduce-a-NETDEV-trigger.patch +@@ -0,0 +1,588 @@ ++From 06f502f57d0d7728f9fa0f157ec5e4111ddb98f6 Mon Sep 17 00:00:00 2001 ++From: Ben Whitten ++Date: Sun, 10 Dec 2017 21:17:55 +0000 ++Subject: [PATCH] leds: trigger: Introduce a NETDEV trigger ++ ++This commit introduces a NETDEV trigger for named device ++activity. Available triggers are link, rx, and tx. ++ ++Signed-off-by: Ben Whitten ++Acked-by: Pavel Machek ++Signed-off-by: Jacek Anaszewski ++--- ++ .../ABI/testing/sysfs-class-led-trigger-netdev | 45 ++ ++ drivers/leds/trigger/Kconfig | 7 + ++ drivers/leds/trigger/Makefile | 1 + ++ drivers/leds/trigger/ledtrig-netdev.c | 496 +++++++++++++++++++++ ++ 4 files changed, 549 insertions(+) ++ create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev ++ create mode 100644 drivers/leds/trigger/ledtrig-netdev.c ++ ++--- /dev/null +++++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev ++@@ -0,0 +1,45 @@ +++What: /sys/class/leds//device_name +++Date: Dec 2017 +++KernelVersion: 4.16 +++Contact: linux-leds@vger.kernel.org +++Description: +++ Specifies the network device name to monitor. +++ +++What: /sys/class/leds//interval +++Date: Dec 2017 +++KernelVersion: 4.16 +++Contact: linux-leds@vger.kernel.org +++Description: +++ Specifies the duration of the LED blink in milliseconds. +++ Defaults to 50 ms. +++ +++What: /sys/class/leds//link +++Date: Dec 2017 +++KernelVersion: 4.16 +++Contact: linux-leds@vger.kernel.org +++Description: +++ Signal the link state of the named network device. +++ If set to 0 (default), the LED's normal state is off. +++ If set to 1, the LED's normal state reflects the link state +++ of the named network device. +++ Setting this value also immediately changes the LED state. +++ +++What: /sys/class/leds//tx +++Date: Dec 2017 +++KernelVersion: 4.16 +++Contact: linux-leds@vger.kernel.org +++Description: +++ Signal transmission of data on the named network device. +++ If set to 0 (default), the LED will not blink on transmission. +++ If set to 1, the LED will blink for the milliseconds specified +++ in interval to signal transmission. +++ +++What: /sys/class/leds//rx +++Date: Dec 2017 +++KernelVersion: 4.16 +++Contact: linux-leds@vger.kernel.org +++Description: +++ Signal reception of data on the named network device. +++ If set to 0 (default), the LED will not blink on reception. +++ If set to 1, the LED will blink for the milliseconds specified +++ in interval to signal reception. ++--- a/drivers/leds/trigger/Kconfig +++++ b/drivers/leds/trigger/Kconfig ++@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC ++ a different trigger. ++ If unsure, say Y. ++ +++config LEDS_TRIGGER_NETDEV +++ tristate "LED Netdev Trigger" +++ depends on NET && LEDS_TRIGGERS +++ help +++ This allows LEDs to be controlled by network device activity. +++ If unsure, say Y. +++ ++ endif # LEDS_TRIGGERS ++--- a/drivers/leds/trigger/Makefile +++++ b/drivers/leds/trigger/Makefile ++@@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ++ obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o ++ obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o ++ obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o +++obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o ++--- /dev/null +++++ b/drivers/leds/trigger/ledtrig-netdev.c ++@@ -0,0 +1,496 @@ +++// SPDX-License-Identifier: GPL-2.0 +++// Copyright 2017 Ben Whitten +++// Copyright 2007 Oliver Jowett +++// +++// LED Kernel Netdev Trigger +++// +++// Toggles the LED to reflect the link and traffic state of a named net device +++// +++// Derived from ledtrig-timer.c which is: +++// Copyright 2005-2006 Openedhand Ltd. +++// Author: Richard Purdie +++ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include "../leds.h" +++ +++/* +++ * Configurable sysfs attributes: +++ * +++ * device_name - network device name to monitor +++ * interval - duration of LED blink, in milliseconds +++ * link - LED's normal state reflects whether the link is up +++ * (has carrier) or not +++ * tx - LED blinks on transmitted data +++ * rx - LED blinks on receive data +++ * +++ */ +++ +++struct led_netdev_data { +++ spinlock_t lock; +++ +++ struct delayed_work work; +++ struct notifier_block notifier; +++ +++ struct led_classdev *led_cdev; +++ struct net_device *net_dev; +++ +++ char device_name[IFNAMSIZ]; +++ atomic_t interval; +++ unsigned int last_activity; +++ +++ unsigned long mode; +++#define NETDEV_LED_LINK 0 +++#define NETDEV_LED_TX 1 +++#define NETDEV_LED_RX 2 +++#define NETDEV_LED_MODE_LINKUP 3 +++}; +++ +++enum netdev_led_attr { +++ NETDEV_ATTR_LINK, +++ NETDEV_ATTR_TX, +++ NETDEV_ATTR_RX +++}; +++ +++static void set_baseline_state(struct led_netdev_data *trigger_data) +++{ +++ int current_brightness; +++ struct led_classdev *led_cdev = trigger_data->led_cdev; +++ +++ current_brightness = led_cdev->brightness; +++ if (current_brightness) +++ led_cdev->blink_brightness = current_brightness; +++ if (!led_cdev->blink_brightness) +++ led_cdev->blink_brightness = led_cdev->max_brightness; +++ +++ if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode)) +++ led_set_brightness(led_cdev, LED_OFF); +++ else { +++ if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) +++ led_set_brightness(led_cdev, +++ led_cdev->blink_brightness); +++ else +++ led_set_brightness(led_cdev, LED_OFF); +++ +++ /* If we are looking for RX/TX start periodically +++ * checking stats +++ */ +++ if (test_bit(NETDEV_LED_TX, &trigger_data->mode) || +++ test_bit(NETDEV_LED_RX, &trigger_data->mode)) +++ schedule_delayed_work(&trigger_data->work, 0); +++ } +++} +++ +++static ssize_t device_name_show(struct device *dev, +++ struct device_attribute *attr, char *buf) +++{ +++ struct led_classdev *led_cdev = dev_get_drvdata(dev); +++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; +++ ssize_t len; +++ +++ spin_lock_bh(&trigger_data->lock); +++ len = sprintf(buf, "%s\n", trigger_data->device_name); +++ spin_unlock_bh(&trigger_data->lock); +++ +++ return len; +++} +++ +++static ssize_t device_name_store(struct device *dev, +++ struct device_attribute *attr, const char *buf, +++ size_t size) +++{ +++ struct led_classdev *led_cdev = dev_get_drvdata(dev); +++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; +++ +++ if (size >= IFNAMSIZ) +++ return -EINVAL; +++ +++ cancel_delayed_work_sync(&trigger_data->work); +++ +++ spin_lock_bh(&trigger_data->lock); +++ +++ if (trigger_data->net_dev) { +++ dev_put(trigger_data->net_dev); +++ trigger_data->net_dev = NULL; +++ } +++ +++ strncpy(trigger_data->device_name, buf, size); +++ if (size > 0 && trigger_data->device_name[size - 1] == '\n') +++ trigger_data->device_name[size - 1] = 0; +++ +++ if (trigger_data->device_name[0] != 0) +++ trigger_data->net_dev = +++ dev_get_by_name(&init_net, trigger_data->device_name); +++ +++ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); +++ if (trigger_data->net_dev != NULL) +++ if (netif_carrier_ok(trigger_data->net_dev)) +++ set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); +++ +++ trigger_data->last_activity = 0; +++ +++ set_baseline_state(trigger_data); +++ spin_unlock_bh(&trigger_data->lock); +++ +++ return size; +++} +++ +++static DEVICE_ATTR_RW(device_name); +++ +++static ssize_t netdev_led_attr_show(struct device *dev, char *buf, +++ enum netdev_led_attr attr) +++{ +++ struct led_classdev *led_cdev = dev_get_drvdata(dev); +++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; +++ int bit; +++ +++ switch (attr) { +++ case NETDEV_ATTR_LINK: +++ bit = NETDEV_LED_LINK; +++ break; +++ case NETDEV_ATTR_TX: +++ bit = NETDEV_LED_TX; +++ break; +++ case NETDEV_ATTR_RX: +++ bit = NETDEV_LED_RX; +++ break; +++ default: +++ return -EINVAL; +++ } +++ +++ return sprintf(buf, "%u\n", test_bit(bit, &trigger_data->mode)); +++} +++ +++static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, +++ size_t size, enum netdev_led_attr attr) +++{ +++ struct led_classdev *led_cdev = dev_get_drvdata(dev); +++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; +++ unsigned long state; +++ int ret; +++ int bit; +++ +++ ret = kstrtoul(buf, 0, &state); +++ if (ret) +++ return ret; +++ +++ switch (attr) { +++ case NETDEV_ATTR_LINK: +++ bit = NETDEV_LED_LINK; +++ break; +++ case NETDEV_ATTR_TX: +++ bit = NETDEV_LED_TX; +++ break; +++ case NETDEV_ATTR_RX: +++ bit = NETDEV_LED_RX; +++ break; +++ default: +++ return -EINVAL; +++ } +++ +++ cancel_delayed_work_sync(&trigger_data->work); +++ +++ if (state) +++ set_bit(bit, &trigger_data->mode); +++ else +++ clear_bit(bit, &trigger_data->mode); +++ +++ set_baseline_state(trigger_data); +++ +++ return size; +++} +++ +++static ssize_t link_show(struct device *dev, +++ struct device_attribute *attr, char *buf) +++{ +++ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK); +++} +++ +++static ssize_t link_store(struct device *dev, +++ struct device_attribute *attr, const char *buf, size_t size) +++{ +++ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK); +++} +++ +++static DEVICE_ATTR_RW(link); +++ +++static ssize_t tx_show(struct device *dev, +++ struct device_attribute *attr, char *buf) +++{ +++ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX); +++} +++ +++static ssize_t tx_store(struct device *dev, +++ struct device_attribute *attr, const char *buf, size_t size) +++{ +++ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX); +++} +++ +++static DEVICE_ATTR_RW(tx); +++ +++static ssize_t rx_show(struct device *dev, +++ struct device_attribute *attr, char *buf) +++{ +++ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX); +++} +++ +++static ssize_t rx_store(struct device *dev, +++ struct device_attribute *attr, const char *buf, size_t size) +++{ +++ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX); +++} +++ +++static DEVICE_ATTR_RW(rx); +++ +++static ssize_t interval_show(struct device *dev, +++ struct device_attribute *attr, char *buf) +++{ +++ struct led_classdev *led_cdev = dev_get_drvdata(dev); +++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; +++ +++ return sprintf(buf, "%u\n", +++ jiffies_to_msecs(atomic_read(&trigger_data->interval))); +++} +++ +++static ssize_t interval_store(struct device *dev, +++ struct device_attribute *attr, const char *buf, +++ size_t size) +++{ +++ struct led_classdev *led_cdev = dev_get_drvdata(dev); +++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; +++ unsigned long value; +++ int ret; +++ +++ ret = kstrtoul(buf, 0, &value); +++ if (ret) +++ return ret; +++ +++ /* impose some basic bounds on the timer interval */ +++ if (value >= 5 && value <= 10000) { +++ cancel_delayed_work_sync(&trigger_data->work); +++ +++ atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); +++ set_baseline_state(trigger_data); /* resets timer */ +++ } +++ +++ return size; +++} +++ +++static DEVICE_ATTR_RW(interval); +++ +++static int netdev_trig_notify(struct notifier_block *nb, +++ unsigned long evt, void *dv) +++{ +++ struct net_device *dev = +++ netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv); +++ struct led_netdev_data *trigger_data = container_of(nb, +++ struct +++ led_netdev_data, +++ notifier); +++ +++ if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE +++ && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER +++ && evt != NETDEV_CHANGENAME) +++ return NOTIFY_DONE; +++ +++ if (strcmp(dev->name, trigger_data->device_name)) +++ return NOTIFY_DONE; +++ +++ cancel_delayed_work_sync(&trigger_data->work); +++ +++ spin_lock_bh(&trigger_data->lock); +++ +++ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); +++ switch (evt) { +++ case NETDEV_REGISTER: +++ if (trigger_data->net_dev) +++ dev_put(trigger_data->net_dev); +++ dev_hold(dev); +++ trigger_data->net_dev = dev; +++ break; +++ case NETDEV_CHANGENAME: +++ case NETDEV_UNREGISTER: +++ if (trigger_data->net_dev) { +++ dev_put(trigger_data->net_dev); +++ trigger_data->net_dev = NULL; +++ } +++ break; +++ case NETDEV_UP: +++ case NETDEV_CHANGE: +++ if (netif_carrier_ok(dev)) +++ set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); +++ break; +++ } +++ +++ set_baseline_state(trigger_data); +++ +++ spin_unlock_bh(&trigger_data->lock); +++ +++ return NOTIFY_DONE; +++} +++ +++/* here's the real work! */ +++static void netdev_trig_work(struct work_struct *work) +++{ +++ struct led_netdev_data *trigger_data = container_of(work, +++ struct +++ led_netdev_data, +++ work.work); +++ struct rtnl_link_stats64 *dev_stats; +++ unsigned int new_activity; +++ struct rtnl_link_stats64 temp; +++ unsigned long interval; +++ int invert; +++ +++ /* If we dont have a device, insure we are off */ +++ if (!trigger_data->net_dev) { +++ led_set_brightness(trigger_data->led_cdev, LED_OFF); +++ return; +++ } +++ +++ /* If we are not looking for RX/TX then return */ +++ if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) && +++ !test_bit(NETDEV_LED_RX, &trigger_data->mode)) +++ return; +++ +++ dev_stats = dev_get_stats(trigger_data->net_dev, &temp); +++ new_activity = +++ (test_bit(NETDEV_LED_TX, &trigger_data->mode) ? +++ dev_stats->tx_packets : 0) + +++ (test_bit(NETDEV_LED_RX, &trigger_data->mode) ? +++ dev_stats->rx_packets : 0); +++ +++ if (trigger_data->last_activity != new_activity) { +++ led_stop_software_blink(trigger_data->led_cdev); +++ +++ invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode); +++ interval = jiffies_to_msecs( +++ atomic_read(&trigger_data->interval)); +++ /* base state is ON (link present) */ +++ led_blink_set_oneshot(trigger_data->led_cdev, +++ &interval, +++ &interval, +++ invert); +++ trigger_data->last_activity = new_activity; +++ } +++ +++ schedule_delayed_work(&trigger_data->work, +++ (atomic_read(&trigger_data->interval)*2)); +++} +++ +++static void netdev_trig_activate(struct led_classdev *led_cdev) +++{ +++ struct led_netdev_data *trigger_data; +++ int rc; +++ +++ trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); +++ if (!trigger_data) +++ return; +++ +++ spin_lock_init(&trigger_data->lock); +++ +++ trigger_data->notifier.notifier_call = netdev_trig_notify; +++ trigger_data->notifier.priority = 10; +++ +++ INIT_DELAYED_WORK(&trigger_data->work, netdev_trig_work); +++ +++ trigger_data->led_cdev = led_cdev; +++ trigger_data->net_dev = NULL; +++ trigger_data->device_name[0] = 0; +++ +++ trigger_data->mode = 0; +++ atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); +++ trigger_data->last_activity = 0; +++ +++ led_cdev->trigger_data = trigger_data; +++ +++ rc = device_create_file(led_cdev->dev, &dev_attr_device_name); +++ if (rc) +++ goto err_out; +++ rc = device_create_file(led_cdev->dev, &dev_attr_link); +++ if (rc) +++ goto err_out_device_name; +++ rc = device_create_file(led_cdev->dev, &dev_attr_rx); +++ if (rc) +++ goto err_out_link; +++ rc = device_create_file(led_cdev->dev, &dev_attr_tx); +++ if (rc) +++ goto err_out_rx; +++ rc = device_create_file(led_cdev->dev, &dev_attr_interval); +++ if (rc) +++ goto err_out_tx; +++ rc = register_netdevice_notifier(&trigger_data->notifier); +++ if (rc) +++ goto err_out_interval; +++ return; +++ +++err_out_interval: +++ device_remove_file(led_cdev->dev, &dev_attr_interval); +++err_out_tx: +++ device_remove_file(led_cdev->dev, &dev_attr_tx); +++err_out_rx: +++ device_remove_file(led_cdev->dev, &dev_attr_rx); +++err_out_link: +++ device_remove_file(led_cdev->dev, &dev_attr_link); +++err_out_device_name: +++ device_remove_file(led_cdev->dev, &dev_attr_device_name); +++err_out: +++ led_cdev->trigger_data = NULL; +++ kfree(trigger_data); +++} +++ +++static void netdev_trig_deactivate(struct led_classdev *led_cdev) +++{ +++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; +++ +++ if (trigger_data) { +++ unregister_netdevice_notifier(&trigger_data->notifier); +++ +++ device_remove_file(led_cdev->dev, &dev_attr_device_name); +++ device_remove_file(led_cdev->dev, &dev_attr_link); +++ device_remove_file(led_cdev->dev, &dev_attr_rx); +++ device_remove_file(led_cdev->dev, &dev_attr_tx); +++ device_remove_file(led_cdev->dev, &dev_attr_interval); +++ +++ cancel_delayed_work_sync(&trigger_data->work); +++ +++ if (trigger_data->net_dev) +++ dev_put(trigger_data->net_dev); +++ +++ kfree(trigger_data); +++ } +++} +++ +++static struct led_trigger netdev_led_trigger = { +++ .name = "netdev", +++ .activate = netdev_trig_activate, +++ .deactivate = netdev_trig_deactivate, +++}; +++ +++static int __init netdev_trig_init(void) +++{ +++ return led_trigger_register(&netdev_led_trigger); +++} +++ +++static void __exit netdev_trig_exit(void) +++{ +++ led_trigger_unregister(&netdev_led_trigger); +++} +++ +++module_init(netdev_trig_init); +++module_exit(netdev_trig_exit); +++ +++MODULE_AUTHOR("Ben Whitten "); +++MODULE_AUTHOR("Oliver Jowett "); +++MODULE_DESCRIPTION("Netdev LED trigger"); +++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/generic/backport-4.14/401-v5.2-leds-trigger-netdev-fix-refcnt-leak-on-interface-ren.patch b/target/linux/generic/backport-4.14/401-v5.2-leds-trigger-netdev-fix-refcnt-leak-on-interface-ren.patch +new file mode 100644 +index 0000000000..32682627fc +--- /dev/null ++++ b/target/linux/generic/backport-4.14/401-v5.2-leds-trigger-netdev-fix-refcnt-leak-on-interface-ren.patch +@@ -0,0 +1,69 @@ ++From dd7590a3ab3f0804ed5e930295e2caa5979e3958 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Thu, 28 Feb 2019 22:57:33 +0100 ++Subject: [PATCH] leds: trigger: netdev: fix refcnt leak on interface rename ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Renaming a netdev-trigger-tracked interface was resulting in an ++unbalanced dev_hold(). ++ ++Example: ++> iw phy phy0 interface add foo type __ap ++> echo netdev > trigger ++> echo foo > device_name ++> ip link set foo name bar ++> iw dev bar del ++[ 237.355366] unregister_netdevice: waiting for bar to become free. Usage count = 1 ++[ 247.435362] unregister_netdevice: waiting for bar to become free. Usage count = 1 ++[ 257.545366] unregister_netdevice: waiting for bar to become free. Usage count = 1 ++ ++Above problem was caused by trigger checking a dev->name which obviously ++changes after renaming an interface. It meant missing all further events ++including the NETDEV_UNREGISTER which is required for calling dev_put(). ++ ++This change fixes that by: ++1) Comparing device struct *address* for notification-filtering purposes ++2) Dropping unneeded NETDEV_CHANGENAME code (no behavior change) ++ ++Fixes: 06f502f57d0d ("leds: trigger: Introduce a NETDEV trigger") ++Signed-off-by: Rafał Miłecki ++Acked-by: Pavel Machek ++Signed-off-by: Jacek Anaszewski ++--- ++ drivers/leds/trigger/ledtrig-netdev.c | 13 +++++-------- ++ 1 file changed, 5 insertions(+), 8 deletions(-) ++ ++--- a/drivers/leds/trigger/ledtrig-netdev.c +++++ b/drivers/leds/trigger/ledtrig-netdev.c ++@@ -299,11 +299,11 @@ static int netdev_trig_notify(struct not ++ notifier); ++ ++ if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE ++- && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER ++- && evt != NETDEV_CHANGENAME) +++ && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER) ++ return NOTIFY_DONE; ++ ++- if (strcmp(dev->name, trigger_data->device_name)) +++ if (!(dev == trigger_data->net_dev || +++ (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name)))) ++ return NOTIFY_DONE; ++ ++ cancel_delayed_work_sync(&trigger_data->work); ++@@ -318,12 +318,9 @@ static int netdev_trig_notify(struct not ++ dev_hold(dev); ++ trigger_data->net_dev = dev; ++ break; ++- case NETDEV_CHANGENAME: ++ case NETDEV_UNREGISTER: ++- if (trigger_data->net_dev) { ++- dev_put(trigger_data->net_dev); ++- trigger_data->net_dev = NULL; ++- } +++ dev_put(trigger_data->net_dev); +++ trigger_data->net_dev = NULL; ++ break; ++ case NETDEV_UP: ++ case NETDEV_CHANGE: +diff --git a/target/linux/generic/backport-4.14/402-leds-trigger-netdev-fix-handling-on-interface-rename.patch b/target/linux/generic/backport-4.14/402-leds-trigger-netdev-fix-handling-on-interface-rename.patch +new file mode 100644 +index 0000000000..ae7d6e8bcb +--- /dev/null ++++ b/target/linux/generic/backport-4.14/402-leds-trigger-netdev-fix-handling-on-interface-rename.patch +@@ -0,0 +1,49 @@ ++From 0ff035231edca3713c3d0839c44e64a4ac41ef38 Mon Sep 17 00:00:00 2001 ++From: Martin Schiller ++Date: Thu, 24 Oct 2019 15:09:23 +0200 ++Subject: [PATCH] leds: trigger: netdev: fix handling on interface rename ++ ++The NETDEV_CHANGENAME code is not "unneeded" like it is stated in commit ++4cb6560514fa ("leds: trigger: netdev: fix refcnt leak on interface ++rename"). ++ ++The event was accidentally misinterpreted equivalent to ++NETDEV_UNREGISTER, but should be equivalent to NETDEV_REGISTER. ++ ++This was the case in the original code from the openwrt project. ++ ++Otherwise, you are unable to set netdev led triggers for (non-existent) ++netdevices, which has to be renamed. This is the case, for example, for ++ppp interfaces in openwrt. ++ ++Fixes: 06f502f57d0d ("leds: trigger: Introduce a NETDEV trigger") ++Fixes: 4cb6560514fa ("leds: trigger: netdev: fix refcnt leak on interface rename") ++Signed-off-by: Martin Schiller ++--- ++ drivers/leds/trigger/ledtrig-netdev.c | 5 ++++- ++ 1 file changed, 4 insertions(+), 1 deletion(-) ++ ++--- a/drivers/leds/trigger/ledtrig-netdev.c +++++ b/drivers/leds/trigger/ledtrig-netdev.c ++@@ -299,10 +299,12 @@ static int netdev_trig_notify(struct not ++ notifier); ++ ++ if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE ++- && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER) +++ && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER +++ && evt != NETDEV_CHANGENAME) ++ return NOTIFY_DONE; ++ ++ if (!(dev == trigger_data->net_dev || +++ (evt == NETDEV_CHANGENAME && !strcmp(dev->name, trigger_data->device_name)) || ++ (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name)))) ++ return NOTIFY_DONE; ++ ++@@ -312,6 +314,7 @@ static int netdev_trig_notify(struct not ++ ++ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); ++ switch (evt) { +++ case NETDEV_CHANGENAME: ++ case NETDEV_REGISTER: ++ if (trigger_data->net_dev) ++ dev_put(trigger_data->net_dev); +diff --git a/target/linux/generic/backport-4.14/410-mtd-fix-calculating-partition-end-address.patch b/target/linux/generic/backport-4.14/410-mtd-fix-calculating-partition-end-address.patch +new file mode 100644 +index 0000000000..ec25eef7a9 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/410-mtd-fix-calculating-partition-end-address.patch +@@ -0,0 +1,28 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Mon, 9 Mar 2020 08:30:19 +0100 ++Subject: [PATCH] mtd: fix calculating partition end address ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This fixes check for partitions that don't start at beginning of their ++parents. Missing partition's offset in formula could result in forcing ++read-only incorrectly. ++ ++Fixes: 6750f61a13a0 ("mtd: improve calculating partition boundaries when checking for alignment") ++Signed-off-by: Rafał Miłecki ++--- ++ drivers/mtd/mtdpart.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -582,7 +582,7 @@ static struct mtd_part *allocate_partiti ++ part->name); ++ } ++ ++- tmp = part_absolute_offset(parent) + slave->mtd.size; +++ tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size; ++ remainder = do_div(tmp, wr_alignment); ++ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { ++ slave->mtd.flags &= ~MTD_WRITEABLE; +diff --git a/target/linux/generic/backport-4.14/420-enable-CONFIG_MMC_SDHCI_IO_ACCESSORS.patch b/target/linux/generic/backport-4.14/420-enable-CONFIG_MMC_SDHCI_IO_ACCESSORS.patch +new file mode 100644 +index 0000000000..eabfc64378 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/420-enable-CONFIG_MMC_SDHCI_IO_ACCESSORS.patch +@@ -0,0 +1,23 @@ ++From: Vijay Viswanath ++Date: Wed, 27 Sep 2017 11:04:42 +0530 ++Subject: [PATCH v2 3/4] mmc: Kconfig: Enable CONFIG_MMC_SDHCI_IO_ACCESSORS ++ ++Enable CONFIG_MMC_SDHCI_IO_ACCESSORS so that SDHC controller specific ++register read and write APIs, if registered, can be used. ++ ++Signed-off-by: Vijay Viswanath ++Acked-by: Adrian Hunter ++--- ++ drivers/mmc/host/Kconfig | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/mmc/host/Kconfig +++++ b/drivers/mmc/host/Kconfig ++@@ -310,6 +310,7 @@ config MMC_SDHCI_BCM_KONA ++ tristate "SDHCI support on Broadcom KONA platform" ++ depends on ARCH_BCM_MOBILE ++ depends on MMC_SDHCI_PLTFM +++ select MMC_SDHCI_IO_ACCESSORS ++ help ++ This selects the Broadcom Kona Secure Digital Host Controller ++ Interface(SDHCI) support. +diff --git a/target/linux/generic/backport-4.14/500-v4.20-ubifs-Fix-default-compression-selection-in-ubifs.patch b/target/linux/generic/backport-4.14/500-v4.20-ubifs-Fix-default-compression-selection-in-ubifs.patch +new file mode 100644 +index 0000000000..4782fc9ed8 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/500-v4.20-ubifs-Fix-default-compression-selection-in-ubifs.patch +@@ -0,0 +1,37 @@ ++From: Gabor Juhos ++Subject: fs: ubifs: fix default compression selection in ubifs ++ ++Signed-off-by: Gabor Juhos ++--- ++ fs/ubifs/sb.c | 13 ++++++++++++- ++ 1 file changed, 12 insertions(+), 1 deletion(-) ++ ++--- a/fs/ubifs/sb.c +++++ b/fs/ubifs/sb.c ++@@ -63,6 +63,17 @@ ++ /* Default time granularity in nanoseconds */ ++ #define DEFAULT_TIME_GRAN 1000000000 ++ +++static int get_default_compressor(void) +++{ +++ if (ubifs_compr_present(UBIFS_COMPR_LZO)) +++ return UBIFS_COMPR_LZO; +++ +++ if (ubifs_compr_present(UBIFS_COMPR_ZLIB)) +++ return UBIFS_COMPR_ZLIB; +++ +++ return UBIFS_COMPR_NONE; +++} +++ ++ /** ++ * create_default_filesystem - format empty UBI volume. ++ * @c: UBIFS file-system description object ++@@ -186,7 +197,7 @@ static int create_default_filesystem(str ++ if (c->mount_opts.override_compr) ++ sup->default_compr = cpu_to_le16(c->mount_opts.compr_type); ++ else ++- sup->default_compr = cpu_to_le16(UBIFS_COMPR_LZO); +++ sup->default_compr = cpu_to_le16(get_default_compressor()); ++ ++ generate_random_uuid(sup->uuid); ++ +diff --git a/target/linux/generic/backport-4.14/900-v4.18-firmware-dmi-Add-access-to-the-SKU-ID-string.patch b/target/linux/generic/backport-4.14/900-v4.18-firmware-dmi-Add-access-to-the-SKU-ID-string.patch +new file mode 100644 +index 0000000000..9c80b47607 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/900-v4.18-firmware-dmi-Add-access-to-the-SKU-ID-string.patch +@@ -0,0 +1,57 @@ ++From b23908d3c48a37c46c6a26df2cdeab1610b360ba Mon Sep 17 00:00:00 2001 ++From: Simon Glass ++Date: Sun, 17 Jun 2018 14:09:42 +0200 ++Subject: [PATCH] firmware: dmi: Add access to the SKU ID string ++ ++This is used in some systems from user space for determining the identity ++of the device. ++ ++Expose this as a file so that that user-space tools don't need to read ++from /sys/firmware/dmi/tables/DMI ++ ++Signed-off-by: Simon Glass ++Signed-off-by: Jean Delvare ++--- ++ drivers/firmware/dmi-id.c | 2 ++ ++ drivers/firmware/dmi_scan.c | 1 + ++ include/linux/mod_devicetable.h | 1 + ++ 3 files changed, 4 insertions(+) ++ ++--- a/drivers/firmware/dmi-id.c +++++ b/drivers/firmware/dmi-id.c ++@@ -47,6 +47,7 @@ DEFINE_DMI_ATTR_WITH_SHOW(product_name, ++ DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION); ++ DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL); ++ DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID); +++DEFINE_DMI_ATTR_WITH_SHOW(product_sku, 0444, DMI_PRODUCT_SKU); ++ DEFINE_DMI_ATTR_WITH_SHOW(product_family, 0444, DMI_PRODUCT_FAMILY); ++ DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR); ++ DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME); ++@@ -193,6 +194,7 @@ static void __init dmi_id_init_attr_tabl ++ ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL); ++ ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID); ++ ADD_DMI_ATTR(product_family, DMI_PRODUCT_FAMILY); +++ ADD_DMI_ATTR(product_sku, DMI_PRODUCT_SKU); ++ ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR); ++ ADD_DMI_ATTR(board_name, DMI_BOARD_NAME); ++ ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION); ++--- a/drivers/firmware/dmi_scan.c +++++ b/drivers/firmware/dmi_scan.c ++@@ -435,6 +435,7 @@ static void __init dmi_decode(const stru ++ dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); ++ dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); ++ dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8); +++ dmi_save_ident(dm, DMI_PRODUCT_SKU, 25); ++ dmi_save_ident(dm, DMI_PRODUCT_FAMILY, 26); ++ break; ++ case 2: /* Base Board Information */ ++--- a/include/linux/mod_devicetable.h +++++ b/include/linux/mod_devicetable.h ++@@ -471,6 +471,7 @@ enum dmi_field { ++ DMI_PRODUCT_VERSION, ++ DMI_PRODUCT_SERIAL, ++ DMI_PRODUCT_UUID, +++ DMI_PRODUCT_SKU, ++ DMI_PRODUCT_FAMILY, ++ DMI_BOARD_VENDOR, ++ DMI_BOARD_NAME, +diff --git a/target/linux/generic/backport-4.14/950-tty-serial-exar-generalize-rs485-setup.patch b/target/linux/generic/backport-4.14/950-tty-serial-exar-generalize-rs485-setup.patch +new file mode 100644 +index 0000000000..c4c4cfcb71 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/950-tty-serial-exar-generalize-rs485-setup.patch +@@ -0,0 +1,75 @@ ++From 9d9398944488cd3a3e1e0912b26fbc4d5921e547 Mon Sep 17 00:00:00 2001 ++From: Daniel Golle ++Date: Mon, 4 Jun 2018 23:33:07 +0200 ++Subject: [PATCH] tty: serial: exar: generalize RS485 setup ++ ++Move the non-board-specific part of the RS485 initialization from ++iot2040_rs485_config function to a new generic function used also for ++other boards. ++This allows using TIOCGRS485 and TIOCSRS485 on boards (such as mPCIe ++serial IO modules) which are hard-wired to RS485 or have jumpers for ++their configurations. ++ ++Signed-off-by: Daniel Golle ++Reviewed-by: Jan Kiszka ++Signed-off-by: Greg Kroah-Hartman ++--- ++ drivers/tty/serial/8250/8250_exar.c | 38 +++++++++++++++++++---------- ++ 1 file changed, 25 insertions(+), 13 deletions(-) ++ ++--- a/drivers/tty/serial/8250/8250_exar.c +++++ b/drivers/tty/serial/8250/8250_exar.c ++@@ -293,8 +293,32 @@ static int xr17v35x_register_gpio(struct ++ return 0; ++ } ++ +++static int generic_rs485_config(struct uart_port *port, +++ struct serial_rs485 *rs485) +++{ +++ bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED); +++ u8 __iomem *p = port->membase; +++ u8 value; +++ +++ value = readb(p + UART_EXAR_FCTR); +++ if (is_rs485) +++ value |= UART_FCTR_EXAR_485; +++ else +++ value &= ~UART_FCTR_EXAR_485; +++ +++ writeb(value, p + UART_EXAR_FCTR); +++ +++ if (is_rs485) +++ writeb(UART_EXAR_RS485_DLY(4), p + UART_MSR); +++ +++ port->rs485 = *rs485; +++ +++ return 0; +++} +++ ++ static const struct exar8250_platform exar8250_default_platform = { ++ .register_gpio = xr17v35x_register_gpio, +++ .rs485_config = generic_rs485_config, ++ }; ++ ++ static int iot2040_rs485_config(struct uart_port *port, ++@@ -327,19 +351,7 @@ static int iot2040_rs485_config(struct u ++ value |= mode; ++ writeb(value, p + UART_EXAR_MPIOLVL_7_0); ++ ++- value = readb(p + UART_EXAR_FCTR); ++- if (is_rs485) ++- value |= UART_FCTR_EXAR_485; ++- else ++- value &= ~UART_FCTR_EXAR_485; ++- writeb(value, p + UART_EXAR_FCTR); ++- ++- if (is_rs485) ++- writeb(UART_EXAR_RS485_DLY(4), p + UART_MSR); ++- ++- port->rs485 = *rs485; ++- ++- return 0; +++ return generic_rs485_config(port, rs485); ++ } ++ ++ static const struct property_entry iot2040_gpio_properties[] = { +diff --git a/target/linux/generic/config-4.14 b/target/linux/generic/config-4.14 +new file mode 100644 +index 0000000000..6bf7dac5e3 +--- /dev/null ++++ b/target/linux/generic/config-4.14 +@@ -0,0 +1,5793 @@ ++# CONFIG_104_QUAD_8 is not set ++CONFIG_32BIT=y ++# CONFIG_6LOWPAN is not set ++# CONFIG_6LOWPAN_DEBUGFS is not set ++# CONFIG_6PACK is not set ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_9P_FS is not set ++# CONFIG_AB3100_CORE is not set ++# CONFIG_AB8500_CORE is not set ++# CONFIG_ABP060MG is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_ACENIC is not set ++# CONFIG_ACERHDF is not set ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_ACPI_ALS is not set ++# CONFIG_ACPI_APEI is not set ++# CONFIG_ACPI_BUTTON is not set ++# CONFIG_ACPI_CONFIGFS is not set ++# CONFIG_ACPI_CUSTOM_METHOD is not set ++# CONFIG_ACPI_EXTLOG is not set ++# CONFIG_ACPI_HED is not set ++# CONFIG_ACPI_NFIT is not set ++# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set ++# CONFIG_ACPI_TABLE_UPGRADE is not set ++# CONFIG_ACPI_VIDEO is not set ++# CONFIG_AD2S1200 is not set ++# CONFIG_AD2S1210 is not set ++# CONFIG_AD2S90 is not set ++# CONFIG_AD5064 is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_AD5360 is not set ++# CONFIG_AD5380 is not set ++# CONFIG_AD5421 is not set ++# CONFIG_AD5446 is not set ++# CONFIG_AD5449 is not set ++# CONFIG_AD5504 is not set ++# CONFIG_AD5592R is not set ++# CONFIG_AD5593R is not set ++# CONFIG_AD5624R_SPI is not set ++# CONFIG_AD5686 is not set ++# CONFIG_AD5755 is not set ++# CONFIG_AD5761 is not set ++# CONFIG_AD5764 is not set ++# CONFIG_AD5791 is not set ++# CONFIG_AD5933 is not set ++# CONFIG_AD7150 is not set ++# CONFIG_AD7152 is not set ++# CONFIG_AD7192 is not set ++# CONFIG_AD7266 is not set ++# CONFIG_AD7280 is not set ++# CONFIG_AD7291 is not set ++# CONFIG_AD7298 is not set ++# CONFIG_AD7303 is not set ++# CONFIG_AD7476 is not set ++# CONFIG_AD7606 is not set ++# CONFIG_AD7746 is not set ++# CONFIG_AD7766 is not set ++# CONFIG_AD7780 is not set ++# CONFIG_AD7791 is not set ++# CONFIG_AD7793 is not set ++# CONFIG_AD7816 is not set ++# CONFIG_AD7887 is not set ++# CONFIG_AD7923 is not set ++# CONFIG_AD799X is not set ++# CONFIG_AD8366 is not set ++# CONFIG_AD8801 is not set ++# CONFIG_AD9523 is not set ++# CONFIG_AD9832 is not set ++# CONFIG_AD9834 is not set ++# CONFIG_ADAPTEC_STARFIRE is not set ++# CONFIG_ADE7753 is not set ++# CONFIG_ADE7754 is not set ++# CONFIG_ADE7758 is not set ++# CONFIG_ADE7759 is not set ++# CONFIG_ADE7854 is not set ++# CONFIG_ADF4350 is not set ++# CONFIG_ADFS_FS is not set ++# CONFIG_ADIS16060 is not set ++# CONFIG_ADIS16080 is not set ++# CONFIG_ADIS16130 is not set ++# CONFIG_ADIS16136 is not set ++# CONFIG_ADIS16201 is not set ++# CONFIG_ADIS16203 is not set ++# CONFIG_ADIS16209 is not set ++# CONFIG_ADIS16240 is not set ++# CONFIG_ADIS16260 is not set ++# CONFIG_ADIS16400 is not set ++# CONFIG_ADIS16480 is not set ++# CONFIG_ADJD_S311 is not set ++# CONFIG_ADM6996_PHY is not set ++# CONFIG_ADM8211 is not set ++# CONFIG_ADT7316 is not set ++CONFIG_ADVISE_SYSCALLS=y ++# CONFIG_ADXL345_I2C is not set ++# CONFIG_ADXL345_SPI is not set ++# CONFIG_ADXRS450 is not set ++CONFIG_AEABI=y ++# CONFIG_AFE4403 is not set ++# CONFIG_AFE4404 is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_AFS_FS is not set ++# CONFIG_AF_KCM is not set ++# CONFIG_AF_RXRPC is not set ++# CONFIG_AF_RXRPC_INJECT_LOSS is not set ++# CONFIG_AF_RXRPC_IPV6 is not set ++# CONFIG_AGP is not set ++# CONFIG_AHCI_CEVA is not set ++# CONFIG_AHCI_IMX is not set ++# CONFIG_AHCI_MVEBU is not set ++# CONFIG_AHCI_QORIQ is not set ++CONFIG_AIO=y ++# CONFIG_AIRO is not set ++# CONFIG_AIRO_CS is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_AK09911 is not set ++# CONFIG_AK8974 is not set ++# CONFIG_AK8975 is not set ++# CONFIG_AL3320A is not set ++# CONFIG_ALIM7101_WDT is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_ALTERA_MBOX is not set ++# CONFIG_ALTERA_MSGDMA is not set ++# CONFIG_ALTERA_STAPL is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_ALX is not set ++# CONFIG_AM2315 is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AMD8111_ETH is not set ++# CONFIG_AMD_MEM_ENCRYPT is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE is not set ++# CONFIG_AMD_XGBE_HAVE_ECC is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_AMILO_RFKILL is not set ++# CONFIG_ANDROID is not set ++CONFIG_ANON_INODES=y ++# CONFIG_APDS9300 is not set ++# CONFIG_APDS9802ALS is not set ++# CONFIG_APDS9960 is not set ++# CONFIG_APM8018X is not set ++# CONFIG_APM_EMULATION is not set ++# CONFIG_APPLE_GMUX is not set ++# CONFIG_APPLE_PROPERTIES is not set ++# CONFIG_APPLICOM is not set ++# CONFIG_AQTION is not set ++# CONFIG_AQUANTIA_PHY is not set ++# CONFIG_AR5523 is not set ++# CONFIG_AR7 is not set ++# CONFIG_AR8216_PHY is not set ++# CONFIG_AR8216_PHY_LEDS is not set ++# CONFIG_ARCH_ACTIONS is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_ASPEED is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_21664 is not set ++# CONFIG_ARCH_BCM_23550 is not set ++# CONFIG_ARCH_BCM_281XX is not set ++# CONFIG_ARCH_BCM_5301X is not set ++# CONFIG_ARCH_BCM_53573 is not set ++# CONFIG_ARCH_BCM_63XX is not set ++# CONFIG_ARCH_BCM_CYGNUS is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BCM_NSP is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CNS3XXX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set ++# CONFIG_ARCH_DOVE is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_EXYNOS is not set ++CONFIG_ARCH_FLATMEM_ENABLE=y ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_GEMINI is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_LPC32XX is not set ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++CONFIG_ARCH_MMAP_RND_BITS=8 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=16 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=8 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_MULTIPLATFORM is not set ++# CONFIG_ARCH_MULTI_V6 is not set ++# CONFIG_ARCH_MULTI_V7 is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_NSPIRE is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_OMAP1 is not set ++# CONFIG_ARCH_OMAP2 is not set ++# CONFIG_ARCH_OMAP2PLUS is not set ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_OXNAS is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++# CONFIG_ARCH_PICOXCELL is not set ++# CONFIG_ARCH_PRIMA2 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALTEK is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_SHMOBILE is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_THUNDER2 is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_VT8500 is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_W90X900 is not set ++# CONFIG_ARCH_WANTS_THP_SWAP is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_ARCH_WM8505 is not set ++# CONFIG_ARCH_WM8750 is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++# CONFIG_ARCH_ZYNQMP is not set ++# CONFIG_ARCNET is not set ++# CONFIG_ARC_EMAC is not set ++# CONFIG_ARM64_ERRATUM_1024718 is not set ++# CONFIG_ARM64_ERRATUM_819472 is not set ++# CONFIG_ARM64_ERRATUM_824069 is not set ++# CONFIG_ARM64_ERRATUM_826319 is not set ++# CONFIG_ARM64_ERRATUM_827319 is not set ++# CONFIG_ARM64_ERRATUM_832075 is not set ++# CONFIG_ARM64_ERRATUM_834220 is not set ++# CONFIG_ARM64_ERRATUM_843419 is not set ++# CONFIG_ARM64_ERRATUM_845719 is not set ++# CONFIG_ARM64_ERRATUM_858921 is not set ++# CONFIG_ARM64_RELOC_TEST is not set ++CONFIG_ARM64_SW_TTBR0_PAN=y ++# CONFIG_ARM_APPENDED_DTB is not set ++# CONFIG_ARM_ARCH_TIMER is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_CCI is not set ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_ARM_CPUIDLE is not set ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_ARM_CRYPTO is not set ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++# CONFIG_ARM_ERRATA_326103 is not set ++# CONFIG_ARM_ERRATA_364296 is not set ++# CONFIG_ARM_ERRATA_411920 is not set ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_458693 is not set ++# CONFIG_ARM_ERRATA_460075 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_742230 is not set ++# CONFIG_ARM_ERRATA_742231 is not set ++# CONFIG_ARM_ERRATA_743622 is not set ++# CONFIG_ARM_ERRATA_751472 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_ARM_KPROBES_TEST is not set ++# CONFIG_ARM_MHU is not set ++# CONFIG_ARM_MODULE_PLTS is not set ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++# CONFIG_ARM_PSCI is not set ++# CONFIG_ARM_PSCI_CHECKER is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_ARM_SBSA_WATCHDOG is not set ++# CONFIG_ARM_SCPI_PROTOCOL is not set ++# CONFIG_ARM_TIMER_SP804 is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_ARM_VIRT_EXT is not set ++# CONFIG_AS3935 is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_ASUS_LAPTOP is not set ++# CONFIG_ASUS_WIRELESS is not set ++# CONFIG_ASYMMETRIC_KEY_TYPE is not set ++# CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE is not set ++# CONFIG_ASYNC_RAID6_TEST is not set ++# CONFIG_ASYNC_TX_DMA is not set ++# CONFIG_AT76C50X_USB is not set ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AT91_SAMA5D2_ADC is not set ++# CONFIG_ATA is not set ++# CONFIG_ATAGS is not set ++CONFIG_ATAGS_PROC=y ++# CONFIG_ATALK is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_ATA_ACPI is not set ++CONFIG_ATA_BMDMA=y ++# CONFIG_ATA_GENERIC is not set ++# CONFIG_ATA_LEDS is not set ++# CONFIG_ATA_NONSTANDARD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_ATA_PIIX is not set ++CONFIG_ATA_SFF=y ++# CONFIG_ATA_VERBOSE_ERROR is not set ++# CONFIG_ATH10K is not set ++# CONFIG_ATH25 is not set ++# CONFIG_ATH5K is not set ++# CONFIG_ATH6KL is not set ++# CONFIG_ATH79 is not set ++# CONFIG_ATH9K is not set ++# CONFIG_ATH9K_HTC is not set ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL2 is not set ++# CONFIG_ATLAS_PH_SENSOR is not set ++# CONFIG_ATM is not set ++# CONFIG_ATMEL is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ATM_AMBASSADOR is not set ++# CONFIG_ATM_BR2684 is not set ++CONFIG_ATM_BR2684_IPFILTER=y ++# CONFIG_ATM_CLIP is not set ++CONFIG_ATM_CLIP_NO_ICMP=y ++# CONFIG_ATM_DRIVERS is not set ++# CONFIG_ATM_DUMMY is not set ++# CONFIG_ATM_ENI is not set ++# CONFIG_ATM_FIRESTREAM is not set ++# CONFIG_ATM_FORE200E is not set ++# CONFIG_ATM_HE is not set ++# CONFIG_ATM_HORIZON is not set ++# CONFIG_ATM_IA is not set ++# CONFIG_ATM_IDT77252 is not set ++# CONFIG_ATM_LANAI is not set ++# CONFIG_ATM_LANE is not set ++# CONFIG_ATM_MPOA is not set ++# CONFIG_ATM_NICSTAR is not set ++# CONFIG_ATM_SOLOS is not set ++# CONFIG_ATM_TCP is not set ++# CONFIG_ATM_ZATM is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_ATP is not set ++# CONFIG_AUDIT is not set ++# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set ++# CONFIG_AURORA_NB8800 is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_AUTO_ZRELADDR is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_AX25 is not set ++# CONFIG_AX25_DAMA_SLAVE is not set ++# CONFIG_AX88796 is not set ++# CONFIG_AXP20X_ADC is not set ++# CONFIG_AXP20X_POWER is not set ++# CONFIG_AXP288_ADC is not set ++# CONFIG_AXP288_FUEL_GAUGE is not set ++# CONFIG_B43 is not set ++# CONFIG_B43LEGACY is not set ++# CONFIG_B44 is not set ++# CONFIG_B53 is not set ++# CONFIG_BACKLIGHT_ADP8860 is not set ++# CONFIG_BACKLIGHT_ADP8870 is not set ++# CONFIG_BACKLIGHT_APPLE is not set ++# CONFIG_BACKLIGHT_ARCXCNN is not set ++# CONFIG_BACKLIGHT_BD6107 is not set ++# CONFIG_BACKLIGHT_GENERIC is not set ++# CONFIG_BACKLIGHT_GPIO is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_BACKLIGHT_LM3630A is not set ++# CONFIG_BACKLIGHT_LM3639 is not set ++# CONFIG_BACKLIGHT_LP855X is not set ++# CONFIG_BACKLIGHT_LV5207LP is not set ++# CONFIG_BACKLIGHT_PANDORA is not set ++# CONFIG_BACKLIGHT_PM8941_WLED is not set ++# CONFIG_BACKLIGHT_PWM is not set ++# CONFIG_BACKLIGHT_RPI is not set ++# CONFIG_BACKLIGHT_SAHARA is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++CONFIG_BASE_FULL=y ++CONFIG_BASE_SMALL=0 ++# CONFIG_BATMAN_ADV is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_BQ27XXX_HDQ is not set ++# CONFIG_BATTERY_DS2760 is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_BATTERY_LEGO_EV3 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_BATTERY_MAX1721X is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BAYCOM_EPP is not set ++# CONFIG_BAYCOM_PAR is not set ++# CONFIG_BAYCOM_SER_FDX is not set ++# CONFIG_BAYCOM_SER_HDX is not set ++# CONFIG_BCACHE is not set ++# CONFIG_BCM47XX is not set ++# CONFIG_BCM63XX is not set ++# CONFIG_BCM63XX_PHY is not set ++# CONFIG_BCM7038_WDT is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_BCMA is not set ++# CONFIG_BCMA_DRIVER_GPIO is not set ++CONFIG_BCMA_POSSIBLE=y ++# CONFIG_BCMGENET is not set ++# CONFIG_BCM_IPROC_ADC is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_BCM_SBA_RAID is not set ++# CONFIG_BDI_SWITCH is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BE2NET is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_BGMAC is not set ++# CONFIG_BH1750 is not set ++# CONFIG_BH1780 is not set ++# CONFIG_BIG_KEYS is not set ++# CONFIG_BIG_LITTLE is not set ++# CONFIG_BINARY_PRINTF is not set ++# CONFIG_BINFMT_AOUT is not set ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_FLAT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_BINFMT_SCRIPT=y ++CONFIG_BITREVERSE=y ++# CONFIG_BLK_CMDLINE_PARSER is not set ++# CONFIG_BLK_DEBUG_FS is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_BLK_DEV_4DRIVES is not set ++# CONFIG_BLK_DEV_AEC62XX is not set ++# CONFIG_BLK_DEV_ALI14XX is not set ++# CONFIG_BLK_DEV_ALI15X3 is not set ++# CONFIG_BLK_DEV_AMD74XX is not set ++# CONFIG_BLK_DEV_ATIIXP is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_CMD640 is not set ++# CONFIG_BLK_DEV_CMD64X is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_CS5520 is not set ++# CONFIG_BLK_DEV_CS5530 is not set ++# CONFIG_BLK_DEV_CS5535 is not set ++# CONFIG_BLK_DEV_CS5536 is not set ++# CONFIG_BLK_DEV_CY82C693 is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_DELKIN is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_DTC2278 is not set ++# CONFIG_BLK_DEV_FD is not set ++# CONFIG_BLK_DEV_GENERIC is not set ++# CONFIG_BLK_DEV_HPT366 is not set ++# CONFIG_BLK_DEV_HT6560B is not set ++# CONFIG_BLK_DEV_IDEACPI is not set ++# CONFIG_BLK_DEV_IDECD is not set ++# CONFIG_BLK_DEV_IDECS is not set ++# CONFIG_BLK_DEV_IDEPCI is not set ++# CONFIG_BLK_DEV_IDEPNP is not set ++# CONFIG_BLK_DEV_IDETAPE is not set ++# CONFIG_BLK_DEV_IDE_AU1XXX is not set ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_BLK_DEV_INITRD=y ++# CONFIG_BLK_DEV_INTEGRITY is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_BLK_DEV_IT8172 is not set ++# CONFIG_BLK_DEV_IT8213 is not set ++# CONFIG_BLK_DEV_IT821X is not set ++# CONFIG_BLK_DEV_JMICRON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_NS87415 is not set ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_BLK_DEV_OFFBOARD is not set ++# CONFIG_BLK_DEV_OPTI621 is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_DEV_PDC202XX_NEW is not set ++# CONFIG_BLK_DEV_PDC202XX_OLD is not set ++# CONFIG_BLK_DEV_PIIX is not set ++# CONFIG_BLK_DEV_PLATFORM is not set ++# CONFIG_BLK_DEV_PMEM is not set ++# CONFIG_BLK_DEV_QD65XX is not set ++# CONFIG_BLK_DEV_RAM is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_RZ1000 is not set ++# CONFIG_BLK_DEV_SC1200 is not set ++# CONFIG_BLK_DEV_SD is not set ++# CONFIG_BLK_DEV_SIIMAGE is not set ++# CONFIG_BLK_DEV_SIS5513 is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SL82C105 is not set ++# CONFIG_BLK_DEV_SLC90E66 is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_BLK_DEV_SVWKS is not set ++# CONFIG_BLK_DEV_SX8 is not set ++# CONFIG_BLK_DEV_TC86C001 is not set ++# CONFIG_BLK_DEV_THROTTLING is not set ++# CONFIG_BLK_DEV_TRIFLEX is not set ++# CONFIG_BLK_DEV_TRM290 is not set ++# CONFIG_BLK_DEV_UMC8672 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_VIA82CXXX is not set ++# CONFIG_BLK_DEV_ZONED is not set ++# CONFIG_BLK_SED_OPAL is not set ++# CONFIG_BLK_WBT is not set ++CONFIG_BLOCK=y ++# CONFIG_BMA180 is not set ++# CONFIG_BMA220 is not set ++# CONFIG_BMC150_ACCEL is not set ++# CONFIG_BMC150_MAGN is not set ++# CONFIG_BMC150_MAGN_I2C is not set ++# CONFIG_BMC150_MAGN_SPI is not set ++# CONFIG_BMG160 is not set ++# CONFIG_BMI160_I2C is not set ++# CONFIG_BMI160_SPI is not set ++# CONFIG_BMIPS_GENERIC is not set ++# CONFIG_BMP280 is not set ++# CONFIG_BNA is not set ++# CONFIG_BNX2 is not set ++# CONFIG_BNX2X is not set ++# CONFIG_BNX2X_SRIOV is not set ++# CONFIG_BNXT is not set ++# CONFIG_BONDING is not set ++# CONFIG_BOOKE_WDT is not set ++CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT=3 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++# CONFIG_BOOT_PRINTK_DELAY is not set ++CONFIG_BOOT_RAW=y ++CONFIG_BPF=y ++CONFIG_BPF_JIT=y ++# CONFIG_BPF_JIT_ALWAYS_ON is not set ++# CONFIG_BPF_STREAM_PARSER is not set ++CONFIG_BPF_SYSCALL=y ++# CONFIG_BPQETHER is not set ++CONFIG_BQL=y ++CONFIG_BRANCH_PROFILE_NONE=y ++# CONFIG_BRCMFMAC is not set ++# CONFIG_BRCMSMAC is not set ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_BRIDGE=y ++# CONFIG_BRIDGE_EBT_802_3 is not set ++# CONFIG_BRIDGE_EBT_AMONG is not set ++# CONFIG_BRIDGE_EBT_ARP is not set ++# CONFIG_BRIDGE_EBT_ARPREPLY is not set ++# CONFIG_BRIDGE_EBT_BROUTE is not set ++# CONFIG_BRIDGE_EBT_DNAT is not set ++# CONFIG_BRIDGE_EBT_IP is not set ++# CONFIG_BRIDGE_EBT_IP6 is not set ++# CONFIG_BRIDGE_EBT_LIMIT is not set ++# CONFIG_BRIDGE_EBT_LOG is not set ++# CONFIG_BRIDGE_EBT_MARK is not set ++# CONFIG_BRIDGE_EBT_MARK_T is not set ++# CONFIG_BRIDGE_EBT_NFLOG is not set ++# CONFIG_BRIDGE_EBT_PKTTYPE is not set ++# CONFIG_BRIDGE_EBT_REDIRECT is not set ++# CONFIG_BRIDGE_EBT_SNAT is not set ++# CONFIG_BRIDGE_EBT_STP is not set ++# CONFIG_BRIDGE_EBT_T_FILTER is not set ++# CONFIG_BRIDGE_EBT_T_NAT is not set ++# CONFIG_BRIDGE_EBT_VLAN is not set ++CONFIG_BRIDGE_IGMP_SNOOPING=y ++# CONFIG_BRIDGE_NETFILTER is not set ++# CONFIG_BRIDGE_NF_EBTABLES is not set ++CONFIG_BRIDGE_VLAN_FILTERING=y ++# CONFIG_BROADCOM_PHY is not set ++CONFIG_BROKEN_ON_SMP=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_BSD_PROCESS_ACCT_V3 is not set ++# CONFIG_BT is not set ++# CONFIG_BTRFS_ASSERT is not set ++# CONFIG_BTRFS_DEBUG is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_BTRFS_FS_POSIX_ACL is not set ++# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set ++# CONFIG_BT_ATH3K is not set ++# CONFIG_BT_BNEP is not set ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++# CONFIG_BT_BREDR is not set ++# CONFIG_BT_CMTP is not set ++# CONFIG_BT_HCIBCM203X is not set ++# CONFIG_BT_HCIBFUSB is not set ++# CONFIG_BT_HCIBLUECARD is not set ++# CONFIG_BT_HCIBPA10X is not set ++# CONFIG_BT_HCIBT3C is not set ++# CONFIG_BT_HCIBTSDIO is not set ++# CONFIG_BT_HCIBTUART is not set ++# CONFIG_BT_HCIBTUSB is not set ++# CONFIG_BT_HCIBTUSB_RTL is not set ++# CONFIG_BT_HCIDTL1 is not set ++# CONFIG_BT_HCIUART is not set ++# CONFIG_BT_HCIUART_3WIRE is not set ++# CONFIG_BT_HCIUART_AG6XX is not set ++# CONFIG_BT_HCIUART_ATH3K is not set ++CONFIG_BT_HCIUART_BCSP=y ++CONFIG_BT_HCIUART_H4=y ++# CONFIG_BT_HCIUART_LL is not set ++# CONFIG_BT_HCIUART_MRVL is not set ++# CONFIG_BT_HCIUART_QCA is not set ++# CONFIG_BT_HCIVHCI is not set ++# CONFIG_BT_HIDP is not set ++# CONFIG_BT_HS is not set ++# CONFIG_BT_LE is not set ++# CONFIG_BT_LEDS is not set ++# CONFIG_BT_MRVL is not set ++# CONFIG_BT_RFCOMM is not set ++CONFIG_BT_RFCOMM_TTY=y ++# CONFIG_BT_SELFTEST is not set ++CONFIG_BUG=y ++# CONFIG_BUG_ON_DATA_CORRUPTION is not set ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_C2PORT is not set ++CONFIG_CACHE_L2X0_PMU=y ++# CONFIG_CADENCE_WATCHDOG is not set ++# CONFIG_CAIF is not set ++# CONFIG_CAN is not set ++# CONFIG_CAN_BCM is not set ++# CONFIG_CAN_DEBUG_DEVICES is not set ++# CONFIG_CAN_DEV is not set ++# CONFIG_CAN_GS_USB is not set ++# CONFIG_CAN_GW is not set ++# CONFIG_CAN_HI311X is not set ++# CONFIG_CAN_IFI_CANFD is not set ++# CONFIG_CAN_MCBA_USB is not set ++# CONFIG_CAN_M_CAN is not set ++# CONFIG_CAN_PEAK_PCIEFD is not set ++# CONFIG_CAN_RAW is not set ++# CONFIG_CAN_RCAR is not set ++# CONFIG_CAN_RCAR_CANFD is not set ++# CONFIG_CAN_SLCAN is not set ++# CONFIG_CAN_SUN4I is not set ++# CONFIG_CAN_VCAN is not set ++# CONFIG_CAN_VXCAN is not set ++# CONFIG_CAPI_AVM is not set ++# CONFIG_CAPI_EICON is not set ++# CONFIG_CAPI_TRACE is not set ++CONFIG_CARDBUS=y ++# CONFIG_CARDMAN_4000 is not set ++# CONFIG_CARDMAN_4040 is not set ++# CONFIG_CARL9170 is not set ++# CONFIG_CASSINI is not set ++# CONFIG_CAVIUM_CPT is not set ++# CONFIG_CAVIUM_ERRATUM_22375 is not set ++# CONFIG_CAVIUM_ERRATUM_23144 is not set ++# CONFIG_CAVIUM_ERRATUM_23154 is not set ++# CONFIG_CAVIUM_ERRATUM_27456 is not set ++# CONFIG_CAVIUM_ERRATUM_30115 is not set ++# CONFIG_CAVIUM_OCTEON_SOC is not set ++# CONFIG_CB710_CORE is not set ++# CONFIG_CC10001_ADC is not set ++# CONFIG_CCS811 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++# CONFIG_CC_STACKPROTECTOR is not set ++CONFIG_CC_STACKPROTECTOR_NONE=y ++# CONFIG_CC_STACKPROTECTOR_REGULAR is not set ++# CONFIG_CC_STACKPROTECTOR_STRONG is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_CEPH_FS is not set ++# CONFIG_CEPH_LIB is not set ++# CONFIG_CFG80211 is not set ++# CONFIG_CFG80211_CERTIFICATION_ONUS is not set ++# CONFIG_CFQ_GROUP_IOSCHED is not set ++# CONFIG_CGROUPS is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_DETECTOR_MAX14656 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_ISP1704 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_LTC3651 is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_CHARGER_SBS is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_CHARGER_TWL4030 is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++# CONFIG_CHROME_PLATFORMS is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_CIFS is not set ++# CONFIG_CIFS_ACL is not set ++CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y ++# CONFIG_CIFS_DEBUG is not set ++# CONFIG_CIFS_DEBUG2 is not set ++# CONFIG_CIFS_FSCACHE is not set ++# CONFIG_CIFS_NFSD_EXPORT is not set ++CONFIG_CIFS_POSIX=y ++# CONFIG_CIFS_SMB2 is not set ++CONFIG_CIFS_STATS=y ++# CONFIG_CIFS_STATS2 is not set ++# CONFIG_CIFS_WEAK_PW_HASH is not set ++# CONFIG_CIFS_XATTR is not set ++# CONFIG_CIO_DAC is not set ++# CONFIG_CLEANCACHE is not set ++# CONFIG_CLKSRC_VERSATILE is not set ++# CONFIG_CLK_HSDK is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_CLOCK_THERMAL is not set ++CONFIG_CLS_U32_MARK=y ++# CONFIG_CLS_U32_PERF is not set ++# CONFIG_CM32181 is not set ++# CONFIG_CM3232 is not set ++# CONFIG_CM3323 is not set ++# CONFIG_CM3605 is not set ++# CONFIG_CM36651 is not set ++# CONFIG_CMA is not set ++CONFIG_CMDLINE="" ++# CONFIG_CMDLINE_BOOL is not set ++# CONFIG_CMDLINE_EXTEND is not set ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_CMDLINE_FROM_BOOTLOADER is not set ++# CONFIG_CMDLINE_PARTITION is not set ++# CONFIG_CNIC is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_CODE_PATCHING_SELFTEST is not set ++# CONFIG_COMEDI is not set ++# CONFIG_COMMON_CLK_CDCE706 is not set ++# CONFIG_COMMON_CLK_CDCE925 is not set ++# CONFIG_COMMON_CLK_CS2000_CP is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_PWM is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SI514 is not set ++# CONFIG_COMMON_CLK_SI5351 is not set ++# CONFIG_COMMON_CLK_SI570 is not set ++# CONFIG_COMMON_CLK_VC5 is not set ++# CONFIG_COMMON_CLK_VERSATILE is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++CONFIG_COMPACTION=y ++# CONFIG_COMPAL_LAPTOP is not set ++# CONFIG_COMPAT is not set ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_COMPILE_TEST is not set ++# CONFIG_CONFIGFS_FS is not set ++# CONFIG_CONNECTOR is not set ++CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 ++CONFIG_CONSTRUCTORS=y ++# CONFIG_CONTEXT_SWITCH_TRACER is not set ++# CONFIG_COPS is not set ++# CONFIG_CORDIC is not set ++# CONFIG_COREDUMP is not set ++# CONFIG_CORESIGHT is not set ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++# CONFIG_CORTINA_PHY is not set ++# CONFIG_CPA_DEBUG is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_FREQ is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_IDLE is not set ++# CONFIG_CPU_IDLE_GOV_MENU is not set ++# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set ++# CONFIG_CPU_NO_EFFICIENT_FFS is not set ++CONFIG_CPU_SW_DOMAIN_PAN=y ++# CONFIG_CRAMFS is not set ++CONFIG_CRASHLOG=y ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_CRC16 is not set ++CONFIG_CRC32=y ++# CONFIG_CRC32_BIT is not set ++CONFIG_CRC32_SARWATE=y ++# CONFIG_CRC32_SELFTEST is not set ++# CONFIG_CRC32_SLICEBY4 is not set ++# CONFIG_CRC32_SLICEBY8 is not set ++# CONFIG_CRC4 is not set ++# CONFIG_CRC7 is not set ++# CONFIG_CRC8 is not set ++# CONFIG_CRC_CCITT is not set ++# CONFIG_CRC_ITU_T is not set ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CROSS_COMPILE="" ++# CONFIG_CROSS_MEMORY_ATTACH is not set ++CONFIG_CRYPTO=y ++# CONFIG_CRYPTO_842 is not set ++# CONFIG_CRYPTO_AEAD is not set ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_586 is not set ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_AES_NI_INTEL is not set ++# CONFIG_CRYPTO_AES_TI is not set ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_AUTHENC is not set ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_CHACHA20 is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_CRC32C_INTEL is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_CRYPTD is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_DEFLATE is not set ++# CONFIG_CRYPTO_DES is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AUTHENC is not set ++# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set ++# CONFIG_CRYPTO_DEV_ATMEL_SHA is not set ++# CONFIG_CRYPTO_DEV_ATMEL_TDES is not set ++# CONFIG_CRYPTO_DEV_CAVIUM_ZIP is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_CCREE is not set ++# CONFIG_CRYPTO_DEV_FSL_CAAM is not set ++# CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC is not set ++# CONFIG_CRYPTO_DEV_HIFN_795X is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++# CONFIG_CRYPTO_DEV_MARVELL_CESA is not set ++# CONFIG_CRYPTO_DEV_MV_CESA is not set ++# CONFIG_CRYPTO_DEV_MXC_SCC is not set ++# CONFIG_CRYPTO_DEV_MXS_DCP is not set ++# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set ++# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set ++# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set ++# CONFIG_CRYPTO_DEV_QAT_C62X is not set ++# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set ++# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set ++# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_SAFEXCEL is not set ++# CONFIG_CRYPTO_DEV_SAHARA is not set ++# CONFIG_CRYPTO_DEV_TALITOS is not set ++# CONFIG_CRYPTO_DEV_VIRTIO is not set ++# CONFIG_CRYPTO_DH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_MENU is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_ECDH is not set ++# CONFIG_CRYPTO_ECHAINIV is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_FIPS is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set ++# CONFIG_CRYPTO_HASH is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_HW is not set ++# CONFIG_CRYPTO_JITTERENTROPY is not set ++# CONFIG_CRYPTO_KEYWRAP is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_LZ4 is not set ++# CONFIG_CRYPTO_LZ4HC is not set ++# CONFIG_CRYPTO_LZO is not set ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_MCRYPTD is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_PCOMP is not set ++# CONFIG_CRYPTO_PCOMP2 is not set ++CONFIG_CRYPTO_PCRYPT=y ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++# CONFIG_CRYPTO_RNG is not set ++# CONFIG_CRYPTO_RSA is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SALSA20_586 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SEQIV is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_SHA1 is not set ++# CONFIG_CRYPTO_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA3 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TEST is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++# CONFIG_CRYPTO_TWOFISH_586 is not set ++# CONFIG_CRYPTO_TWOFISH_COMMON is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_VMAC is not set ++# CONFIG_CRYPTO_WP512 is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++# CONFIG_CRYPTO_ZLIB is not set ++# CONFIG_CS5535_MFGPT is not set ++# CONFIG_CS89x0 is not set ++# CONFIG_CUSE is not set ++# CONFIG_CW1200 is not set ++# CONFIG_CXL_AFU_DRIVER_OPS is not set ++# CONFIG_CXL_BASE is not set ++# CONFIG_CXL_EEH is not set ++# CONFIG_CXL_KERNEL_API is not set ++# CONFIG_CXL_LIB is not set ++# CONFIG_CYPRESS_FIRMWARE is not set ++# CONFIG_DA280 is not set ++# CONFIG_DA311 is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_DAX is not set ++# CONFIG_DCB is not set ++# CONFIG_DDR is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_EFI is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_DEBUG_GPIO is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_ICEDCC is not set ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_DEBUG_INFO_DWARF4 is not set ++CONFIG_DEBUG_INFO_REDUCED=y ++# CONFIG_DEBUG_INFO_SPLIT is not set ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_KOBJECT_RELEASE is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_LL is not set ++# CONFIG_DEBUG_LL_UART_8250 is not set ++# CONFIG_DEBUG_LL_UART_PL01X is not set ++# CONFIG_DEBUG_LOCKDEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_NX_TEST is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_PAGE_REF is not set ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_PREEMPT is not set ++# CONFIG_DEBUG_RODATA_TEST is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_SEMIHOSTING is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_SHIRQ is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_STACKOVERFLOW is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_DEBUG_UART_8250_PALMCHIP is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++# CONFIG_DEBUG_VIRTUAL is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_VM_PGFLAGS is not set ++# CONFIG_DEBUG_VM_RB is not set ++# CONFIG_DEBUG_VM_VMACACHE is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_WX is not set ++# CONFIG_DEBUG_ZBOOT is not set ++# CONFIG_DECNET is not set ++CONFIG_DEFAULT_CUBIC=y ++CONFIG_DEFAULT_DEADLINE=y ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++CONFIG_DEFAULT_IOSCHED="deadline" ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_DEFAULT_NOOP is not set ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_SECURITY="" ++CONFIG_DEFAULT_SECURITY_DAC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++# CONFIG_DELL_LAPTOP is not set ++# CONFIG_DELL_RBTN is not set ++# CONFIG_DELL_SMO8800 is not set ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_DEVKMEM is not set ++# CONFIG_DEVMEM is not set ++CONFIG_DEVPORT=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# CONFIG_DEVTMPFS is not set ++# CONFIG_DEVTMPFS_MOUNT is not set ++# CONFIG_DEV_DAX is not set ++# CONFIG_DGAP is not set ++# CONFIG_DGNC is not set ++# CONFIG_DHT11 is not set ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_DISPLAY_CONNECTOR_ANALOG_TV is not set ++# CONFIG_DISPLAY_CONNECTOR_DVI is not set ++# CONFIG_DISPLAY_CONNECTOR_HDMI is not set ++# CONFIG_DISPLAY_ENCODER_TFP410 is not set ++# CONFIG_DISPLAY_ENCODER_TPD12S015 is not set ++# CONFIG_DISPLAY_PANEL_DPI is not set ++# CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02 is not set ++# CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1 is not set ++# CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1 is not set ++# CONFIG_DL2K is not set ++# CONFIG_DLM is not set ++# CONFIG_DM9000 is not set ++# CONFIG_DMADEVICES is not set ++# CONFIG_DMADEVICES_DEBUG is not set ++# CONFIG_DMARD06 is not set ++# CONFIG_DMARD09 is not set ++# CONFIG_DMARD10 is not set ++# CONFIG_DMASCC is not set ++# CONFIG_DMATEST is not set ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_DMA_ENGINE is not set ++# CONFIG_DMA_FENCE_TRACE is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_NOOP_OPS is not set ++# CONFIG_DMA_SHARED_BUFFER is not set ++# CONFIG_DMA_VIRT_OPS is not set ++# CONFIG_DM_CACHE is not set ++# CONFIG_DM_DEBUG is not set ++# CONFIG_DM_DELAY is not set ++# CONFIG_DM_ERA is not set ++# CONFIG_DM_FLAKEY is not set ++# CONFIG_DM_INTEGRITY is not set ++# CONFIG_DM_LOG_USERSPACE is not set ++# CONFIG_DM_LOG_WRITES is not set ++# CONFIG_DM_MQ_DEFAULT is not set ++# CONFIG_DM_MULTIPATH is not set ++# CONFIG_DM_RAID is not set ++# CONFIG_DM_SWITCH is not set ++# CONFIG_DM_THIN_PROVISIONING is not set ++# CONFIG_DM_UEVENT is not set ++# CONFIG_DM_VERITY is not set ++# CONFIG_DM_ZERO is not set ++# CONFIG_DNET is not set ++# CONFIG_DNOTIFY is not set ++# CONFIG_DNS_RESOLVER is not set ++CONFIG_DOUBLEFAULT=y ++# CONFIG_DP83848_PHY is not set ++# CONFIG_DP83867_PHY is not set ++# CONFIG_DPOT_DAC is not set ++CONFIG_DQL=y ++# CONFIG_DRAGONRISE_FF is not set ++# CONFIG_DRM is not set ++# CONFIG_DRM_AMDGPU is not set ++# CONFIG_DRM_AMDGPU_CIK is not set ++# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set ++# CONFIG_DRM_AMDGPU_SI is not set ++# CONFIG_DRM_AMDGPU_USERPTR is not set ++# CONFIG_DRM_AMD_ACP is not set ++# CONFIG_DRM_ANALOGIX_ANX78XX is not set ++# CONFIG_DRM_ARCPGU is not set ++# CONFIG_DRM_ARMADA is not set ++# CONFIG_DRM_AST is not set ++# CONFIG_DRM_BOCHS is not set ++# CONFIG_DRM_CIRRUS_QEMU is not set ++# CONFIG_DRM_DEBUG_MM is not set ++# CONFIG_DRM_DEBUG_MM_SELFTEST is not set ++# CONFIG_DRM_DP_AUX_CHARDEV is not set ++# CONFIG_DRM_DUMB_VGA_DAC is not set ++# CONFIG_DRM_DW_HDMI_CEC is not set ++# CONFIG_DRM_ETNAVIV is not set ++# CONFIG_DRM_EXYNOS is not set ++# CONFIG_DRM_FBDEV_EMULATION is not set ++# CONFIG_DRM_FSL_DCU is not set ++# CONFIG_DRM_GMA500 is not set ++# CONFIG_DRM_HDLCD is not set ++# CONFIG_DRM_HISI_HIBMC is not set ++# CONFIG_DRM_HISI_KIRIN is not set ++# CONFIG_DRM_I2C_ADV7511 is not set ++# CONFIG_DRM_I2C_CH7006 is not set ++# CONFIG_DRM_I2C_NXP_TDA998X is not set ++# CONFIG_DRM_I2C_SIL164 is not set ++# CONFIG_DRM_I915 is not set ++# CONFIG_DRM_LEGACY is not set ++# CONFIG_DRM_LIB_RANDOM is not set ++# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set ++# CONFIG_DRM_LVDS_ENCODER is not set ++# CONFIG_DRM_MALI_DISPLAY is not set ++# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set ++# CONFIG_DRM_MGAG200 is not set ++# CONFIG_DRM_MXSFB is not set ++# CONFIG_DRM_NOUVEAU is not set ++# CONFIG_DRM_NXP_PTN3460 is not set ++# CONFIG_DRM_OMAP is not set ++# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set ++# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set ++# CONFIG_DRM_PANEL_LG_LG4573 is not set ++# CONFIG_DRM_PANEL_LVDS is not set ++# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set ++# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set ++# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set ++# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set ++# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set ++# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set ++# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set ++# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set ++# CONFIG_DRM_PARADE_PS8622 is not set ++# CONFIG_DRM_PL111 is not set ++# CONFIG_DRM_QXL is not set ++# CONFIG_DRM_RADEON is not set ++# CONFIG_DRM_RADEON_USERPTR is not set ++# CONFIG_DRM_RCAR_DW_HDMI is not set ++# CONFIG_DRM_SII902X is not set ++# CONFIG_DRM_SIL_SII8620 is not set ++# CONFIG_DRM_STI is not set ++# CONFIG_DRM_STM is not set ++# CONFIG_DRM_SUN4I is not set ++# CONFIG_DRM_TILCDC is not set ++# CONFIG_DRM_TINYDRM is not set ++# CONFIG_DRM_TI_TFP410 is not set ++# CONFIG_DRM_TOSHIBA_TC358767 is not set ++# CONFIG_DRM_UDL is not set ++# CONFIG_DRM_VBOXVIDEO is not set ++# CONFIG_DRM_VGEM is not set ++# CONFIG_DRM_VIRTIO_GPU is not set ++# CONFIG_DRM_VMWGFX is not set ++# CONFIG_DS1682 is not set ++# CONFIG_DS1803 is not set ++# CONFIG_DST_CACHE is not set ++# CONFIG_DTLK is not set ++# CONFIG_DUMMY is not set ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_CORE is not set ++# CONFIG_DVB_DUMMY_FE is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++# CONFIG_DWC_XLGMAC is not set ++# CONFIG_DWMAC_IPQ806X is not set ++# CONFIG_DWMAC_LPC18XX is not set ++# CONFIG_DWMAC_MESON is not set ++# CONFIG_DWMAC_ROCKCHIP is not set ++# CONFIG_DWMAC_SOCFPGA is not set ++# CONFIG_DWMAC_STI is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++# CONFIG_DW_WATCHDOG is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++# CONFIG_E100 is not set ++# CONFIG_E1000 is not set ++# CONFIG_E1000E is not set ++# CONFIG_E1000E_HWTS is not set ++# CONFIG_EARLY_PRINTK_8250 is not set ++# CONFIG_EARLY_PRINTK_USB_XDBC is not set ++# CONFIG_ECHO is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_EDAC is not set ++# CONFIG_EEEPC_LAPTOP is not set ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_EEPROM_93XX46 is not set ++# CONFIG_EEPROM_AT24 is not set ++# CONFIG_EEPROM_AT25 is not set ++# CONFIG_EEPROM_DIGSY_MTC_CFG is not set ++# CONFIG_EEPROM_IDT_89HPESX is not set ++# CONFIG_EEPROM_LEGACY is not set ++# CONFIG_EEPROM_MAX6875 is not set ++# CONFIG_EFI is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_EFS_FS is not set ++CONFIG_ELFCORE=y ++# CONFIG_ELF_CORE is not set ++# CONFIG_EMAC_ROCKCHIP is not set ++CONFIG_EMBEDDED=y ++# CONFIG_EM_TIMER_STI is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_ENABLE_WARN_DEPRECATED=y ++# CONFIG_ENA_ETHERNET is not set ++# CONFIG_ENC28J60 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_ENCRYPTED_KEYS is not set ++# CONFIG_ENCX24J600 is not set ++# CONFIG_ENIC is not set ++# CONFIG_ENVELOPE_DETECTOR is not set ++# CONFIG_EPAPR_PARAVIRT is not set ++# CONFIG_EPIC100 is not set ++CONFIG_EPOLL=y ++# CONFIG_EQUALIZER is not set ++# CONFIG_ET131X is not set ++CONFIG_ETHERNET=y ++# CONFIG_ETHOC is not set ++CONFIG_EVENTFD=y ++CONFIG_EXPERT=y ++CONFIG_EXPORTFS=y ++# CONFIG_EXPORTFS_BLOCK_OPS is not set ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_EXT4_DEBUG is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_FS is not set ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXTCON is not set ++# CONFIG_EXTCON_ADC_JACK is not set ++# CONFIG_EXTCON_AXP288 is not set ++# CONFIG_EXTCON_GPIO is not set ++# CONFIG_EXTCON_INTEL_INT3496 is not set ++# CONFIG_EXTCON_MAX3355 is not set ++# CONFIG_EXTCON_QCOM_SPMI_MISC is not set ++# CONFIG_EXTCON_RT8973A is not set ++# CONFIG_EXTCON_SM5502 is not set ++# CONFIG_EXTCON_USB_GPIO is not set ++CONFIG_EXTRA_FIRMWARE="" ++CONFIG_EXTRA_TARGETS="" ++# CONFIG_EXYNOS_ADC is not set ++# CONFIG_EXYNOS_VIDEO is not set ++# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set ++# CONFIG_EZX_PCAP is not set ++# CONFIG_F2FS_FAULT_INJECTION is not set ++# CONFIG_F2FS_FS is not set ++# CONFIG_F2FS_FS_ENCRYPTION is not set ++# CONFIG_F2FS_FS_POSIX_ACL is not set ++# CONFIG_F2FS_IO_TRACE is not set ++# CONFIG_FAIR_GROUP_SCHED is not set ++# CONFIG_FANOTIFY is not set ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_FAT_DEFAULT_UTF8 is not set ++# CONFIG_FAT_FS is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_FB is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_ARC is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_BIG_ENDIAN is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_BOTH_ENDIAN is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_DA8XX is not set ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_FLEX is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_GEODE is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_HGA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_IMX is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_LE80578 is not set ++# CONFIG_FB_LITTLE_ENDIAN is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_MXS is not set ++# CONFIG_FB_N411 is not set ++# CONFIG_FB_NEOMAGIC is not set ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_OF is not set ++# CONFIG_FB_OMAP2 is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_PS3 is not set ++# CONFIG_FB_PXA is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FB_TFT_AGM1264K_FL is not set ++# CONFIG_FB_TFT_BD663474 is not set ++# CONFIG_FB_TFT_FBTFT_DEVICE is not set ++# CONFIG_FB_TFT_HX8340BN is not set ++# CONFIG_FB_TFT_HX8347D is not set ++# CONFIG_FB_TFT_HX8353D is not set ++# CONFIG_FB_TFT_HX8357D is not set ++# CONFIG_FB_TFT_ILI9163 is not set ++# CONFIG_FB_TFT_ILI9320 is not set ++# CONFIG_FB_TFT_ILI9325 is not set ++# CONFIG_FB_TFT_ILI9340 is not set ++# CONFIG_FB_TFT_ILI9341 is not set ++# CONFIG_FB_TFT_ILI9481 is not set ++# CONFIG_FB_TFT_ILI9486 is not set ++# CONFIG_FB_TFT_PCD8544 is not set ++# CONFIG_FB_TFT_RA8875 is not set ++# CONFIG_FB_TFT_S6D02A1 is not set ++# CONFIG_FB_TFT_S6D1121 is not set ++# CONFIG_FB_TFT_SH1106 is not set ++# CONFIG_FB_TFT_SSD1289 is not set ++# CONFIG_FB_TFT_SSD1305 is not set ++# CONFIG_FB_TFT_SSD1306 is not set ++# CONFIG_FB_TFT_SSD1325 is not set ++# CONFIG_FB_TFT_SSD1331 is not set ++# CONFIG_FB_TFT_SSD1351 is not set ++# CONFIG_FB_TFT_ST7735R is not set ++# CONFIG_FB_TFT_ST7789V is not set ++# CONFIG_FB_TFT_TINYLCD is not set ++# CONFIG_FB_TFT_TLS8204 is not set ++# CONFIG_FB_TFT_UC1611 is not set ++# CONFIG_FB_TFT_UC1701 is not set ++# CONFIG_FB_TFT_UPD161704 is not set ++# CONFIG_FB_TFT_WATTEROTT is not set ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_UVESA is not set ++# CONFIG_FB_VGA16 is not set ++# CONFIG_FB_VIA is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_XGI is not set ++# CONFIG_FCOE is not set ++# CONFIG_FCOE_FNIC is not set ++# CONFIG_FDDI is not set ++# CONFIG_FEALNX is not set ++# CONFIG_FENCE_TRACE is not set ++# CONFIG_FHANDLE is not set ++CONFIG_FIB_RULES=y ++CONFIG_FILE_LOCKING=y ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++# CONFIG_FIREWIRE_SERIAL is not set ++# CONFIG_FIRMWARE_EDID is not set ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FIXED_PHY is not set ++CONFIG_FLATMEM=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++# CONFIG_FM10K is not set ++# CONFIG_FMC is not set ++# CONFIG_FORCEDETH is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++CONFIG_FORTIFY_SOURCE=y ++# CONFIG_FPGA is not set ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_FRAME_POINTER is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_FREEZER is not set ++# CONFIG_FRONTSWAP is not set ++# CONFIG_FSCACHE is not set ++# CONFIG_FSI is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_FSL_ERRATUM_A008585 is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_FSL_PQ_MDIO is not set ++# CONFIG_FSL_XGMAC_MDIO is not set ++CONFIG_FSNOTIFY=y ++# CONFIG_FS_DAX is not set ++# CONFIG_FS_ENCRYPTION is not set ++# CONFIG_FS_POSIX_ACL is not set ++# CONFIG_FTGMAC100 is not set ++# CONFIG_FTL is not set ++# CONFIG_FTMAC100 is not set ++# CONFIG_FTRACE is not set ++# CONFIG_FTRACE_STARTUP_TEST is not set ++# CONFIG_FTR_FIXUP_SELFTEST is not set ++# CONFIG_FUJITSU_ES is not set ++# CONFIG_FUJITSU_LAPTOP is not set ++# CONFIG_FUJITSU_TABLET is not set ++# CONFIG_FUNCTION_TRACER is not set ++# CONFIG_FUSE_FS is not set ++# CONFIG_FUSION is not set ++# CONFIG_FUSION_FC is not set ++# CONFIG_FUSION_SAS is not set ++# CONFIG_FUSION_SPI is not set ++CONFIG_FUTEX=y ++CONFIG_FUTEX_PI=y ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_FW_LOADER=y ++CONFIG_FW_LOADER_USER_HELPER=y ++CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y ++CONFIG_GACT_PROB=y ++# CONFIG_GADGET_UAC1 is not set ++# CONFIG_GAMEPORT is not set ++# CONFIG_GATEWORKS_GW16083 is not set ++# CONFIG_GCC_PLUGINS is not set ++# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set ++# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set ++# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set ++# CONFIG_GCC_PLUGIN_STRUCTLEAK is not set ++# CONFIG_GCOV is not set ++# CONFIG_GCOV_KERNEL is not set ++# CONFIG_GDB_SCRIPTS is not set ++# CONFIG_GENERIC_ADC_BATTERY is not set ++# CONFIG_GENERIC_ADC_THERMAL is not set ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_HWEIGHT=y ++# CONFIG_GENERIC_IRQ_DEBUGFS is not set ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_NET_UTILS=y ++# CONFIG_GENERIC_PHY is not set ++# CONFIG_GENEVE is not set ++# CONFIG_GENWQE is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_GIGASET_CAPI is not set ++# CONFIG_GIGASET_DEBUG is not set ++# CONFIG_GIGASET_DUMMYLL is not set ++# CONFIG_GLOB_SELFTEST is not set ++# CONFIG_GOLDFISH is not set ++# CONFIG_GOOGLE_FIRMWARE is not set ++# CONFIG_GP2AP020A00F is not set ++# CONFIG_GPIOLIB is not set ++# CONFIG_GPIO_74X164 is not set ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ADNP is not set ++# CONFIG_GPIO_ADP5588 is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_AMDPT is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_CS5535 is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_EXAR is not set ++# CONFIG_GPIO_F7188X is not set ++# CONFIG_GPIO_FTGPIO010 is not set ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_GPIO_MM is not set ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_ICH is not set ++# CONFIG_GPIO_IT87 is not set ++# CONFIG_GPIO_LYNXPOINT is not set ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MPC8XXX is not set ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_PCI_IDIO_16 is not set ++# CONFIG_GPIO_PISOSR is not set ++# CONFIG_GPIO_PL061 is not set ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_RDC321X is not set ++# CONFIG_GPIO_SCH is not set ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SX150X is not set ++# CONFIG_GPIO_SYSCON is not set ++CONFIG_GPIO_SYSFS=y ++# CONFIG_GPIO_TPIC2810 is not set ++# CONFIG_GPIO_TS4900 is not set ++# CONFIG_GPIO_TS5500 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_WATCHDOG is not set ++# CONFIG_GPIO_WS16C48 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XRA1403 is not set ++# CONFIG_GPIO_ZEVIO is not set ++# CONFIG_GPIO_ZX is not set ++# CONFIG_GREENASIA_FF is not set ++# CONFIG_GREYBUS is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_GTP is not set ++# CONFIG_HAMACHI is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_HAPPYMEAL is not set ++CONFIG_HARDENED_USERCOPY=y ++# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++# CONFIG_HAVE_AOUT is not set ++CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y ++# CONFIG_HAVE_ARCH_HASH is not set ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++# CONFIG_HAVE_ARCH_VMAP_STACK is not set ++CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y ++# CONFIG_HAVE_ARM_ARCH_TIMER is not set ++CONFIG_HAVE_EXIT_THREAD=y ++CONFIG_HAVE_GCC_PLUGINS=y ++CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y ++CONFIG_HAVE_KERNEL_BZIP2=y ++CONFIG_HAVE_KERNEL_CAT=y ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_LZ4=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_HAVE_KERNEL_XZ=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_NMI=y ++# CONFIG_HCALL_STATS is not set ++# CONFIG_HDC100X is not set ++# CONFIG_HDLC is not set ++# CONFIG_HDLC_CISCO is not set ++# CONFIG_HDLC_FR is not set ++# CONFIG_HDLC_PPP is not set ++# CONFIG_HDLC_RAW is not set ++# CONFIG_HDLC_RAW_ETH is not set ++# CONFIG_HDMI_LPE_AUDIO is not set ++# CONFIG_HDQ_MASTER_OMAP is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_HERMES is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_HFSPLUS_FS_POSIX_ACL is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFS_FS_POSIX_ACL is not set ++# CONFIG_HI8435 is not set ++# CONFIG_HIBERNATION is not set ++# CONFIG_HID is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACCUTOUCH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_ACRUX_FF is not set ++# CONFIG_HID_ALPS is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_ASUS is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CORSAIR is not set ++# CONFIG_HID_CP2112 is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GENERIC is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_GT683R is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_ITE is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LED is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_LOGITECH_DJ is not set ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_HID_MAGICMOUSE is not set ++# CONFIG_HID_MAYFLASH is not set ++# CONFIG_HID_MICROSOFT is not set ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTI is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PID is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_PRODIKEYS is not set ++# CONFIG_HID_RETRODE is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_SONY is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_THINGM is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_UDRAW_PS3 is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_WIIMOTE is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HIGHMEM is not set ++CONFIG_HIGH_RES_TIMERS=y ++# CONFIG_HINIC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HIPPI is not set ++# CONFIG_HISILICON_ERRATUM_161010101 is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HMC6352 is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS3 is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_HOSTAP_CS is not set ++# CONFIG_HOSTAP_PCI is not set ++# CONFIG_HOSTAP_PLX is not set ++# CONFIG_HOTPLUG_CPU is not set ++# CONFIG_HOTPLUG_PCI is not set ++# CONFIG_HP03 is not set ++# CONFIG_HP100 is not set ++# CONFIG_HP206C is not set ++CONFIG_HPET_MMAP_DEFAULT=y ++# CONFIG_HPFS_FS is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_HP_WIRELESS is not set ++# CONFIG_HSI is not set ++# CONFIG_HSR is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTS221 is not set ++# CONFIG_HTU21 is not set ++# CONFIG_HUGETLB_PAGE is not set ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_HVC_UDBG is not set ++# CONFIG_HWLAT_TRACER is not set ++# CONFIG_HWMON is not set ++# CONFIG_HWMON_DEBUG_CHIP is not set ++# CONFIG_HWMON_VID is not set ++# CONFIG_HWSPINLOCK is not set ++# CONFIG_HWSPINLOCK_OMAP is not set ++CONFIG_HW_PERF_EVENTS=y ++# CONFIG_HW_RANDOM is not set ++# CONFIG_HW_RANDOM_AMD is not set ++# CONFIG_HW_RANDOM_ATMEL is not set ++# CONFIG_HW_RANDOM_CAVIUM is not set ++# CONFIG_HW_RANDOM_EXYNOS is not set ++# CONFIG_HW_RANDOM_GEODE is not set ++# CONFIG_HW_RANDOM_INTEL is not set ++# CONFIG_HW_RANDOM_IPROC_RNG200 is not set ++# CONFIG_HW_RANDOM_OMAP is not set ++# CONFIG_HW_RANDOM_OMAP3_ROM is not set ++# CONFIG_HW_RANDOM_PPC4XX is not set ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_HW_RANDOM_TPM is not set ++# CONFIG_HW_RANDOM_VIA is not set ++# CONFIG_HW_RANDOM_VIRTIO is not set ++# CONFIG_HX711 is not set ++# CONFIG_HYPERV is not set ++# CONFIG_HYPERV_TSCPAGE is not set ++# CONFIG_HYSDN is not set ++CONFIG_HZ=100 ++CONFIG_HZ_100=y ++# CONFIG_HZ_1000 is not set ++# CONFIG_HZ_1024 is not set ++# CONFIG_HZ_128 is not set ++# CONFIG_HZ_200 is not set ++# CONFIG_HZ_24 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_256 is not set ++# CONFIG_HZ_300 is not set ++# CONFIG_HZ_48 is not set ++# CONFIG_HZ_500 is not set ++# CONFIG_HZ_PERIODIC is not set ++# CONFIG_I2C is not set ++# CONFIG_I2C_ALGOBIT is not set ++# CONFIG_I2C_ALGOPCA is not set ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_AU1550 is not set ++# CONFIG_I2C_BCM2835 is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_CHARDEV is not set ++# CONFIG_I2C_COMPAT is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEMUX_PINCTRL is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DIOLAN_U2C is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_ELEKTOR is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HELPER_AUTO is not set ++# CONFIG_I2C_HID is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_IBM_IIC is not set ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_ISMT is not set ++# CONFIG_I2C_MLXCPLD is not set ++# CONFIG_I2C_MPC is not set ++# CONFIG_I2C_MUX is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_GPMUX is not set ++# CONFIG_I2C_MUX_LTC4306 is not set ++# CONFIG_I2C_MUX_MLXCPLD is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_MV64XXX is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_NOMADIK is not set ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_OCTEON is not set ++# CONFIG_I2C_PARPORT is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_PCA_ISA is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_PXA_PCI is not set ++# CONFIG_I2C_RCAR is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_ROBOTFUZZ_OSIF is not set ++# CONFIG_I2C_S3C2410 is not set ++# CONFIG_I2C_SCMI is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_SLAVE is not set ++# CONFIG_I2C_SMBUS is not set ++# CONFIG_I2C_STUB is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_TINY_USB is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I40E is not set ++# CONFIG_I40EVF is not set ++# CONFIG_I6300ESB_WDT is not set ++# CONFIG_I82092 is not set ++# CONFIG_I82365 is not set ++# CONFIG_IAQCORE is not set ++# CONFIG_IBM_ASM is not set ++# CONFIG_IBM_EMAC_DEBUG is not set ++# CONFIG_IBM_EMAC_EMAC4 is not set ++# CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT is not set ++# CONFIG_IBM_EMAC_MAL_COMMON_ERR is not set ++# CONFIG_IBM_EMAC_NO_FLOW_CTRL is not set ++# CONFIG_IBM_EMAC_RGMII is not set ++# CONFIG_IBM_EMAC_TAH is not set ++# CONFIG_IBM_EMAC_ZMII is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_IDE is not set ++# CONFIG_IDEAPAD_LAPTOP is not set ++# CONFIG_IDE_GD is not set ++# CONFIG_IDE_PROC_FS is not set ++# CONFIG_IDE_TASK_IOCTL is not set ++# CONFIG_IDLE_PAGE_TRACKING is not set ++# CONFIG_IEEE802154 is not set ++# CONFIG_IEEE802154_ADF7242 is not set ++# CONFIG_IEEE802154_ATUSB is not set ++# CONFIG_IEEE802154_CA8210 is not set ++# CONFIG_IFB is not set ++# CONFIG_IGB is not set ++# CONFIG_IGBVF is not set ++# CONFIG_IIO is not set ++# CONFIG_IIO_BUFFER_CB is not set ++# CONFIG_IIO_CONFIGFS is not set ++CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 ++# CONFIG_IIO_INTERRUPT_TRIGGER is not set ++# CONFIG_IIO_MUX is not set ++# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set ++# CONFIG_IIO_SIMPLE_DUMMY is not set ++# CONFIG_IIO_SSP_SENSORHUB is not set ++# CONFIG_IIO_ST_ACCEL_3AXIS is not set ++# CONFIG_IIO_ST_GYRO_3AXIS is not set ++# CONFIG_IIO_ST_LSM6DSX is not set ++# CONFIG_IIO_ST_MAGN_3AXIS is not set ++# CONFIG_IIO_ST_PRESS is not set ++# CONFIG_IIO_SW_DEVICE is not set ++# CONFIG_IIO_SW_TRIGGER is not set ++# CONFIG_IIO_SYSFS_TRIGGER is not set ++# CONFIG_IKCONFIG is not set ++# CONFIG_IKCONFIG_PROC is not set ++# CONFIG_IMAGE_CMDLINE_HACK is not set ++# CONFIG_IMGPDC_WDT is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_IMX7D_ADC is not set ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_IMX_THERMAL is not set ++# CONFIG_INA2XX_ADC is not set ++CONFIG_INET=y ++# CONFIG_INET6_AH is not set ++# CONFIG_INET6_ESP is not set ++# CONFIG_INET6_IPCOMP is not set ++# CONFIG_INET6_TUNNEL is not set ++# CONFIG_INET6_XFRM_MODE_BEET is not set ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET6_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_LRO is not set ++# CONFIG_INET_TCP_DIAG is not set ++# CONFIG_INET_TUNNEL is not set ++# CONFIG_INET_UDP_DIAG is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++# CONFIG_INFINIBAND is not set ++# CONFIG_INFTL is not set ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++CONFIG_INOTIFY_USER=y ++# CONFIG_INPUT is not set ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_APANEL is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_ATLAS_BTNS is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_AXP20X_PEK is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set ++# CONFIG_INPUT_IMS_PCU is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_LEDS is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++# CONFIG_INPUT_MAX8997_HAPTIC is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_PALMAS_PWRBUTTON is not set ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_PCSPKR is not set ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_PWM_BEEPER is not set ++# CONFIG_INPUT_PWM_VIBRA is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_TPS65218_PWRBUTTON is not set ++# CONFIG_INPUT_TWL4030_PWRBUTTON is not set ++# CONFIG_INPUT_TWL4030_VIBRA is not set ++# CONFIG_INPUT_TWL6040_VIBRA is not set ++# CONFIG_INPUT_UINPUT is not set ++# CONFIG_INPUT_WISTRON_BTNS is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INT340X_THERMAL is not set ++# CONFIG_INTEL_CHT_INT33FE is not set ++# CONFIG_INTEL_HID_EVENT is not set ++# CONFIG_INTEL_IDLE is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_INTEL_IOATDMA is not set ++# CONFIG_INTEL_ISH_HID is not set ++# CONFIG_INTEL_MEI is not set ++# CONFIG_INTEL_MEI_ME is not set ++# CONFIG_INTEL_MEI_TXE is not set ++# CONFIG_INTEL_MIC_CARD is not set ++# CONFIG_INTEL_MIC_HOST is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_INTEL_OAKTRAIL is not set ++# CONFIG_INTEL_PMC_CORE is not set ++# CONFIG_INTEL_PUNIT_IPC is not set ++# CONFIG_INTEL_RST is not set ++# CONFIG_INTEL_SMARTCONNECT is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_INTEL_SOC_PMIC_CHTWC is not set ++# CONFIG_INTEL_TH is not set ++# CONFIG_INTEL_VBTN is not set ++# CONFIG_INTEL_XWAY_PHY is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_INV_MPU6050_I2C is not set ++# CONFIG_INV_MPU6050_IIO is not set ++# CONFIG_INV_MPU6050_SPI is not set ++# CONFIG_IOMMU_SUPPORT is not set ++# CONFIG_IOSCHED_BFQ is not set ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IO_STRICT_DEVMEM=y ++# CONFIG_IP17XX_PHY is not set ++# CONFIG_IP6_NF_FILTER is not set ++# CONFIG_IP6_NF_IPTABLES is not set ++# CONFIG_IP6_NF_MANGLE is not set ++# CONFIG_IP6_NF_MATCH_AH is not set ++# CONFIG_IP6_NF_MATCH_EUI64 is not set ++# CONFIG_IP6_NF_MATCH_FRAG is not set ++# CONFIG_IP6_NF_MATCH_HL is not set ++# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set ++# CONFIG_IP6_NF_MATCH_MH is not set ++# CONFIG_IP6_NF_MATCH_OPTS is not set ++# CONFIG_IP6_NF_MATCH_RPFILTER is not set ++# CONFIG_IP6_NF_MATCH_RT is not set ++# CONFIG_IP6_NF_NAT is not set ++# CONFIG_IP6_NF_RAW is not set ++# CONFIG_IP6_NF_SECURITY is not set ++# CONFIG_IP6_NF_TARGET_HL is not set ++# CONFIG_IP6_NF_TARGET_REJECT is not set ++# CONFIG_IP6_NF_TARGET_SYNPROXY is not set ++# CONFIG_IPACK_BUS is not set ++# CONFIG_IPC_NS is not set ++# CONFIG_IPMI_HANDLER is not set ++# CONFIG_IPV6 is not set ++# CONFIG_IPV6_FOU is not set ++# CONFIG_IPV6_FOU_TUNNEL is not set ++# CONFIG_IPV6_ILA is not set ++# CONFIG_IPV6_MIP6 is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_ROUTE_INFO is not set ++# CONFIG_IPV6_SEG6_HMAC is not set ++# CONFIG_IPV6_SEG6_LWTUNNEL is not set ++# CONFIG_IPV6_SIT is not set ++# CONFIG_IPV6_SIT_6RD is not set ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_VTI is not set ++# CONFIG_IPVLAN is not set ++# CONFIG_IPW2100 is not set ++# CONFIG_IPW2100_DEBUG is not set ++CONFIG_IPW2100_MONITOR=y ++# CONFIG_IPW2200 is not set ++# CONFIG_IPW2200_DEBUG is not set ++CONFIG_IPW2200_MONITOR=y ++# CONFIG_IPW2200_PROMISCUOUS is not set ++# CONFIG_IPW2200_QOS is not set ++# CONFIG_IPW2200_RADIOTAP is not set ++# CONFIG_IPWIRELESS is not set ++# CONFIG_IPX is not set ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_FIB_TRIE_STATS is not set ++# CONFIG_IP_MROUTE is not set ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_MULTIPLE_TABLES=y ++# CONFIG_IP_NF_ARPFILTER is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++# CONFIG_IP_NF_ARP_MANGLE is not set ++# CONFIG_IP_NF_FILTER is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_MANGLE is not set ++# CONFIG_IP_NF_MATCH_AH is not set ++# CONFIG_IP_NF_MATCH_ECN is not set ++# CONFIG_IP_NF_MATCH_RPFILTER is not set ++# CONFIG_IP_NF_MATCH_TTL is not set ++# CONFIG_IP_NF_RAW is not set ++# CONFIG_IP_NF_SECURITY is not set ++# CONFIG_IP_NF_TARGET_CLUSTERIP is not set ++# CONFIG_IP_NF_TARGET_ECN is not set ++# CONFIG_IP_NF_TARGET_MASQUERADE is not set ++# CONFIG_IP_NF_TARGET_NETMAP is not set ++# CONFIG_IP_NF_TARGET_REDIRECT is not set ++# CONFIG_IP_NF_TARGET_REJECT is not set ++# CONFIG_IP_NF_TARGET_SYNPROXY is not set ++# CONFIG_IP_NF_TARGET_TTL is not set ++# CONFIG_IP_PIMSM_V1 is not set ++# CONFIG_IP_PIMSM_V2 is not set ++# CONFIG_IP_PNP is not set ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++# CONFIG_IP_SCTP is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_SET_HASH_IPMAC is not set ++# CONFIG_IP_VS is not set ++# CONFIG_IRDA is not set ++# CONFIG_IRQSOFF_TRACER is not set ++# CONFIG_IRQ_ALL_CPUS is not set ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++# CONFIG_IRQ_POLL is not set ++# CONFIG_IRQ_TIME_ACCOUNTING is not set ++# CONFIG_IR_GPIO_CIR is not set ++# CONFIG_IR_HIX5HD2 is not set ++# CONFIG_IR_IGORPLUGUSB is not set ++# CONFIG_IR_IGUANA is not set ++# CONFIG_IR_IMG is not set ++# CONFIG_IR_IMON is not set ++# CONFIG_IR_JVC_DECODER is not set ++# CONFIG_IR_LIRC_CODEC is not set ++# CONFIG_IR_MCEUSB is not set ++# CONFIG_IR_NEC_DECODER is not set ++# CONFIG_IR_RC5_DECODER is not set ++# CONFIG_IR_RC6_DECODER is not set ++# CONFIG_IR_REDRAT3 is not set ++# CONFIG_IR_SONY_DECODER is not set ++# CONFIG_IR_STREAMZAP is not set ++# CONFIG_IR_TTUSBIR is not set ++# CONFIG_ISA_BUS is not set ++# CONFIG_ISA_BUS_API is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_ISCSI_TCP is not set ++CONFIG_ISDN=y ++# CONFIG_ISDN_AUDIO is not set ++# CONFIG_ISDN_CAPI is not set ++# CONFIG_ISDN_CAPI_CAPIDRV is not set ++# CONFIG_ISDN_DIVERSION is not set ++# CONFIG_ISDN_DRV_ACT2000 is not set ++# CONFIG_ISDN_DRV_GIGASET is not set ++# CONFIG_ISDN_DRV_HISAX is not set ++# CONFIG_ISDN_DRV_ICN is not set ++# CONFIG_ISDN_DRV_LOOP is not set ++# CONFIG_ISDN_DRV_PCBIT is not set ++# CONFIG_ISDN_DRV_SC is not set ++# CONFIG_ISDN_I4L is not set ++# CONFIG_ISL29003 is not set ++# CONFIG_ISL29020 is not set ++# CONFIG_ISL29125 is not set ++# CONFIG_ISO9660_FS is not set ++# CONFIG_ISS4xx is not set ++# CONFIG_ITG3200 is not set ++# CONFIG_IWL3945 is not set ++# CONFIG_IWLWIFI is not set ++# CONFIG_IXGB is not set ++# CONFIG_IXGBE is not set ++# CONFIG_IXGBEVF is not set ++# CONFIG_JBD2_DEBUG is not set ++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set ++# CONFIG_JFFS2_CMODE_NONE is not set ++CONFIG_JFFS2_CMODE_PRIORITY=y ++# CONFIG_JFFS2_CMODE_SIZE is not set ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++# CONFIG_JFFS2_FS_POSIX_ACL is not set ++# CONFIG_JFFS2_FS_SECURITY is not set ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++CONFIG_JFFS2_FS_XATTR=y ++CONFIG_JFFS2_LZMA=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++CONFIG_JFFS2_SUMMARY=y ++# CONFIG_JFFS2_ZLIB is not set ++# CONFIG_JFS_DEBUG is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_JFS_POSIX_ACL is not set ++# CONFIG_JFS_SECURITY is not set ++# CONFIG_JFS_STATISTICS is not set ++# CONFIG_JME is not set ++CONFIG_JOLIET=y ++# CONFIG_JSA1212 is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_KALLSYMS is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++# CONFIG_KALLSYMS_UNCOMPRESSED is not set ++# CONFIG_KARMA_PARTITION is not set ++# CONFIG_KASAN is not set ++# CONFIG_KCOV is not set ++# CONFIG_KERNEL_BZIP2 is not set ++# CONFIG_KERNEL_CAT is not set ++# CONFIG_KERNEL_GZIP is not set ++# CONFIG_KERNEL_LZ4 is not set ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_LZO is not set ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_KERNEL_XZ=y ++CONFIG_KERNFS=y ++# CONFIG_KEXEC is not set ++# CONFIG_KEXEC_FILE is not set ++# CONFIG_KEYBOARD_ADC is not set ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_BCM is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_DLINK_DIR685 is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_LM8323 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_PXA27x is not set ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_SNVS_PWRKEY is not set ++# CONFIG_KEYBOARD_STMPE is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_TEGRA is not set ++# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set ++# CONFIG_KEYBOARD_TWL4030 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYS is not set ++# CONFIG_KEY_DH_OPERATIONS is not set ++# CONFIG_KGDB is not set ++# CONFIG_KMEMCHECK is not set ++# CONFIG_KMX61 is not set ++# CONFIG_KPROBES is not set ++# CONFIG_KPROBES_SANITY_TEST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_KS8842 is not set ++# CONFIG_KS8851 is not set ++# CONFIG_KS8851_MLL is not set ++# CONFIG_KSM is not set ++# CONFIG_KSZ884X_PCI is not set ++CONFIG_KUSER_HELPERS=y ++# CONFIG_KVM_AMD is not set ++# CONFIG_KVM_GUEST is not set ++# CONFIG_KVM_INTEL is not set ++# CONFIG_KXCJK1013 is not set ++# CONFIG_KXSD9 is not set ++# CONFIG_L2TP is not set ++# CONFIG_L2TP_ETH is not set ++# CONFIG_L2TP_IP is not set ++# CONFIG_L2TP_V3 is not set ++# CONFIG_LANMEDIA is not set ++# CONFIG_LANTIQ is not set ++# CONFIG_LAPB is not set ++# CONFIG_LASAT is not set ++# CONFIG_LATENCYTOP is not set ++# CONFIG_LATTICE_ECP3_CONFIG is not set ++CONFIG_LBDAF=y ++# CONFIG_LCD_AMS369FG06 is not set ++# CONFIG_LCD_HX8357 is not set ++# CONFIG_LCD_ILI922X is not set ++# CONFIG_LCD_ILI9320 is not set ++# CONFIG_LCD_L4F00242T03 is not set ++# CONFIG_LCD_LD9040 is not set ++# CONFIG_LCD_LMS283GF05 is not set ++# CONFIG_LCD_LMS501KF03 is not set ++# CONFIG_LCD_LTV350QV is not set ++# CONFIG_LCD_S6E63M0 is not set ++# CONFIG_LCD_TDO24M is not set ++# CONFIG_LCD_VGG2432A4 is not set ++CONFIG_LDISC_AUTOLOAD=y ++# CONFIG_LDM_PARTITION is not set ++CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y ++# CONFIG_LEDS_BCM6328 is not set ++# CONFIG_LEDS_BCM6358 is not set ++# CONFIG_LEDS_BD2802 is not set ++# CONFIG_LEDS_BLINKM is not set ++CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y ++CONFIG_LEDS_CLASS=y ++# CONFIG_LEDS_CLASS_FLASH is not set ++# CONFIG_LEDS_DAC124S085 is not set ++# CONFIG_LEDS_GPIO is not set ++# CONFIG_LEDS_INTEL_SS4200 is not set ++# CONFIG_LEDS_IS31FL319X is not set ++# CONFIG_LEDS_IS31FL32XX is not set ++# CONFIG_LEDS_LM3530 is not set ++# CONFIG_LEDS_LM355x is not set ++# CONFIG_LEDS_LM3642 is not set ++# CONFIG_LEDS_LP3944 is not set ++# CONFIG_LEDS_LP3952 is not set ++# CONFIG_LEDS_LP5521 is not set ++# CONFIG_LEDS_LP5523 is not set ++# CONFIG_LEDS_LP5562 is not set ++# CONFIG_LEDS_LP8501 is not set ++# CONFIG_LEDS_LP8860 is not set ++# CONFIG_LEDS_LT3593 is not set ++# CONFIG_LEDS_MLXCPLD is not set ++# CONFIG_LEDS_NIC78BX is not set ++# CONFIG_LEDS_NS2 is not set ++# CONFIG_LEDS_OT200 is not set ++# CONFIG_LEDS_PCA9532 is not set ++# CONFIG_LEDS_PCA955X is not set ++# CONFIG_LEDS_PCA963X is not set ++# CONFIG_LEDS_PWM is not set ++# CONFIG_LEDS_REGULATOR is not set ++# CONFIG_LEDS_SYSCON is not set ++# CONFIG_LEDS_TCA6507 is not set ++# CONFIG_LEDS_TLC591XX is not set ++CONFIG_LEDS_TRIGGERS=y ++# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set ++# CONFIG_LEDS_TRIGGER_CAMERA is not set ++# CONFIG_LEDS_TRIGGER_CPU is not set ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++# CONFIG_LEDS_TRIGGER_DISK is not set ++# CONFIG_LEDS_TRIGGER_GPIO is not set ++# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set ++# CONFIG_LEDS_TRIGGER_MTD is not set ++CONFIG_LEDS_TRIGGER_NETDEV=y ++# CONFIG_LEDS_TRIGGER_ONESHOT is not set ++# CONFIG_LEDS_TRIGGER_PANIC is not set ++CONFIG_LEDS_TRIGGER_TIMER=y ++# CONFIG_LEDS_TRIGGER_TRANSIENT is not set ++# CONFIG_LEDS_USER is not set ++# CONFIG_LED_TRIGGER_PHY is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_LGUEST is not set ++# CONFIG_LIB80211 is not set ++# CONFIG_LIB80211_CRYPT_CCMP is not set ++# CONFIG_LIB80211_CRYPT_TKIP is not set ++# CONFIG_LIB80211_CRYPT_WEP is not set ++# CONFIG_LIB80211_DEBUG is not set ++# CONFIG_LIBCRC32C is not set ++# CONFIG_LIBERTAS is not set ++# CONFIG_LIBERTAS_THINFIRM is not set ++# CONFIG_LIBERTAS_USB is not set ++# CONFIG_LIBFC is not set ++# CONFIG_LIBFCOE is not set ++# CONFIG_LIBIPW_DEBUG is not set ++# CONFIG_LIBNVDIMM is not set ++# CONFIG_LIDAR_LITE_V2 is not set ++# CONFIG_LIQUIDIO is not set ++# CONFIG_LIQUIDIO_VF is not set ++# CONFIG_LIRC_STAGING is not set ++# CONFIG_LIS3L02DQ is not set ++# CONFIG_LKDTM is not set ++CONFIG_LLC=y ++# CONFIG_LLC2 is not set ++# CONFIG_LMP91000 is not set ++# CONFIG_LNET is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++# CONFIG_LOCKD is not set ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_LOCKD_V4=y ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++# CONFIG_LOGFS is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_LOGO is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++# CONFIG_LOONGSON_MC146818 is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_LP_CONSOLE is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_LTC2471 is not set ++# CONFIG_LTC2485 is not set ++# CONFIG_LTC2497 is not set ++# CONFIG_LTC2632 is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_LTPC is not set ++# CONFIG_LTR501 is not set ++# CONFIG_LUSTRE_FS is not set ++# CONFIG_LWTUNNEL is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_LZ4HC_COMPRESS is not set ++# CONFIG_LZ4_COMPRESS is not set ++# CONFIG_LZ4_DECOMPRESS is not set ++CONFIG_LZMA_COMPRESS=y ++CONFIG_LZMA_DECOMPRESS=y ++# CONFIG_LZO_COMPRESS is not set ++# CONFIG_LZO_DECOMPRESS is not set ++# CONFIG_M62332 is not set ++# CONFIG_MAC80211 is not set ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_MACB is not set ++# CONFIG_MACH_ASM9260 is not set ++# CONFIG_MACH_DECSTATION is not set ++# CONFIG_MACH_INGENIC is not set ++# CONFIG_MACH_JAZZ is not set ++# CONFIG_MACH_JZ4740 is not set ++# CONFIG_MACH_LOONGSON32 is not set ++# CONFIG_MACH_LOONGSON64 is not set ++# CONFIG_MACH_PIC32 is not set ++# CONFIG_MACH_PISTACHIO is not set ++# CONFIG_MACH_TX39XX is not set ++# CONFIG_MACH_TX49XX is not set ++# CONFIG_MACH_VR41XX is not set ++# CONFIG_MACH_XILFPGA is not set ++# CONFIG_MACINTOSH_DRIVERS is not set ++# CONFIG_MACSEC is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_MACVTAP is not set ++# CONFIG_MAC_EMUMOUSEBTN is not set ++# CONFIG_MAC_PARTITION is not set ++# CONFIG_MAG3110 is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++# CONFIG_MAGIC_SYSRQ_SERIAL is not set ++# CONFIG_MAILBOX is not set ++# CONFIG_MANDATORY_FILE_LOCKING is not set ++# CONFIG_MANGLE_BOOTARGS is not set ++# CONFIG_MARVELL_10G_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_MAX1027 is not set ++# CONFIG_MAX11100 is not set ++# CONFIG_MAX1118 is not set ++# CONFIG_MAX1363 is not set ++# CONFIG_MAX30100 is not set ++# CONFIG_MAX30102 is not set ++# CONFIG_MAX44000 is not set ++# CONFIG_MAX517 is not set ++# CONFIG_MAX5481 is not set ++# CONFIG_MAX5487 is not set ++# CONFIG_MAX5821 is not set ++# CONFIG_MAX63XX_WATCHDOG is not set ++# CONFIG_MAX9611 is not set ++# CONFIG_MAXIM_THERMOCOUPLE is not set ++CONFIG_MAY_USE_DEVLINK=y ++# CONFIG_MC3230 is not set ++# CONFIG_MCB is not set ++# CONFIG_MCP320X is not set ++# CONFIG_MCP3422 is not set ++# CONFIG_MCP4131 is not set ++# CONFIG_MCP4531 is not set ++# CONFIG_MCP4725 is not set ++# CONFIG_MCP4922 is not set ++# CONFIG_MCPM is not set ++# CONFIG_MD is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_GPIO is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_DEVICE is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MD_FAULTY is not set ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_ATTACH is not set ++# CONFIG_MEDIA_CAMERA_SUPPORT is not set ++# CONFIG_MEDIA_CEC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set ++# CONFIG_MEDIA_SUPPORT is not set ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_SAS is not set ++CONFIG_MEMBARRIER=y ++# CONFIG_MEMORY is not set ++# CONFIG_MEMORY_FAILURE is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_MEMTEST is not set ++# CONFIG_MEN_A21_WDT is not set ++# CONFIG_MESON_SM is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_MFD_88PM800 is not set ++# CONFIG_MFD_88PM805 is not set ++# CONFIG_MFD_88PM860X is not set ++# CONFIG_MFD_AAT2870_CORE is not set ++# CONFIG_MFD_ACT8945A is not set ++# CONFIG_MFD_ARIZONA_I2C is not set ++# CONFIG_MFD_ARIZONA_SPI is not set ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_MFD_ATMEL_FLEXCOM is not set ++# CONFIG_MFD_ATMEL_HLCDC is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_AXP20X_I2C is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_BD9571MWV is not set ++# CONFIG_MFD_CORE is not set ++# CONFIG_MFD_CPCAP is not set ++# CONFIG_MFD_CROS_EC is not set ++# CONFIG_MFD_CS5535 is not set ++# CONFIG_MFD_DA9052_I2C is not set ++# CONFIG_MFD_DA9052_SPI is not set ++# CONFIG_MFD_DA9055 is not set ++# CONFIG_MFD_DA9062 is not set ++# CONFIG_MFD_DA9063 is not set ++# CONFIG_MFD_DA9150 is not set ++# CONFIG_MFD_DLN2 is not set ++# CONFIG_MFD_EXYNOS_LPASS is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set ++# CONFIG_MFD_JANZ_CMODIO is not set ++# CONFIG_MFD_KEMPLD is not set ++# CONFIG_MFD_LM3533 is not set ++# CONFIG_MFD_LP3943 is not set ++# CONFIG_MFD_LP8788 is not set ++# CONFIG_MFD_MAX14577 is not set ++# CONFIG_MFD_MAX77620 is not set ++# CONFIG_MFD_MAX77686 is not set ++# CONFIG_MFD_MAX77693 is not set ++# CONFIG_MFD_MAX77843 is not set ++# CONFIG_MFD_MAX8907 is not set ++# CONFIG_MFD_MAX8925 is not set ++# CONFIG_MFD_MAX8997 is not set ++# CONFIG_MFD_MAX8998 is not set ++# CONFIG_MFD_MC13XXX is not set ++# CONFIG_MFD_MC13XXX_I2C is not set ++# CONFIG_MFD_MC13XXX_SPI is not set ++# CONFIG_MFD_MENF21BMC is not set ++# CONFIG_MFD_MT6397 is not set ++# CONFIG_MFD_OMAP_USB_HOST is not set ++# CONFIG_MFD_PALMAS is not set ++# CONFIG_MFD_PCF50633 is not set ++# CONFIG_MFD_PM8921_CORE is not set ++# CONFIG_MFD_PM8XXX is not set ++# CONFIG_MFD_RC5T583 is not set ++# CONFIG_MFD_RDC321X is not set ++# CONFIG_MFD_RETU is not set ++# CONFIG_MFD_RK808 is not set ++# CONFIG_MFD_RN5T618 is not set ++# CONFIG_MFD_RT5033 is not set ++# CONFIG_MFD_RTSX_PCI is not set ++# CONFIG_MFD_RTSX_USB is not set ++# CONFIG_MFD_SEC_CORE is not set ++# CONFIG_MFD_SI476X_CORE is not set ++# CONFIG_MFD_SKY81452 is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_SMSC is not set ++# CONFIG_MFD_STMPE is not set ++# CONFIG_MFD_SYSCON is not set ++# CONFIG_MFD_T7L66XB is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TC6387XB is not set ++# CONFIG_MFD_TC6393XB is not set ++# CONFIG_MFD_TIMBERDALE is not set ++# CONFIG_MFD_TI_AM335X_TSCADC is not set ++# CONFIG_MFD_TI_LMU is not set ++# CONFIG_MFD_TI_LP873X is not set ++# CONFIG_MFD_TI_LP87565 is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_TPS65086 is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 is not set ++# CONFIG_MFD_TPS65912_I2C is not set ++# CONFIG_MFD_TPS65912_SPI is not set ++# CONFIG_MFD_TPS68470 is not set ++# CONFIG_MFD_TPS80031 is not set ++# CONFIG_MFD_VIPERBOARD is not set ++# CONFIG_MFD_VX855 is not set ++# CONFIG_MFD_WL1273_CORE is not set ++# CONFIG_MFD_WM831X is not set ++# CONFIG_MFD_WM831X_I2C is not set ++# CONFIG_MFD_WM831X_SPI is not set ++# CONFIG_MFD_WM8350_I2C is not set ++# CONFIG_MFD_WM8400 is not set ++# CONFIG_MFD_WM8994 is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_MICROCHIP_KSZ is not set ++# CONFIG_MICROCHIP_PHY is not set ++# CONFIG_MICROSEMI_PHY is not set ++# CONFIG_MIGRATION is not set ++CONFIG_MII=y ++# CONFIG_MIKROTIK_RB532 is not set ++# CONFIG_MIKROTIK is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_MIPS_ALCHEMY is not set ++# CONFIG_MIPS_CDMM is not set ++# CONFIG_MIPS_COBALT is not set ++# CONFIG_MIPS_FPU_EMULATOR is not set ++# CONFIG_MIPS_GENERIC is not set ++# CONFIG_MIPS_MALTA is not set ++# CONFIG_MIPS_O32_FP64_SUPPORT is not set ++# CONFIG_MIPS_PARAVIRT is not set ++# CONFIG_MIPS_PLATFORM_DEVICES is not set ++# CONFIG_MIPS_SEAD3 is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_MISDN is not set ++# CONFIG_MISDN_AVMFRITZ is not set ++# CONFIG_MISDN_HFCPCI is not set ++# CONFIG_MISDN_HFCUSB is not set ++# CONFIG_MISDN_INFINEON is not set ++# CONFIG_MISDN_NETJET is not set ++# CONFIG_MISDN_SPEEDFAX is not set ++# CONFIG_MISDN_W6692 is not set ++# CONFIG_MKISS is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLX90614 is not set ++# CONFIG_MLXFW is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_MLX_CPLD_PLATFORM is not set ++# CONFIG_MLX_PLATFORM is not set ++# CONFIG_MMA7455_I2C is not set ++# CONFIG_MMA7455_SPI is not set ++# CONFIG_MMA7660 is not set ++# CONFIG_MMA8452 is not set ++# CONFIG_MMA9551 is not set ++# CONFIG_MMA9553 is not set ++# CONFIG_MMC is not set ++# CONFIG_MMC35240 is not set ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_AU1X is not set ++# CONFIG_MMC_BLOCK is not set ++CONFIG_MMC_BLOCK_BOUNCE=y ++CONFIG_MMC_BLOCK_MINORS=8 ++# CONFIG_MMC_CAVIUM_THUNDERX is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_MTK is not set ++# CONFIG_MMC_MVSDIO is not set ++# CONFIG_MMC_S3C is not set ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_SDHCI_ACPI is not set ++# CONFIG_MMC_SDHCI_BCM_KONA is not set ++# CONFIG_MMC_SDHCI_CADENCE is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_SDHCI_MSM is not set ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++# CONFIG_MMC_SDHCI_OF_ESDHC is not set ++# CONFIG_MMC_SDHCI_OF_HLWD is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_S3C is not set ++# CONFIG_MMC_SDHCI_XENON is not set ++# CONFIG_MMC_SDRICOH_CS is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_TEST is not set ++# CONFIG_MMC_TOSHIBA_PCI is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMIOTRACE is not set ++CONFIG_MMU=y ++CONFIG_MODULES=y ++# CONFIG_MODULE_COMPRESS is not set ++# CONFIG_MODULE_FORCE_LOAD is not set ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++# CONFIG_MODULE_SIG is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_MODULE_STRIPPED=y ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MOST is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_INPORT is not set ++# CONFIG_MOUSE_LOGIBM is not set ++# CONFIG_MOUSE_PC110PAD is not set ++# CONFIG_MOUSE_PS2_FOCALTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_MPL115 is not set ++# CONFIG_MPL115_I2C is not set ++# CONFIG_MPL115_SPI is not set ++# CONFIG_MPL3115 is not set ++# CONFIG_MPLS is not set ++# CONFIG_MPU3050_I2C is not set ++# CONFIG_MQ_IOSCHED_DEADLINE is not set ++# CONFIG_MQ_IOSCHED_KYBER is not set ++# CONFIG_MS5611 is not set ++# CONFIG_MS5637 is not set ++# CONFIG_MSDOS_FS is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_MSI_BITMAP_SELFTEST is not set ++# CONFIG_MSI_LAPTOP is not set ++CONFIG_MTD=y ++# CONFIG_MTD_ABSENT is not set ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_MTD_BLOCK2MTD is not set ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_CFI_ADV_OPTIONS is not set ++CONFIG_MTD_CFI_AMDSTD=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++CONFIG_MTD_CFI_INTELEXT=y ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_STAA is not set ++CONFIG_MTD_CFI_UTIL=y ++# CONFIG_MTD_CMDLINE_PARTS is not set ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_GEN_PROBE=y ++# CONFIG_MTD_GPIO_ADDR is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_JEDECPROBE is not set ++# CONFIG_MTD_LATCH_ADDR is not set ++# CONFIG_MTD_LPDDR is not set ++# CONFIG_MTD_LPDDR2_NVM is not set ++# CONFIG_MTD_M25P80 is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MCHP23K256 is not set ++# CONFIG_MTD_MT81xx_NOR is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_MYLOADER_PARTS is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_NAND_AMS_DELTA is not set ++# CONFIG_MTD_NAND_AR934X is not set ++# CONFIG_MTD_NAND_AR934X_HW_ECC is not set ++# CONFIG_MTD_NAND_ATMEL is not set ++# CONFIG_MTD_NAND_AU1550 is not set ++# CONFIG_MTD_NAND_BCH is not set ++# CONFIG_MTD_NAND_BF5XX is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_CM_X270 is not set ++# CONFIG_MTD_NAND_CS553X is not set ++# CONFIG_MTD_NAND_DAVINCI is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_ECC is not set ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_NAND_ECC_SMC is not set ++# CONFIG_MTD_NAND_FSL_ELBC is not set ++# CONFIG_MTD_NAND_FSL_IFC is not set ++# CONFIG_MTD_NAND_FSL_UPM is not set ++# CONFIG_MTD_NAND_FSMC is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_GPMI_NAND is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_JZ4740 is not set ++# CONFIG_MTD_NAND_MPC5121_NFC is not set ++# CONFIG_MTD_NAND_MTK is not set ++# CONFIG_MTD_NAND_MXC is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_NDFC is not set ++# CONFIG_MTD_NAND_NUC900 is not set ++# CONFIG_MTD_NAND_OMAP2 is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_ORION is not set ++# CONFIG_MTD_NAND_PASEMI is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_PXA3xx is not set ++# CONFIG_MTD_NAND_RB4XX is not set ++# CONFIG_MTD_NAND_RB750 is not set ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_S3C2410 is not set ++# CONFIG_MTD_NAND_SHARPSL is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_SOCRATES is not set ++# CONFIG_MTD_NAND_TMIO is not set ++# CONFIG_MTD_NAND_TXX9NDFMC is not set ++CONFIG_MTD_OF_PARTS=y ++# CONFIG_MTD_ONENAND is not set ++# CONFIG_MTD_OOPS is not set ++# CONFIG_MTD_OTP is not set ++# CONFIG_MTD_PARTITIONED_MASTER is not set ++# CONFIG_MTD_PCI is not set ++# CONFIG_MTD_PCMCIA is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_PHYSMAP is not set ++# CONFIG_MTD_PHYSMAP_COMPAT is not set ++CONFIG_MTD_PHYSMAP_OF=y ++# CONFIG_MTD_PHYSMAP_OF_GEMINI is not set ++# CONFIG_MTD_PHYSMAP_OF_VERSATILE is not set ++# CONFIG_MTD_PLATRAM is not set ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_RAM is not set ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++# CONFIG_MTD_REDBOOT_PARTS is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_ROM is not set ++CONFIG_MTD_ROOTFS_ROOT_DEV=y ++# CONFIG_MTD_ROUTERBOOT_PARTS is not set ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_MTD_SPI_NOR is not set ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096 ++CONFIG_MTD_SPLIT=y ++# CONFIG_MTD_SPLIT_BCM_WFI_FW is not set ++# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set ++# CONFIG_MTD_SPLIT_EVA_FW is not set ++# CONFIG_MTD_SPLIT_FIRMWARE is not set ++CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware" ++# CONFIG_MTD_SPLIT_FIT_FW is not set ++# CONFIG_MTD_SPLIT_JIMAGE_FW is not set ++# CONFIG_MTD_SPLIT_LZMA_FW is not set ++# CONFIG_MTD_SPLIT_MINOR_FW is not set ++# CONFIG_MTD_SPLIT_SEAMA_FW is not set ++CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y ++CONFIG_MTD_SPLIT_SUPPORT=y ++# CONFIG_MTD_SPLIT_TPLINK_FW is not set ++# CONFIG_MTD_SPLIT_TRX_FW is not set ++# CONFIG_MTD_SPLIT_UIMAGE_FW is not set ++# CONFIG_MTD_SPLIT_WRGG_FW is not set ++# CONFIG_MTD_SST25L is not set ++# CONFIG_MTD_SWAP is not set ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_UBI is not set ++# CONFIG_MTD_UIMAGE_SPLIT is not set ++# CONFIG_MTD_VIRT_CONCAT is not set ++CONFIG_MULTIUSER=y ++# CONFIG_MUTEX_SPIN_ON_OWNER is not set ++# CONFIG_MV643XX_ETH is not set ++# CONFIG_MVMDIO is not set ++# CONFIG_MVNETA_BM is not set ++# CONFIG_MVSW61XX_PHY is not set ++# CONFIG_MVSWITCH_PHY is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_MWAVE is not set ++# CONFIG_MWL8K is not set ++# CONFIG_MXC4005 is not set ++# CONFIG_MXC6255 is not set ++# CONFIG_MYRI10GE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_NATSEMI is not set ++# CONFIG_NAU7802 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_NE2000 is not set ++# CONFIG_NE2K_PCI is not set ++# CONFIG_NEC_MARKEINS is not set ++CONFIG_NET=y ++# CONFIG_NETCONSOLE is not set ++CONFIG_NETDEVICES=y ++# CONFIG_NETFILTER is not set ++# CONFIG_NETFILTER_ADVANCED is not set ++# CONFIG_NETFILTER_DEBUG is not set ++# CONFIG_NETFILTER_INGRESS is not set ++# CONFIG_NETFILTER_NETLINK is not set ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_NETFILTER_XT_CONNMARK is not set ++# CONFIG_NETFILTER_XT_MARK is not set ++# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set ++# CONFIG_NETFILTER_XT_MATCH_BPF is not set ++# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set ++# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set ++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set ++# CONFIG_NETFILTER_XT_MATCH_CPU is not set ++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set ++# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set ++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set ++# CONFIG_NETFILTER_XT_MATCH_ECN is not set ++# CONFIG_NETFILTER_XT_MATCH_ESP is not set ++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set ++# CONFIG_NETFILTER_XT_MATCH_HELPER is not set ++# CONFIG_NETFILTER_XT_MATCH_HL is not set ++# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set ++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set ++# CONFIG_NETFILTER_XT_MATCH_L2TP is not set ++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set ++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set ++# CONFIG_NETFILTER_XT_MATCH_MAC is not set ++# CONFIG_NETFILTER_XT_MATCH_MARK is not set ++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set ++# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set ++# CONFIG_NETFILTER_XT_MATCH_OSF is not set ++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set ++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set ++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set ++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set ++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set ++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set ++# CONFIG_NETFILTER_XT_MATCH_REALM is not set ++# CONFIG_NETFILTER_XT_MATCH_RECENT is not set ++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set ++# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set ++# CONFIG_NETFILTER_XT_MATCH_STATE is not set ++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set ++# CONFIG_NETFILTER_XT_MATCH_STRING is not set ++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set ++# CONFIG_NETFILTER_XT_MATCH_TIME is not set ++# CONFIG_NETFILTER_XT_MATCH_U32 is not set ++# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set ++# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set ++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set ++# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set ++# CONFIG_NETFILTER_XT_TARGET_CT is not set ++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set ++# CONFIG_NETFILTER_XT_TARGET_HL is not set ++# CONFIG_NETFILTER_XT_TARGET_HMARK is not set ++# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set ++# CONFIG_NETFILTER_XT_TARGET_LED is not set ++# CONFIG_NETFILTER_XT_TARGET_LOG is not set ++# CONFIG_NETFILTER_XT_TARGET_MARK is not set ++# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set ++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set ++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set ++# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set ++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set ++# CONFIG_NETFILTER_XT_TARGET_REDIRECT is not set ++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set ++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set ++# CONFIG_NETFILTER_XT_TARGET_TEE is not set ++# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set ++# CONFIG_NETFILTER_XT_TARGET_TRACE is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NETROM is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_NET_9P is not set ++# CONFIG_NET_ACT_BPF is not set ++# CONFIG_NET_ACT_CSUM is not set ++# CONFIG_NET_ACT_GACT is not set ++# CONFIG_NET_ACT_IFE is not set ++# CONFIG_NET_ACT_IPT is not set ++# CONFIG_NET_ACT_MIRRED is not set ++# CONFIG_NET_ACT_NAT is not set ++# CONFIG_NET_ACT_PEDIT is not set ++# CONFIG_NET_ACT_POLICE is not set ++# CONFIG_NET_ACT_SAMPLE is not set ++# CONFIG_NET_ACT_SIMP is not set ++# CONFIG_NET_ACT_SKBEDIT is not set ++# CONFIG_NET_ACT_SKBMOD is not set ++# CONFIG_NET_ACT_TUNNEL_KEY is not set ++# CONFIG_NET_ACT_VLAN is not set ++CONFIG_NET_CADENCE=y ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_CLS=y ++# CONFIG_NET_CLS_ACT is not set ++# CONFIG_NET_CLS_BASIC is not set ++# CONFIG_NET_CLS_BPF is not set ++# CONFIG_NET_CLS_FLOW is not set ++# CONFIG_NET_CLS_FLOWER is not set ++# CONFIG_NET_CLS_FW is not set ++CONFIG_NET_CLS_IND=y ++# CONFIG_NET_CLS_MATCHALL is not set ++# CONFIG_NET_CLS_ROUTE4 is not set ++# CONFIG_NET_CLS_RSVP is not set ++# CONFIG_NET_CLS_RSVP6 is not set ++# CONFIG_NET_CLS_TCINDEX is not set ++# CONFIG_NET_CLS_U32 is not set ++CONFIG_NET_CORE=y ++# CONFIG_NET_DEVLINK is not set ++# CONFIG_NET_DROP_MONITOR is not set ++# CONFIG_NET_DSA is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_NET_DSA_LOOP is not set ++# CONFIG_NET_DSA_MT7530 is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_MV88E6352 is not set ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_QCA8K is not set ++# CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set ++# CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set ++# CONFIG_NET_DSA_TAG_DSA is not set ++# CONFIG_NET_DSA_TAG_EDSA is not set ++# CONFIG_NET_EMATCH is not set ++# CONFIG_NET_EMATCH_CANID is not set ++# CONFIG_NET_EMATCH_CMP is not set ++# CONFIG_NET_EMATCH_META is not set ++# CONFIG_NET_EMATCH_NBYTE is not set ++CONFIG_NET_EMATCH_STACK=32 ++# CONFIG_NET_EMATCH_TEXT is not set ++# CONFIG_NET_EMATCH_U32 is not set ++# CONFIG_NET_FC is not set ++# CONFIG_NET_FOU is not set ++# CONFIG_NET_FOU_IP_TUNNELS is not set ++# CONFIG_NET_IFE is not set ++# CONFIG_NET_IPGRE is not set ++CONFIG_NET_IPGRE_BROADCAST=y ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPVTI is not set ++# CONFIG_NET_IP_TUNNEL is not set ++# CONFIG_NET_KEY is not set ++# CONFIG_NET_KEY_MIGRATE is not set ++# CONFIG_NET_L3_MASTER_DEV is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_NET_NCSI is not set ++# CONFIG_NET_NSH is not set ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++CONFIG_NET_RX_BUSY_POLL=y ++# CONFIG_NET_SB1000 is not set ++CONFIG_NET_SCHED=y ++# CONFIG_NET_SCH_ATM is not set ++# CONFIG_NET_SCH_CBQ is not set ++# CONFIG_NET_SCH_CHOKE is not set ++# CONFIG_NET_SCH_CODEL is not set ++# CONFIG_NET_SCH_DEFAULT is not set ++# CONFIG_NET_SCH_DRR is not set ++# CONFIG_NET_SCH_DSMARK is not set ++CONFIG_NET_SCH_FIFO=y ++# CONFIG_NET_SCH_FQ is not set ++CONFIG_NET_SCH_FQ_CODEL=y ++# CONFIG_NET_SCH_GRED is not set ++# CONFIG_NET_SCH_HFSC is not set ++# CONFIG_NET_SCH_HHF is not set ++# CONFIG_NET_SCH_HTB is not set ++# CONFIG_NET_SCH_INGRESS is not set ++# CONFIG_NET_SCH_MQPRIO is not set ++# CONFIG_NET_SCH_MULTIQ is not set ++# CONFIG_NET_SCH_NETEM is not set ++# CONFIG_NET_SCH_PIE is not set ++# CONFIG_NET_SCH_PLUG is not set ++# CONFIG_NET_SCH_PRIO is not set ++# CONFIG_NET_SCH_QFQ is not set ++# CONFIG_NET_SCH_RED is not set ++# CONFIG_NET_SCH_SFB is not set ++# CONFIG_NET_SCH_SFQ is not set ++# CONFIG_NET_SCH_TBF is not set ++# CONFIG_NET_SCH_TEQL is not set ++# CONFIG_NET_SCTPPROBE is not set ++# CONFIG_NET_SWITCHDEV is not set ++# CONFIG_NET_TCPPROBE is not set ++# CONFIG_NET_TEAM is not set ++# CONFIG_NET_TULIP is not set ++# CONFIG_NET_UDP_TUNNEL is not set ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_NET_VENDOR_8390=y ++CONFIG_NET_VENDOR_ADAPTEC=y ++CONFIG_NET_VENDOR_AGERE=y ++CONFIG_NET_VENDOR_ALACRITECH=y ++CONFIG_NET_VENDOR_ALTEON=y ++CONFIG_NET_VENDOR_AMAZON=y ++CONFIG_NET_VENDOR_AMD=y ++CONFIG_NET_VENDOR_AQUANTIA=y ++CONFIG_NET_VENDOR_ARC=y ++CONFIG_NET_VENDOR_ATHEROS=y ++CONFIG_NET_VENDOR_AURORA=y ++CONFIG_NET_VENDOR_BROADCOM=y ++CONFIG_NET_VENDOR_BROCADE=y ++CONFIG_NET_VENDOR_CAVIUM=y ++CONFIG_NET_VENDOR_CHELSIO=y ++CONFIG_NET_VENDOR_CIRRUS=y ++CONFIG_NET_VENDOR_CISCO=y ++CONFIG_NET_VENDOR_DEC=y ++CONFIG_NET_VENDOR_DLINK=y ++CONFIG_NET_VENDOR_EMULEX=y ++CONFIG_NET_VENDOR_EXAR=y ++CONFIG_NET_VENDOR_EZCHIP=y ++CONFIG_NET_VENDOR_FARADAY=y ++CONFIG_NET_VENDOR_FREESCALE=y ++CONFIG_NET_VENDOR_FUJITSU=y ++CONFIG_NET_VENDOR_HISILICON=y ++CONFIG_NET_VENDOR_HP=y ++CONFIG_NET_VENDOR_HUAWEI=y ++CONFIG_NET_VENDOR_I825XX=y ++CONFIG_NET_VENDOR_IBM=y ++CONFIG_NET_VENDOR_INTEL=y ++CONFIG_NET_VENDOR_MARVELL=y ++CONFIG_NET_VENDOR_MELLANOX=y ++CONFIG_NET_VENDOR_MICREL=y ++CONFIG_NET_VENDOR_MICROCHIP=y ++CONFIG_NET_VENDOR_MYRI=y ++CONFIG_NET_VENDOR_NATSEMI=y ++CONFIG_NET_VENDOR_NETRONOME=y ++CONFIG_NET_VENDOR_NVIDIA=y ++CONFIG_NET_VENDOR_OKI=y ++CONFIG_NET_VENDOR_QLOGIC=y ++CONFIG_NET_VENDOR_QUALCOMM=y ++CONFIG_NET_VENDOR_RDC=y ++CONFIG_NET_VENDOR_REALTEK=y ++CONFIG_NET_VENDOR_RENESAS=y ++CONFIG_NET_VENDOR_ROCKER=y ++CONFIG_NET_VENDOR_SAMSUNG=y ++CONFIG_NET_VENDOR_SEEQ=y ++CONFIG_NET_VENDOR_SILAN=y ++CONFIG_NET_VENDOR_SIS=y ++CONFIG_NET_VENDOR_SMSC=y ++CONFIG_NET_VENDOR_SOLARFLARE=y ++CONFIG_NET_VENDOR_STMICRO=y ++CONFIG_NET_VENDOR_SUN=y ++CONFIG_NET_VENDOR_SYNOPSYS=y ++CONFIG_NET_VENDOR_TEHUTI=y ++CONFIG_NET_VENDOR_TI=y ++CONFIG_NET_VENDOR_TOSHIBA=y ++CONFIG_NET_VENDOR_VIA=y ++CONFIG_NET_VENDOR_WIZNET=y ++CONFIG_NET_VENDOR_XILINX=y ++CONFIG_NET_VENDOR_XIRCOM=y ++# CONFIG_NET_VRF is not set ++# CONFIG_NET_XGENE is not set ++CONFIG_NEW_LEDS=y ++# CONFIG_NFC is not set ++# CONFIG_NFP is not set ++# CONFIG_NFSD is not set ++# CONFIG_NFSD_V2_ACL is not set ++CONFIG_NFSD_V3=y ++# CONFIG_NFSD_V3_ACL is not set ++# CONFIG_NFSD_V4 is not set ++# CONFIG_NFS_ACL_SUPPORT is not set ++CONFIG_NFS_COMMON=y ++# CONFIG_NFS_FS is not set ++# CONFIG_NFS_FSCACHE is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFS_V2 is not set ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_V4_1 is not set ++# CONFIG_NFTL is not set ++# CONFIG_NFT_BRIDGE_META is not set ++# CONFIG_NFT_BRIDGE_REJECT is not set ++# CONFIG_NFT_DUP_IPV4 is not set ++# CONFIG_NFT_DUP_IPV6 is not set ++# CONFIG_NFT_FIB_IPV4 is not set ++# CONFIG_NFT_FIB_IPV6 is not set ++# CONFIG_NFT_FIB_NETDEV is not set ++# CONFIG_NFT_FLOW_OFFLOAD is not set ++# CONFIG_NFT_OBJREF is not set ++# CONFIG_NFT_RT is not set ++# CONFIG_NFT_SET_BITMAP is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_CONNTRACK_AMANDA is not set ++# CONFIG_NF_CONNTRACK_EVENTS is not set ++# CONFIG_NF_CONNTRACK_FTP is not set ++# CONFIG_NF_CONNTRACK_H323 is not set ++# CONFIG_NF_CONNTRACK_IPV4 is not set ++# CONFIG_NF_CONNTRACK_IPV6 is not set ++# CONFIG_NF_CONNTRACK_IRC is not set ++# CONFIG_NF_CONNTRACK_MARK is not set ++# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set ++# CONFIG_NF_CONNTRACK_PPTP is not set ++CONFIG_NF_CONNTRACK_PROCFS=y ++# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set ++# CONFIG_NF_CONNTRACK_SANE is not set ++# CONFIG_NF_CONNTRACK_SIP is not set ++# CONFIG_NF_CONNTRACK_SNMP is not set ++# CONFIG_NF_CONNTRACK_TFTP is not set ++# CONFIG_NF_CONNTRACK_TIMEOUT is not set ++# CONFIG_NF_CONNTRACK_TIMESTAMP is not set ++# CONFIG_NF_CONNTRACK_ZONES is not set ++# CONFIG_NF_CT_NETLINK is not set ++# CONFIG_NF_CT_NETLINK_TIMEOUT is not set ++# CONFIG_NF_CT_PROTO_DCCP is not set ++# CONFIG_NF_CT_PROTO_GRE is not set ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_FLOW_TABLE is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_LOG_NETDEV is not set ++# CONFIG_NF_NAT is not set ++# CONFIG_NF_NAT_AMANDA is not set ++# CONFIG_NF_NAT_FTP is not set ++# CONFIG_NF_NAT_H323 is not set ++# CONFIG_NF_NAT_IPV6 is not set ++# CONFIG_NF_NAT_IRC is not set ++# CONFIG_NF_NAT_MASQUERADE_IPV4 is not set ++# CONFIG_NF_NAT_MASQUERADE_IPV6 is not set ++# CONFIG_NF_NAT_NEEDED is not set ++# CONFIG_NF_NAT_PPTP is not set ++# CONFIG_NF_NAT_PROTO_GRE is not set ++# CONFIG_NF_NAT_SIP is not set ++# CONFIG_NF_NAT_SNMP_BASIC is not set ++# CONFIG_NF_NAT_TFTP is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_SOCKET_IPV4 is not set ++# CONFIG_NF_SOCKET_IPV6 is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NF_TABLES_NETDEV is not set ++# CONFIG_NI65 is not set ++# CONFIG_NI903X_WDT is not set ++# CONFIG_NIC7018_WDT is not set ++# CONFIG_NILFS2_FS is not set ++# CONFIG_NIU is not set ++CONFIG_NLATTR=y ++# CONFIG_NLMON is not set ++# CONFIG_NLM_XLP_BOARD is not set ++# CONFIG_NLM_XLR_BOARD is not set ++# CONFIG_NLS is not set ++# CONFIG_NLS_ASCII is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++# CONFIG_NLS_CODEPAGE_437 is not set ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++CONFIG_NLS_DEFAULT="iso8859-1" ++# CONFIG_NLS_ISO8859_1 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++# CONFIG_NLS_MAC_CELTIC is not set ++# CONFIG_NLS_MAC_CENTEURO is not set ++# CONFIG_NLS_MAC_CROATIAN is not set ++# CONFIG_NLS_MAC_CYRILLIC is not set ++# CONFIG_NLS_MAC_GAELIC is not set ++# CONFIG_NLS_MAC_GREEK is not set ++# CONFIG_NLS_MAC_ICELAND is not set ++# CONFIG_NLS_MAC_INUIT is not set ++# CONFIG_NLS_MAC_ROMAN is not set ++# CONFIG_NLS_MAC_ROMANIAN is not set ++# CONFIG_NLS_MAC_TURKISH is not set ++# CONFIG_NLS_UTF8 is not set ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_NORTEL_HERMES is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT is not set ++# CONFIG_NOZOMI is not set ++# CONFIG_NO_BOOTMEM is not set ++# CONFIG_NO_HZ is not set ++# CONFIG_NO_HZ_FULL is not set ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NS83820 is not set ++# CONFIG_NTB is not set ++# CONFIG_NTFS_DEBUG is not set ++# CONFIG_NTFS_FS is not set ++# CONFIG_NTFS_RW is not set ++# CONFIG_NTP_PPS is not set ++# CONFIG_NVM is not set ++# CONFIG_NVMEM is not set ++# CONFIG_NVMEM_BCM_OCOTP is not set ++# CONFIG_NVMEM_IMX_OCOTP is not set ++# CONFIG_NVME_FC is not set ++# CONFIG_NVME_TARGET is not set ++# CONFIG_NVRAM is not set ++# CONFIG_NV_TCO is not set ++# CONFIG_NXP_STB220 is not set ++# CONFIG_NXP_STB225 is not set ++# CONFIG_N_GSM is not set ++# CONFIG_OABI_COMPAT is not set ++# CONFIG_OBS600 is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OMAP2_DSS_DEBUG is not set ++# CONFIG_OMAP2_DSS_DEBUGFS is not set ++# CONFIG_OMAP2_DSS_SDI is not set ++# CONFIG_OMAP_OCP2SCP is not set ++# CONFIG_OMAP_USB2 is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_OPROFILE is not set ++# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set ++# CONFIG_OPT3001 is not set ++CONFIG_OPTIMIZE_INLINING=y ++# CONFIG_ORANGEFS_FS is not set ++# CONFIG_ORION_WATCHDOG is not set ++# CONFIG_OSF_PARTITION is not set ++CONFIG_OVERLAY_FS=y ++# CONFIG_OVERLAY_FS_INDEX is not set ++# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set ++# CONFIG_OWL_LOADER is not set ++# CONFIG_P54_COMMON is not set ++# CONFIG_PA12203001 is not set ++CONFIG_PACKET=y ++# CONFIG_PACKET_DIAG is not set ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_PAGE_SIZE_16KB is not set ++# CONFIG_PAGE_SIZE_32KB is not set ++CONFIG_PAGE_SIZE_4KB=y ++# CONFIG_PAGE_SIZE_64KB is not set ++# CONFIG_PAGE_SIZE_8KB is not set ++# CONFIG_PALMAS_GPADC is not set ++# CONFIG_PANASONIC_LAPTOP is not set ++# CONFIG_PANEL is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=1 ++# CONFIG_PANTHERLORD_FF is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_PARPORT is not set ++# CONFIG_PARPORT_1284 is not set ++# CONFIG_PARPORT_AX88796 is not set ++# CONFIG_PARPORT_GSC is not set ++# CONFIG_PARPORT_PC is not set ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_PATA_ALI is not set ++# CONFIG_PATA_AMD is not set ++# CONFIG_PATA_ARASAN_CF is not set ++# CONFIG_PATA_ARTOP is not set ++# CONFIG_PATA_ATIIXP is not set ++# CONFIG_PATA_ATP867X is not set ++# CONFIG_PATA_CMD640_PCI is not set ++# CONFIG_PATA_CMD64X is not set ++# CONFIG_PATA_CS5520 is not set ++# CONFIG_PATA_CS5530 is not set ++# CONFIG_PATA_CS5535 is not set ++# CONFIG_PATA_CS5536 is not set ++# CONFIG_PATA_CYPRESS is not set ++# CONFIG_PATA_EFAR is not set ++# CONFIG_PATA_HPT366 is not set ++# CONFIG_PATA_HPT37X is not set ++# CONFIG_PATA_HPT3X2N is not set ++# CONFIG_PATA_HPT3X3 is not set ++# CONFIG_PATA_IMX is not set ++# CONFIG_PATA_ISAPNP is not set ++# CONFIG_PATA_IT8213 is not set ++# CONFIG_PATA_IT821X is not set ++# CONFIG_PATA_JMICRON is not set ++# CONFIG_PATA_LEGACY is not set ++# CONFIG_PATA_MARVELL is not set ++# CONFIG_PATA_MPIIX is not set ++# CONFIG_PATA_NETCELL is not set ++# CONFIG_PATA_NINJA32 is not set ++# CONFIG_PATA_NS87410 is not set ++# CONFIG_PATA_NS87415 is not set ++# CONFIG_PATA_OCTEON_CF is not set ++# CONFIG_PATA_OF_PLATFORM is not set ++# CONFIG_PATA_OLDPIIX is not set ++# CONFIG_PATA_OPTI is not set ++# CONFIG_PATA_OPTIDMA is not set ++# CONFIG_PATA_PCMCIA is not set ++# CONFIG_PATA_PDC2027X is not set ++# CONFIG_PATA_PDC_OLD is not set ++# CONFIG_PATA_PLATFORM is not set ++# CONFIG_PATA_QDI is not set ++# CONFIG_PATA_RADISYS is not set ++# CONFIG_PATA_RDC is not set ++# CONFIG_PATA_RZ1000 is not set ++# CONFIG_PATA_SC1200 is not set ++# CONFIG_PATA_SCH is not set ++# CONFIG_PATA_SERVERWORKS is not set ++# CONFIG_PATA_SIL680 is not set ++# CONFIG_PATA_SIS is not set ++# CONFIG_PATA_TOSHIBA is not set ++# CONFIG_PATA_TRIFLEX is not set ++# CONFIG_PATA_VIA is not set ++# CONFIG_PATA_WINBOND is not set ++# CONFIG_PATA_WINBOND_VLB is not set ++# CONFIG_PC104 is not set ++# CONFIG_PC300TOO is not set ++# CONFIG_PCCARD is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PCH_GBE is not set ++# CONFIG_PCH_PHUB is not set ++# CONFIG_PCI is not set ++# CONFIG_PCI200SYN is not set ++# CONFIG_PCIEAER_INJECT is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIEPORTBUS is not set ++# CONFIG_PCIE_ALTERA is not set ++# CONFIG_PCIE_ARMADA_8K is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCIE_ECRC is not set ++# CONFIG_PCIE_IPROC is not set ++# CONFIG_PCIE_KIRIN is not set ++# CONFIG_PCIE_PTM is not set ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_PCI_ATMEL is not set ++# CONFIG_PCI_CNB20LE_QUIRK is not set ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_DISABLE_COMMON_QUIRKS is not set ++# CONFIG_PCI_ENDPOINT is not set ++# CONFIG_PCI_ENDPOINT_TEST is not set ++# CONFIG_PCI_FTPCI100 is not set ++# CONFIG_PCI_HERMES is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_LAYERSCAPE is not set ++# CONFIG_PCI_MSI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_PCI_PRI is not set ++CONFIG_PCI_QUIRKS=y ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_SW_SWITCHTEC is not set ++CONFIG_PCI_SYSCALL=y ++# CONFIG_PCI_XGENE is not set ++# CONFIG_PCMCIA is not set ++# CONFIG_PCMCIA_3C574 is not set ++# CONFIG_PCMCIA_3C589 is not set ++# CONFIG_PCMCIA_AHA152X is not set ++# CONFIG_PCMCIA_ATMEL is not set ++# CONFIG_PCMCIA_AXNET is not set ++# CONFIG_PCMCIA_DEBUG is not set ++# CONFIG_PCMCIA_FDOMAIN is not set ++# CONFIG_PCMCIA_FMVJ18X is not set ++# CONFIG_PCMCIA_HERMES is not set ++# CONFIG_PCMCIA_LOAD_CIS is not set ++# CONFIG_PCMCIA_NINJA_SCSI is not set ++# CONFIG_PCMCIA_NMCLAN is not set ++# CONFIG_PCMCIA_PCNET is not set ++# CONFIG_PCMCIA_QLOGIC is not set ++# CONFIG_PCMCIA_RAYCS is not set ++# CONFIG_PCMCIA_SMC91C92 is not set ++# CONFIG_PCMCIA_SPECTRUM is not set ++# CONFIG_PCMCIA_SYM53C500 is not set ++# CONFIG_PCMCIA_WL3501 is not set ++# CONFIG_PCMCIA_XIRC2PS is not set ++# CONFIG_PCMCIA_XIRCOM is not set ++# CONFIG_PCNET32 is not set ++# CONFIG_PCSPKR_PLATFORM is not set ++# CONFIG_PD6729 is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_PDC_ADMA is not set ++# CONFIG_PERCPU_STATS is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_PERF_EVENTS is not set ++# CONFIG_PERF_EVENTS_AMD_POWER is not set ++# CONFIG_PERSISTENT_KEYRINGS is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_PHONET is not set ++# CONFIG_PHYLIB is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++# CONFIG_PHY_CPCAP_USB is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_PHY_QCOM_DWC3 is not set ++# CONFIG_PHY_SAMSUNG_USB2 is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PI433 is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_PID_NS is not set ++CONFIG_PINCONF=y ++# CONFIG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_EXYNOS is not set ++# CONFIG_PINCTRL_EXYNOS5440 is not set ++# CONFIG_PINCTRL_MCP23S08 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_SX150X is not set ++CONFIG_PINMUX=y ++# CONFIG_PKCS7_MESSAGE_PARSER is not set ++# CONFIG_PL320_MBOX is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_PLATFORM_MHU is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_PLIP is not set ++# CONFIG_PLX_HERMES is not set ++# CONFIG_PM is not set ++# CONFIG_PMBUS is not set ++# CONFIG_PMC_MSP is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_PMIC_DA903X is not set ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_POSIX_TIMERS=y ++# CONFIG_POWERCAP is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_POWER_RESET is not set ++# CONFIG_POWER_RESET_BRCMKONA is not set ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_PIIX4_POWEROFF is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_SUPPLY is not set ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PPC4xx_GPIO is not set ++# CONFIG_PPC_16K_PAGES is not set ++# CONFIG_PPC_256K_PAGES is not set ++CONFIG_PPC_4K_PAGES=y ++# CONFIG_PPC_64K_PAGES is not set ++# CONFIG_PPC_DISABLE_WERROR is not set ++# CONFIG_PPC_EMULATED_STATS is not set ++# CONFIG_PPC_EPAPR_HV_BYTECHAN is not set ++# CONFIG_PPP is not set ++# CONFIG_PPPOATM is not set ++# CONFIG_PPPOE is not set ++# CONFIG_PPPOL2TP is not set ++# CONFIG_PPP_ASYNC is not set ++# CONFIG_PPP_BSDCOMP is not set ++# CONFIG_PPP_DEFLATE is not set ++CONFIG_PPP_FILTER=y ++# CONFIG_PPP_MPPE is not set ++CONFIG_PPP_MULTILINK=y ++# CONFIG_PPP_SYNC_TTY is not set ++# CONFIG_PPS is not set ++# CONFIG_PPS_CLIENT_GPIO is not set ++# CONFIG_PPS_CLIENT_KTIMER is not set ++# CONFIG_PPS_CLIENT_LDISC is not set ++# CONFIG_PPS_CLIENT_PARPORT is not set ++# CONFIG_PPS_DEBUG is not set ++# CONFIG_PPTP is not set ++# CONFIG_PREEMPT is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_TRACER is not set ++# CONFIG_PREEMPT_VOLUNTARY is not set ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 ++# CONFIG_PRINTK_TIME is not set ++CONFIG_PRINT_STACK_DEPTH=64 ++# CONFIG_PRISM2_USB is not set ++# CONFIG_PRISM54 is not set ++# CONFIG_PROC_CHILDREN is not set ++CONFIG_PROC_FS=y ++# CONFIG_PROC_KCORE is not set ++# CONFIG_PROC_PAGE_MONITOR is not set ++CONFIG_PROC_STRIPPED=y ++CONFIG_PROC_SYSCTL=y ++# CONFIG_PROFILE_ALL_BRANCHES is not set ++# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set ++# CONFIG_PROFILING is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_PROVE_RCU is not set ++# CONFIG_PROVE_RCU_REPEATEDLY is not set ++# CONFIG_PSAMPLE is not set ++# CONFIG_PSB6970_PHY is not set ++# CONFIG_PSTORE is not set ++# CONFIG_PTP_1588_CLOCK is not set ++# CONFIG_PTP_1588_CLOCK_IXP46X is not set ++# CONFIG_PTP_1588_CLOCK_KVM is not set ++# CONFIG_PTP_1588_CLOCK_PCH is not set ++# CONFIG_PUBLIC_KEY_ALGO_RSA is not set ++# CONFIG_PWM is not set ++# CONFIG_PWM_FSL_FTM is not set ++# CONFIG_PWM_PCA9685 is not set ++CONFIG_PWRSEQ_EMMC=y ++# CONFIG_PWRSEQ_SD8787 is not set ++CONFIG_PWRSEQ_SIMPLE=y ++# CONFIG_QCA7000 is not set ++# CONFIG_QCA7000_SPI is not set ++# CONFIG_QCA7000_UART is not set ++# CONFIG_QCOM_EMAC is not set ++# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set ++# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set ++# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set ++# CONFIG_QCOM_SPMI_IADC is not set ++# CONFIG_QCOM_SPMI_TEMP_ALARM is not set ++# CONFIG_QCOM_SPMI_VADC is not set ++# CONFIG_QED is not set ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_QNX6FS_FS is not set ++# CONFIG_QORIQ_CPUFREQ is not set ++# CONFIG_QORIQ_THERMAL is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_QUEUED_LOCK_STAT is not set ++# CONFIG_QUOTA is not set ++# CONFIG_QUOTACTL is not set ++# CONFIG_QUOTA_DEBUG is not set ++# CONFIG_R3964 is not set ++# CONFIG_R6040 is not set ++# CONFIG_R8169 is not set ++# CONFIG_R8188EU is not set ++# CONFIG_R8712U is not set ++# CONFIG_R8723AU is not set ++# CONFIG_RADIO_ADAPTERS is not set ++# CONFIG_RADIO_AZTECH is not set ++# CONFIG_RADIO_CADET is not set ++# CONFIG_RADIO_GEMTEK is not set ++# CONFIG_RADIO_MAXIRADIO is not set ++# CONFIG_RADIO_RTRACK is not set ++# CONFIG_RADIO_RTRACK2 is not set ++# CONFIG_RADIO_SF16FMI is not set ++# CONFIG_RADIO_SF16FMR2 is not set ++# CONFIG_RADIO_TERRATEC is not set ++# CONFIG_RADIO_TRUST is not set ++# CONFIG_RADIO_TYPHOON is not set ++# CONFIG_RADIO_ZOLTRIX is not set ++# CONFIG_RAID_ATTRS is not set ++# CONFIG_RALINK is not set ++# CONFIG_RANDOM32_SELFTEST is not set ++# CONFIG_RAPIDIO is not set ++# CONFIG_RAS is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_RBTREE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++CONFIG_RCU_EXPERT=y ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FAST_NO_HZ is not set ++CONFIG_RCU_KTHREAD_PRIO=0 ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RC_ATI_REMOTE is not set ++# CONFIG_RC_CORE is not set ++# CONFIG_RC_DECODERS is not set ++# CONFIG_RC_LOOPBACK is not set ++# CONFIG_RC_MAP is not set ++# CONFIG_RDS is not set ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_GZIP is not set ++# CONFIG_RD_LZ4 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_REDWOOD is not set ++# CONFIG_REFCOUNT_FULL is not set ++# CONFIG_REGMAP is not set ++# CONFIG_REGMAP_I2C is not set ++# CONFIG_REGMAP_MMIO is not set ++# CONFIG_REGMAP_SPI is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_PWM is not set ++# CONFIG_REGULATOR_TI_ABB is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS65132 is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_VCTRL is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REISERFS_CHECK is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_REISERFS_FS_POSIX_ACL is not set ++# CONFIG_REISERFS_FS_SECURITY is not set ++# CONFIG_REISERFS_FS_XATTR is not set ++# CONFIG_REISERFS_PROC_INFO is not set ++# CONFIG_RELAY is not set ++# CONFIG_RELOCATABLE is not set ++# CONFIG_REMOTEPROC is not set ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_CONTROLLER is not set ++# CONFIG_RESET_IMX7 is not set ++# CONFIG_RESET_LANTIQ is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_RESET_TEGRA_BPMP is not set ++# CONFIG_RESET_TI_SYSCON is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_RFD_FTL is not set ++CONFIG_RFKILL=y ++# CONFIG_RFKILL_FULL is not set ++# CONFIG_RFKILL_GPIO is not set ++# CONFIG_RFKILL_INPUT is not set ++# CONFIG_RFKILL_LEDS is not set ++# CONFIG_RFKILL_REGULATOR is not set ++# CONFIG_RING_BUFFER_BENCHMARK is not set ++# CONFIG_RING_BUFFER_STARTUP_TEST is not set ++# CONFIG_RMI4_CORE is not set ++# CONFIG_RMNET is not set ++# CONFIG_ROCKCHIP_PHY is not set ++# CONFIG_ROCKER is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_ROSE is not set ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPMSG_QCOM_GLINK_RPM is not set ++# CONFIG_RPR0521 is not set ++# CONFIG_RT2X00 is not set ++# CONFIG_RTC_CLASS is not set ++# CONFIG_RTC_DEBUG is not set ++# CONFIG_RTC_DRV_ABB5ZES3 is not set ++# CONFIG_RTC_DRV_ABX80X is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_AU1XXX is not set ++# CONFIG_RTC_DRV_BQ32K is not set ++# CONFIG_RTC_DRV_BQ4802 is not set ++CONFIG_RTC_DRV_CMOS=y ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1302 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1307_CENTURY is not set ++# CONFIG_RTC_DRV_DS1307_HWMON is not set ++# CONFIG_RTC_DRV_DS1343 is not set ++# CONFIG_RTC_DRV_DS1347 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1390 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_DS1685_FAMILY is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_DS2404 is not set ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++# CONFIG_RTC_DRV_EM3027 is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++# CONFIG_RTC_DRV_FTRTC010 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++# CONFIG_RTC_DRV_HYM8563 is not set ++# CONFIG_RTC_DRV_ISL12022 is not set ++# CONFIG_RTC_DRV_ISL12057 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_M41T93 is not set ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_M48T35 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_MAX6916 is not set ++# CONFIG_RTC_DRV_MCP795 is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MPC5121 is not set ++# CONFIG_RTC_DRV_MSM6242 is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_PCF2123 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_PCF85063 is not set ++# CONFIG_RTC_DRV_PCF8523 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_PS3 is not set ++# CONFIG_RTC_DRV_PT7C4338 is not set ++# CONFIG_RTC_DRV_R7301 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RP5C01 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_RTC7301 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++# CONFIG_RTC_DRV_RV8803 is not set ++# CONFIG_RTC_DRV_RX4581 is not set ++# CONFIG_RTC_DRV_RX6110 is not set ++# CONFIG_RTC_DRV_RX8010 is not set ++# CONFIG_RTC_DRV_RX8025 is not set ++# CONFIG_RTC_DRV_RX8581 is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_SUN6I is not set ++# CONFIG_RTC_DRV_TEST is not set ++# CONFIG_RTC_DRV_V3020 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++CONFIG_RTC_HCTOSYS=y ++CONFIG_RTC_HCTOSYS_DEVICE="rtc0" ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_NVMEM is not set ++CONFIG_RTC_SYSTOHC=y ++CONFIG_RTC_SYSTOHC_DEVICE="rtc0" ++# CONFIG_RTL8180 is not set ++# CONFIG_RTL8187 is not set ++# CONFIG_RTL8192E is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTL8306_PHY is not set ++# CONFIG_RTL8366RB_PHY is not set ++# CONFIG_RTL8366S_PHY is not set ++# CONFIG_RTL8366_SMI is not set ++# CONFIG_RTL8366_SMI_DEBUG_FS is not set ++# CONFIG_RTL8367B_PHY is not set ++# CONFIG_RTL8367_PHY is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_RTL_CARDS is not set ++# CONFIG_RTS5208 is not set ++CONFIG_RT_MUTEXES=y ++# CONFIG_RUNTIME_DEBUG is not set ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_RXKAD=y ++# CONFIG_S2IO is not set ++# CONFIG_SAMPLES is not set ++# CONFIG_SAMSUNG_LAPTOP is not set ++# CONFIG_SATA_ACARD_AHCI is not set ++# CONFIG_SATA_AHCI is not set ++# CONFIG_SATA_AHCI_PLATFORM is not set ++# CONFIG_SATA_DWC is not set ++# CONFIG_SATA_FSL is not set ++# CONFIG_SATA_HIGHBANK is not set ++# CONFIG_SATA_INIC162X is not set ++# CONFIG_SATA_MV is not set ++# CONFIG_SATA_NV is not set ++# CONFIG_SATA_PMP is not set ++# CONFIG_SATA_PROMISE is not set ++# CONFIG_SATA_QSTOR is not set ++# CONFIG_SATA_RCAR is not set ++# CONFIG_SATA_SIL is not set ++# CONFIG_SATA_SIL24 is not set ++# CONFIG_SATA_SIS is not set ++# CONFIG_SATA_SVW is not set ++# CONFIG_SATA_SX4 is not set ++# CONFIG_SATA_ULI is not set ++# CONFIG_SATA_VIA is not set ++# CONFIG_SATA_VITESSE is not set ++# CONFIG_SBC_FITPC2_WATCHDOG is not set ++CONFIG_SBITMAP=y ++# CONFIG_SC92031 is not set ++# CONFIG_SCA3000 is not set ++# CONFIG_SCACHE_DEBUGFS is not set ++# CONFIG_SCC is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SCHED_DEBUG is not set ++CONFIG_SCHED_HRTICK=y ++# CONFIG_SCHED_MC is not set ++CONFIG_SCHED_OMIT_FRAME_POINTER=y ++# CONFIG_SCHED_SMT is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_SCHED_TRACER is not set ++# CONFIG_SCR24X is not set ++# CONFIG_SCSI is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_7000FASST is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_AHA152X is not set ++# CONFIG_SCSI_AHA1542 is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_BFA_FC is not set ++# CONFIG_SCSI_BNX2X_FCOE is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_SCSI_BUSLOGIC is not set ++# CONFIG_SCSI_CHELSIO_FCOE is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_DH is not set ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_SCSI_DTC3280 is not set ++# CONFIG_SCSI_EATA is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_GDTH is not set ++# CONFIG_SCSI_GENERIC_NCR5380 is not set ++# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_IN2000 is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_IPR is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_ISCI is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_LOGGING is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_LPFC is not set ++CONFIG_SCSI_MOD=y ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVSAS_DEBUG is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_NCR53C406A is not set ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_SCSI_PAS16 is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_PMCRAID is not set ++CONFIG_SCSI_PROC_FS=y ++# CONFIG_SCSI_QLA_FC is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLOGIC_FAS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C416 is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_T128 is not set ++# CONFIG_SCSI_U14_34F is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_ULTRASTOR is not set ++# CONFIG_SCSI_VIRTIO is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCx200_ACB is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_SECCOMP is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++CONFIG_SECURITY_DMESG_RESTRICT=y ++CONFIG_SELECT_MEMORY_MODEL=y ++# CONFIG_SENSORS_ABITUGURU is not set ++# CONFIG_SENSORS_ABITUGURU3 is not set ++# CONFIG_SENSORS_ACPI_POWER is not set ++# CONFIG_SENSORS_AD7314 is not set ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADC128D818 is not set ++# CONFIG_SENSORS_ADCXX is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM1275 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADS1015 is not set ++# CONFIG_SENSORS_ADS7828 is not set ++# CONFIG_SENSORS_ADS7871 is not set ++# CONFIG_SENSORS_ADT7310 is not set ++# CONFIG_SENSORS_ADT7410 is not set ++# CONFIG_SENSORS_ADT7411 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++# CONFIG_SENSORS_ADT7470 is not set ++# CONFIG_SENSORS_ADT7475 is not set ++# CONFIG_SENSORS_AMC6821 is not set ++# CONFIG_SENSORS_APDS990X is not set ++# CONFIG_SENSORS_APPLESMC is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_ASC7621 is not set ++# CONFIG_SENSORS_ASPEED is not set ++# CONFIG_SENSORS_ATK0110 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_BH1770 is not set ++# CONFIG_SENSORS_BH1780 is not set ++# CONFIG_SENSORS_CORETEMP is not set ++# CONFIG_SENSORS_DELL_SMM is not set ++# CONFIG_SENSORS_DME1737 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_DS620 is not set ++# CONFIG_SENSORS_EMC1403 is not set ++# CONFIG_SENSORS_EMC2103 is not set ++# CONFIG_SENSORS_EMC6W201 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_F71882FG is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_FAM15H_POWER is not set ++# CONFIG_SENSORS_FSCHMD is not set ++# CONFIG_SENSORS_FTSTEUTATES is not set ++# CONFIG_SENSORS_G760A is not set ++# CONFIG_SENSORS_G762 is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_GPIO_FAN is not set ++# CONFIG_SENSORS_GSC is not set ++# CONFIG_SENSORS_HDAPS is not set ++# CONFIG_SENSORS_HIH6130 is not set ++# CONFIG_SENSORS_HMC5843 is not set ++# CONFIG_SENSORS_HMC5843_I2C is not set ++# CONFIG_SENSORS_HMC5843_SPI is not set ++# CONFIG_SENSORS_HTU21 is not set ++# CONFIG_SENSORS_I5500 is not set ++# CONFIG_SENSORS_I5K_AMB is not set ++# CONFIG_SENSORS_IBM_CFFPS is not set ++# CONFIG_SENSORS_IIO_HWMON is not set ++# CONFIG_SENSORS_INA209 is not set ++# CONFIG_SENSORS_INA2XX is not set ++# CONFIG_SENSORS_INA3221 is not set ++# CONFIG_SENSORS_IR35221 is not set ++# CONFIG_SENSORS_ISL29018 is not set ++# CONFIG_SENSORS_ISL29028 is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_JC42 is not set ++# CONFIG_SENSORS_K10TEMP is not set ++# CONFIG_SENSORS_K8TEMP is not set ++# CONFIG_SENSORS_LINEAGE is not set ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_SENSORS_LIS3_I2C is not set ++# CONFIG_SENSORS_LIS3_SPI is not set ++# CONFIG_SENSORS_LM25066 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM70 is not set ++# CONFIG_SENSORS_LM73 is not set ++# CONFIG_SENSORS_LM75 is not set ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++# CONFIG_SENSORS_LM95234 is not set ++# CONFIG_SENSORS_LM95241 is not set ++# CONFIG_SENSORS_LM95245 is not set ++# CONFIG_SENSORS_LTC2945 is not set ++# CONFIG_SENSORS_LTC2978 is not set ++# CONFIG_SENSORS_LTC2990 is not set ++# CONFIG_SENSORS_LTC3815 is not set ++# CONFIG_SENSORS_LTC4151 is not set ++# CONFIG_SENSORS_LTC4215 is not set ++# CONFIG_SENSORS_LTC4222 is not set ++# CONFIG_SENSORS_LTC4245 is not set ++# CONFIG_SENSORS_LTC4260 is not set ++# CONFIG_SENSORS_LTC4261 is not set ++# CONFIG_SENSORS_MAX1111 is not set ++# CONFIG_SENSORS_MAX16064 is not set ++# CONFIG_SENSORS_MAX16065 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX1668 is not set ++# CONFIG_SENSORS_MAX197 is not set ++# CONFIG_SENSORS_MAX20751 is not set ++# CONFIG_SENSORS_MAX31722 is not set ++# CONFIG_SENSORS_MAX31790 is not set ++# CONFIG_SENSORS_MAX34440 is not set ++# CONFIG_SENSORS_MAX6639 is not set ++# CONFIG_SENSORS_MAX6642 is not set ++# CONFIG_SENSORS_MAX6650 is not set ++# CONFIG_SENSORS_MAX6697 is not set ++# CONFIG_SENSORS_MAX8688 is not set ++# CONFIG_SENSORS_MCP3021 is not set ++# CONFIG_SENSORS_NCT6683 is not set ++# CONFIG_SENSORS_NCT6775 is not set ++# CONFIG_SENSORS_NCT7802 is not set ++# CONFIG_SENSORS_NCT7904 is not set ++# CONFIG_SENSORS_NSA320 is not set ++# CONFIG_SENSORS_NTC_THERMISTOR is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_PMBUS is not set ++# CONFIG_SENSORS_POWR1220 is not set ++# CONFIG_SENSORS_PWM_FAN is not set ++# CONFIG_SENSORS_SCH5627 is not set ++# CONFIG_SENSORS_SCH5636 is not set ++# CONFIG_SENSORS_SCH56XX_COMMON is not set ++# CONFIG_SENSORS_SHT15 is not set ++# CONFIG_SENSORS_SHT21 is not set ++# CONFIG_SENSORS_SHT3x is not set ++# CONFIG_SENSORS_SHTC1 is not set ++# CONFIG_SENSORS_SIS5595 is not set ++# CONFIG_SENSORS_SMM665 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_STTS751 is not set ++# CONFIG_SENSORS_TC654 is not set ++# CONFIG_SENSORS_TC74 is not set ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_TMP102 is not set ++# CONFIG_SENSORS_TMP103 is not set ++# CONFIG_SENSORS_TMP108 is not set ++# CONFIG_SENSORS_TMP401 is not set ++# CONFIG_SENSORS_TMP421 is not set ++# CONFIG_SENSORS_TPS40422 is not set ++# CONFIG_SENSORS_TPS53679 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_SENSORS_TSL2563 is not set ++# CONFIG_SENSORS_UCD9000 is not set ++# CONFIG_SENSORS_UCD9200 is not set ++# CONFIG_SENSORS_VEXPRESS is not set ++# CONFIG_SENSORS_VIA686A is not set ++# CONFIG_SENSORS_VIA_CPUTEMP is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_VT8231 is not set ++# CONFIG_SENSORS_W83627EHF is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83795 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++# CONFIG_SENSORS_XGENE is not set ++# CONFIG_SENSORS_ZL6100 is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_ACCENT is not set ++# CONFIG_SERIAL_8250_ASPEED_VUART is not set ++# CONFIG_SERIAL_8250_BOCA is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_CS is not set ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++CONFIG_SERIAL_8250_DMA=y ++# CONFIG_SERIAL_8250_DW is not set ++# CONFIG_SERIAL_8250_EM is not set ++# CONFIG_SERIAL_8250_EXAR is not set ++# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set ++# CONFIG_SERIAL_8250_EXTENDED is not set ++# CONFIG_SERIAL_8250_FINTEK is not set ++# CONFIG_SERIAL_8250_FOURPORT is not set ++# CONFIG_SERIAL_8250_HUB6 is not set ++# CONFIG_SERIAL_8250_INGENIC is not set ++# CONFIG_SERIAL_8250_LPSS is not set ++# CONFIG_SERIAL_8250_MANY_PORTS is not set ++# CONFIG_SERIAL_8250_MID is not set ++# CONFIG_SERIAL_8250_MOXA is not set ++CONFIG_SERIAL_8250_NR_UARTS=2 ++# CONFIG_SERIAL_8250_PCI is not set ++# CONFIG_SERIAL_8250_RSA is not set ++# CONFIG_SERIAL_8250_RT288X is not set ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_DEV_BUS is not set ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_FSL_LPUART is not set ++# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_SERIAL_OF_PLATFORM is not set ++# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_RP2 is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SH_SCI is not set ++# CONFIG_SERIAL_STM32 is not set ++# CONFIG_SERIAL_ST_ASC is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIO is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_CT82C710 is not set ++# CONFIG_SERIO_GPIO_PS2 is not set ++# CONFIG_SERIO_I8042 is not set ++# CONFIG_SERIO_LIBPS2 is not set ++# CONFIG_SERIO_PARKBD is not set ++# CONFIG_SERIO_PCIPS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_SERPORT is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_SFC is not set ++# CONFIG_SFC_FALCON is not set ++# CONFIG_SFI is not set ++# CONFIG_SGETMASK_SYSCALL is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_SGI_IP22 is not set ++# CONFIG_SGI_IP27 is not set ++# CONFIG_SGI_IP28 is not set ++# CONFIG_SGI_IP32 is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_SGL_ALLOC is not set ++# CONFIG_SG_POOL is not set ++# CONFIG_SG_SPLIT is not set ++CONFIG_SHMEM=y ++# CONFIG_SH_ETH is not set ++# CONFIG_SH_TIMER_CMT is not set ++# CONFIG_SH_TIMER_MTU2 is not set ++# CONFIG_SH_TIMER_TMU is not set ++# CONFIG_SI1145 is not set ++# CONFIG_SI7005 is not set ++# CONFIG_SI7020 is not set ++# CONFIG_SIBYTE_BIGSUR is not set ++# CONFIG_SIBYTE_CARMEL is not set ++# CONFIG_SIBYTE_CRHINE is not set ++# CONFIG_SIBYTE_CRHONE is not set ++# CONFIG_SIBYTE_LITTLESUR is not set ++# CONFIG_SIBYTE_RHONE is not set ++# CONFIG_SIBYTE_SENTOSA is not set ++# CONFIG_SIBYTE_SWARM is not set ++CONFIG_SIGNALFD=y ++# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set ++# CONFIG_SIMPLE_GPIO is not set ++# CONFIG_SIMPLE_PM_BUS is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SIS900 is not set ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++# CONFIG_SKY2_DEBUG is not set ++# CONFIG_SLAB is not set ++CONFIG_SLABINFO=y ++# CONFIG_SLAB_FREELIST_HARDENED is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLAB_MERGE_DEFAULT=y ++# CONFIG_SLHC is not set ++# CONFIG_SLICOSS is not set ++# CONFIG_SLIP is not set ++# CONFIG_SLOB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SLUB_DEBUG is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_MEMCG_SYSFS_ON is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_SMARTJOYPLUS_FF is not set ++# CONFIG_SMC911X is not set ++# CONFIG_SMC9194 is not set ++# CONFIG_SMC91X is not set ++# CONFIG_SMP is not set ++# CONFIG_SMSC911X is not set ++# CONFIG_SMSC9420 is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_SM_FTL is not set ++# CONFIG_SND is not set ++# CONFIG_SND_AC97_POWER_SAVE is not set ++# CONFIG_SND_AD1816A is not set ++# CONFIG_SND_AD1848 is not set ++# CONFIG_SND_AD1889 is not set ++# CONFIG_SND_ADLIB is not set ++# CONFIG_SND_ALI5451 is not set ++# CONFIG_SND_ALOOP is not set ++# CONFIG_SND_ALS100 is not set ++# CONFIG_SND_ALS300 is not set ++# CONFIG_SND_ALS4000 is not set ++# CONFIG_SND_ARM is not set ++# CONFIG_SND_ASIHPI is not set ++# CONFIG_SND_ATIIXP is not set ++# CONFIG_SND_ATIIXP_MODEM is not set ++# CONFIG_SND_ATMEL_AC97C is not set ++# CONFIG_SND_ATMEL_SOC is not set ++# CONFIG_SND_AU8810 is not set ++# CONFIG_SND_AU8820 is not set ++# CONFIG_SND_AU8830 is not set ++# CONFIG_SND_AUDIO_GRAPH_CARD is not set ++# CONFIG_SND_AUDIO_GRAPH_SCU_CARD is not set ++# CONFIG_SND_AW2 is not set ++# CONFIG_SND_AZT2320 is not set ++# CONFIG_SND_AZT3328 is not set ++# CONFIG_SND_BCD2000 is not set ++# CONFIG_SND_BT87X is not set ++# CONFIG_SND_CA0106 is not set ++# CONFIG_SND_CMI8330 is not set ++# CONFIG_SND_CMIPCI is not set ++# CONFIG_SND_CS4231 is not set ++# CONFIG_SND_CS4236 is not set ++# CONFIG_SND_CS4281 is not set ++# CONFIG_SND_CS46XX is not set ++# CONFIG_SND_CS5530 is not set ++# CONFIG_SND_CS5535AUDIO is not set ++# CONFIG_SND_CTXFI is not set ++# CONFIG_SND_DARLA20 is not set ++# CONFIG_SND_DARLA24 is not set ++# CONFIG_SND_DEBUG is not set ++# CONFIG_SND_DESIGNWARE_I2S is not set ++CONFIG_SND_DRIVERS=y ++# CONFIG_SND_DUMMY is not set ++# CONFIG_SND_DYNAMIC_MINORS is not set ++# CONFIG_SND_ECHO3G is not set ++# CONFIG_SND_EDMA_SOC is not set ++# CONFIG_SND_EMU10K1 is not set ++# CONFIG_SND_EMU10K1X is not set ++# CONFIG_SND_EMU10K1_SEQ is not set ++# CONFIG_SND_ENS1370 is not set ++# CONFIG_SND_ENS1371 is not set ++# CONFIG_SND_ES1688 is not set ++# CONFIG_SND_ES18XX is not set ++# CONFIG_SND_ES1938 is not set ++# CONFIG_SND_ES1968 is not set ++# CONFIG_SND_FIREWIRE is not set ++# CONFIG_SND_FM801 is not set ++# CONFIG_SND_GINA20 is not set ++# CONFIG_SND_GINA24 is not set ++# CONFIG_SND_GUSCLASSIC is not set ++# CONFIG_SND_GUSEXTREME is not set ++# CONFIG_SND_GUSMAX is not set ++# CONFIG_SND_HDA_INTEL is not set ++CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 ++CONFIG_SND_HDA_PREALLOC_SIZE=64 ++# CONFIG_SND_HDSP is not set ++# CONFIG_SND_HDSPM is not set ++# CONFIG_SND_HRTIMER is not set ++# CONFIG_SND_HWDEP is not set ++# CONFIG_SND_I2S_HI6210_I2S is not set ++# CONFIG_SND_ICE1712 is not set ++# CONFIG_SND_ICE1724 is not set ++# CONFIG_SND_INDIGO is not set ++# CONFIG_SND_INDIGODJ is not set ++# CONFIG_SND_INDIGODJX is not set ++# CONFIG_SND_INDIGOIO is not set ++# CONFIG_SND_INDIGOIOX is not set ++# CONFIG_SND_INTEL8X0 is not set ++# CONFIG_SND_INTEL8X0M is not set ++# CONFIG_SND_INTERWAVE is not set ++# CONFIG_SND_INTERWAVE_STB is not set ++# CONFIG_SND_ISA is not set ++# CONFIG_SND_KIRKWOOD_SOC is not set ++# CONFIG_SND_KORG1212 is not set ++# CONFIG_SND_LAYLA20 is not set ++# CONFIG_SND_LAYLA24 is not set ++# CONFIG_SND_LOLA is not set ++# CONFIG_SND_LX6464ES is not set ++# CONFIG_SND_MAESTRO3 is not set ++# CONFIG_SND_MIA is not set ++# CONFIG_SND_MIPS is not set ++# CONFIG_SND_MIRO is not set ++# CONFIG_SND_MIXART is not set ++# CONFIG_SND_MIXER_OSS is not set ++# CONFIG_SND_MONA is not set ++# CONFIG_SND_MPC52xx_SOC_EFIKA is not set ++# CONFIG_SND_MPU401 is not set ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_MTS64 is not set ++# CONFIG_SND_MXS_SOC is not set ++# CONFIG_SND_NM256 is not set ++# CONFIG_SND_OPL3SA2 is not set ++# CONFIG_SND_OPL3_LIB_SEQ is not set ++# CONFIG_SND_OPL4_LIB_SEQ is not set ++# CONFIG_SND_OPTI92X_AD1848 is not set ++# CONFIG_SND_OPTI92X_CS4231 is not set ++# CONFIG_SND_OPTI93X is not set ++CONFIG_SND_OSSEMUL=y ++# CONFIG_SND_OXYGEN is not set ++CONFIG_SND_PCI=y ++# CONFIG_SND_PCM is not set ++# CONFIG_SND_PCMCIA is not set ++# CONFIG_SND_PCM_OSS is not set ++CONFIG_SND_PCM_OSS_PLUGINS=y ++# CONFIG_SND_PCM_TIMER is not set ++# CONFIG_SND_PCM_XRUN_DEBUG is not set ++# CONFIG_SND_PCXHR is not set ++# CONFIG_SND_PDAUDIOCF is not set ++# CONFIG_SND_PORTMAN2X4 is not set ++# CONFIG_SND_POWERPC_SOC is not set ++# CONFIG_SND_PPC is not set ++CONFIG_SND_PROC_FS=y ++# CONFIG_SND_RAWMIDI is not set ++# CONFIG_SND_RAWMIDI_SEQ is not set ++# CONFIG_SND_RIPTIDE is not set ++# CONFIG_SND_RME32 is not set ++# CONFIG_SND_RME96 is not set ++# CONFIG_SND_RME9652 is not set ++# CONFIG_SND_RTCTIMER is not set ++# CONFIG_SND_SB16 is not set ++# CONFIG_SND_SB8 is not set ++# CONFIG_SND_SBAWE is not set ++# CONFIG_SND_SBAWE_SEQ is not set ++# CONFIG_SND_SE6X is not set ++# CONFIG_SND_SEQUENCER is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_SIMPLE_CARD is not set ++# CONFIG_SND_SIMPLE_SCU_CARD is not set ++# CONFIG_SND_SIS7019 is not set ++# CONFIG_SND_SOC is not set ++# CONFIG_SND_SOC_AC97_CODEC is not set ++# CONFIG_SND_SOC_ADAU1701 is not set ++# CONFIG_SND_SOC_ADAU1761_I2C is not set ++# CONFIG_SND_SOC_ADAU1761_SPI is not set ++# CONFIG_SND_SOC_ADAU7002 is not set ++# CONFIG_SND_SOC_AK4104 is not set ++# CONFIG_SND_SOC_AK4554 is not set ++# CONFIG_SND_SOC_AK4613 is not set ++# CONFIG_SND_SOC_AK4642 is not set ++# CONFIG_SND_SOC_AK5386 is not set ++# CONFIG_SND_SOC_ALC5623 is not set ++# CONFIG_SND_SOC_AMD_ACP is not set ++# CONFIG_SND_SOC_AU1XAUDIO is not set ++# CONFIG_SND_SOC_AU1XPSC is not set ++# CONFIG_SND_SOC_BT_SCO is not set ++# CONFIG_SND_SOC_CS35L32 is not set ++# CONFIG_SND_SOC_CS35L33 is not set ++# CONFIG_SND_SOC_CS35L34 is not set ++# CONFIG_SND_SOC_CS35L35 is not set ++# CONFIG_SND_SOC_CS4265 is not set ++# CONFIG_SND_SOC_CS4270 is not set ++# CONFIG_SND_SOC_CS4271 is not set ++# CONFIG_SND_SOC_CS4271_I2C is not set ++# CONFIG_SND_SOC_CS4271_SPI is not set ++# CONFIG_SND_SOC_CS42L42 is not set ++# CONFIG_SND_SOC_CS42L51_I2C is not set ++# CONFIG_SND_SOC_CS42L52 is not set ++# CONFIG_SND_SOC_CS42L56 is not set ++# CONFIG_SND_SOC_CS42L73 is not set ++# CONFIG_SND_SOC_CS42XX8_I2C is not set ++# CONFIG_SND_SOC_CS43130 is not set ++# CONFIG_SND_SOC_CS4349 is not set ++# CONFIG_SND_SOC_CS53L30 is not set ++# CONFIG_SND_SOC_DIO2125 is not set ++# CONFIG_SND_SOC_ES7134 is not set ++# CONFIG_SND_SOC_ES8316 is not set ++# CONFIG_SND_SOC_ES8328 is not set ++# CONFIG_SND_SOC_ES8328_I2C is not set ++# CONFIG_SND_SOC_ES8328_SPI is not set ++# CONFIG_SND_SOC_EUKREA_TLV320 is not set ++# CONFIG_SND_SOC_FSL_ASOC_CARD is not set ++# CONFIG_SND_SOC_FSL_ASRC is not set ++# CONFIG_SND_SOC_FSL_ESAI is not set ++# CONFIG_SND_SOC_FSL_SAI is not set ++# CONFIG_SND_SOC_FSL_SPDIF is not set ++# CONFIG_SND_SOC_FSL_SSI is not set ++# CONFIG_SND_SOC_GTM601 is not set ++# CONFIG_SND_SOC_ICS43432 is not set ++# CONFIG_SND_SOC_IMG is not set ++# CONFIG_SND_SOC_IMX_AUDMUX is not set ++# CONFIG_SND_SOC_IMX_ES8328 is not set ++# CONFIG_SND_SOC_IMX_SPDIF is not set ++# CONFIG_SND_SOC_IMX_WM8962 is not set ++# CONFIG_SND_SOC_INNO_RK3036 is not set ++# CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH is not set ++# CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH is not set ++# CONFIG_SND_SOC_INTEL_BXT_RT298_MACH is not set ++# CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH is not set ++# CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH is not set ++# CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH is not set ++# CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH is not set ++# CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH is not set ++# CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH is not set ++# CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH is not set ++# CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH is not set ++# CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH is not set ++# CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH is not set ++# CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH is not set ++# CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH is not set ++# CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH is not set ++# CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH is not set ++# CONFIG_SND_SOC_INTEL_SKL_RT286_MACH is not set ++# CONFIG_SND_SOC_INTEL_SST is not set ++# CONFIG_SND_SOC_MAX98504 is not set ++# CONFIG_SND_SOC_MAX9860 is not set ++# CONFIG_SND_SOC_MAX98927 is not set ++# CONFIG_SND_SOC_MEDIATEK is not set ++# CONFIG_SND_SOC_MPC5200_AC97 is not set ++# CONFIG_SND_SOC_MPC5200_I2S is not set ++# CONFIG_SND_SOC_MSM8916_WCD_ANALOG is not set ++# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set ++# CONFIG_SND_SOC_MT2701 is not set ++# CONFIG_SND_SOC_MT8173 is not set ++# CONFIG_SND_SOC_NAU8540 is not set ++# CONFIG_SND_SOC_NAU8810 is not set ++# CONFIG_SND_SOC_NAU8824 is not set ++# CONFIG_SND_SOC_PCM1681 is not set ++# CONFIG_SND_SOC_PCM1792A is not set ++# CONFIG_SND_SOC_PCM179X_I2C is not set ++# CONFIG_SND_SOC_PCM179X_SPI is not set ++# CONFIG_SND_SOC_PCM3168A_I2C is not set ++# CONFIG_SND_SOC_PCM3168A_SPI is not set ++# CONFIG_SND_SOC_PCM512x_I2C is not set ++# CONFIG_SND_SOC_PCM512x_SPI is not set ++# CONFIG_SND_SOC_QCOM is not set ++# CONFIG_SND_SOC_RT5616 is not set ++# CONFIG_SND_SOC_RT5631 is not set ++# CONFIG_SND_SOC_RT5677_SPI is not set ++# CONFIG_SND_SOC_SGTL5000 is not set ++# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set ++# CONFIG_SND_SOC_SPDIF is not set ++# CONFIG_SND_SOC_SSM2602_I2C is not set ++# CONFIG_SND_SOC_SSM2602_SPI is not set ++# CONFIG_SND_SOC_SSM4567 is not set ++# CONFIG_SND_SOC_STA32X is not set ++# CONFIG_SND_SOC_STA350 is not set ++# CONFIG_SND_SOC_STI_SAS is not set ++# CONFIG_SND_SOC_TAS2552 is not set ++# CONFIG_SND_SOC_TAS5086 is not set ++# CONFIG_SND_SOC_TAS571X is not set ++# CONFIG_SND_SOC_TAS5720 is not set ++# CONFIG_SND_SOC_TFA9879 is not set ++# CONFIG_SND_SOC_TLV320AIC23_I2C is not set ++# CONFIG_SND_SOC_TLV320AIC23_SPI is not set ++# CONFIG_SND_SOC_TLV320AIC31XX is not set ++# CONFIG_SND_SOC_TLV320AIC3X is not set ++# CONFIG_SND_SOC_TPA6130A2 is not set ++# CONFIG_SND_SOC_TS3A227E is not set ++# CONFIG_SND_SOC_WM8510 is not set ++# CONFIG_SND_SOC_WM8523 is not set ++# CONFIG_SND_SOC_WM8524 is not set ++# CONFIG_SND_SOC_WM8580 is not set ++# CONFIG_SND_SOC_WM8711 is not set ++# CONFIG_SND_SOC_WM8728 is not set ++# CONFIG_SND_SOC_WM8731 is not set ++# CONFIG_SND_SOC_WM8737 is not set ++# CONFIG_SND_SOC_WM8741 is not set ++# CONFIG_SND_SOC_WM8750 is not set ++# CONFIG_SND_SOC_WM8753 is not set ++# CONFIG_SND_SOC_WM8770 is not set ++# CONFIG_SND_SOC_WM8776 is not set ++# CONFIG_SND_SOC_WM8804_I2C is not set ++# CONFIG_SND_SOC_WM8804_SPI is not set ++# CONFIG_SND_SOC_WM8903 is not set ++# CONFIG_SND_SOC_WM8960 is not set ++# CONFIG_SND_SOC_WM8962 is not set ++# CONFIG_SND_SOC_WM8974 is not set ++# CONFIG_SND_SOC_WM8978 is not set ++# CONFIG_SND_SOC_WM8985 is not set ++# CONFIG_SND_SOC_XTFPGA_I2S is not set ++# CONFIG_SND_SOC_ZX_AUD96P22 is not set ++# CONFIG_SND_SONICVIBES is not set ++# CONFIG_SND_SPI is not set ++# CONFIG_SND_SSCAPE is not set ++# CONFIG_SND_SUN4I_CODEC is not set ++# CONFIG_SND_SUPPORT_OLD_API is not set ++# CONFIG_SND_TIMER is not set ++# CONFIG_SND_TRIDENT is not set ++CONFIG_SND_USB=y ++# CONFIG_SND_USB_6FIRE is not set ++# CONFIG_SND_USB_AUDIO is not set ++# CONFIG_SND_USB_CAIAQ is not set ++# CONFIG_SND_USB_HIFACE is not set ++# CONFIG_SND_USB_POD is not set ++# CONFIG_SND_USB_PODHD is not set ++# CONFIG_SND_USB_TONEPORT is not set ++# CONFIG_SND_USB_UA101 is not set ++# CONFIG_SND_USB_US122L is not set ++# CONFIG_SND_USB_USX2Y is not set ++# CONFIG_SND_USB_VARIAX is not set ++# CONFIG_SND_VERBOSE_PRINTK is not set ++CONFIG_SND_VERBOSE_PROCFS=y ++# CONFIG_SND_VIA82XX is not set ++# CONFIG_SND_VIA82XX_MODEM is not set ++# CONFIG_SND_VIRTUOSO is not set ++# CONFIG_SND_VX222 is not set ++# CONFIG_SND_VXPOCKET is not set ++# CONFIG_SND_WAVEFRONT is not set ++CONFIG_SND_X86=y ++# CONFIG_SND_YMFPCI is not set ++# CONFIG_SNI_RM is not set ++# CONFIG_SOCK_CGROUP_DATA is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_BRCMSTB is not set ++# CONFIG_SOC_CAMERA is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_SOC_HAS_OMAP2_SDRC is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_SOFTLOCKUP_DETECTOR is not set ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_SONYPI is not set ++# CONFIG_SONY_LAPTOP is not set ++# CONFIG_SOUND is not set ++# CONFIG_SOUND_OSS_CORE is not set ++# CONFIG_SOUND_PRIME is not set ++# CONFIG_SP5100_TCO is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_STATIC is not set ++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set ++# CONFIG_SPARSE_IRQ is not set ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_SPEAKUP is not set ++# CONFIG_SPI is not set ++# CONFIG_SPINLOCK_TEST is not set ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_AU1550 is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_BUTTERFLY is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++# CONFIG_SPI_DEBUG is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_FSL_ESPI is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_GPIO_OLD is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_LM70_LLP is not set ++# CONFIG_SPI_LOOPBACK_TEST is not set ++# CONFIG_SPI_MASTER is not set ++# CONFIG_SPI_MPC52xx is not set ++# CONFIG_SPI_MPC52xx_PSC is not set ++# CONFIG_SPI_OCTEON is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PL022 is not set ++# CONFIG_SPI_PPC4xx is not set ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_S3C64XX is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SLAVE is not set ++# CONFIG_SPI_SPIDEV is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_TLE62X0 is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XWAY is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_SPMI is not set ++CONFIG_SQUASHFS=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y ++# CONFIG_SQUASHFS_DECOMP_SINGLE is not set ++CONFIG_SQUASHFS_EMBEDDED=y ++# CONFIG_SQUASHFS_FILE_CACHE is not set ++CONFIG_SQUASHFS_FILE_DIRECT=y ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# CONFIG_SQUASHFS_LZ4 is not set ++# CONFIG_SQUASHFS_LZO is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_ZLIB is not set ++# CONFIG_SQUASHFS_ZSTD is not set ++# CONFIG_SRAM is not set ++# CONFIG_SRF04 is not set ++# CONFIG_SRF08 is not set ++# CONFIG_SSB is not set ++# CONFIG_SSB_DEBUG is not set ++# CONFIG_SSB_DRIVER_GPIO is not set ++# CONFIG_SSB_HOST_SOC is not set ++# CONFIG_SSB_PCMCIAHOST is not set ++CONFIG_SSB_POSSIBLE=y ++# CONFIG_SSB_SDIOHOST is not set ++# CONFIG_SSB_SILENT is not set ++# CONFIG_SSFDC is not set ++# CONFIG_STACKTRACE is not set ++CONFIG_STACKTRACE_SUPPORT=y ++# CONFIG_STACK_TRACER is not set ++# CONFIG_STACK_VALIDATION is not set ++CONFIG_STAGING=y ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_STAGING_MEDIA is not set ++CONFIG_STANDALONE=y ++# CONFIG_STATIC_KEYS_SELFTEST is not set ++# CONFIG_STATIC_USERMODEHELPER is not set ++CONFIG_STDBINUTILS=y ++# CONFIG_STE10XP is not set ++# CONFIG_STE_MODEM_RPROC is not set ++# CONFIG_STK3310 is not set ++# CONFIG_STK8312 is not set ++# CONFIG_STK8BA50 is not set ++# CONFIG_STM is not set ++# CONFIG_STMMAC_ETH is not set ++# CONFIG_STMMAC_PCI is not set ++# CONFIG_STMMAC_PLATFORM is not set ++# CONFIG_STM_DUMMY is not set ++# CONFIG_STM_SOURCE_CONSOLE is not set ++CONFIG_STP=y ++# CONFIG_STREAM_PARSER is not set ++# CONFIG_STRICT_DEVMEM is not set ++CONFIG_STRICT_KERNEL_RWX=y ++CONFIG_STRICT_MODULE_RWX=y ++# CONFIG_STRING_SELFTEST is not set ++CONFIG_STRIP_ASM_SYMS=y ++# CONFIG_STX104 is not set ++# CONFIG_SUN4I_GPADC is not set ++# CONFIG_SUNDANCE is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_SUNRPC is not set ++# CONFIG_SUNRPC_DEBUG is not set ++# CONFIG_SUNRPC_GSS is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_SURFACE_3_BUTTON is not set ++# CONFIG_SUSPEND is not set ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_SWAP=y ++# CONFIG_SWCONFIG is not set ++# CONFIG_SWCONFIG_B53 is not set ++# CONFIG_SWCONFIG_B53_MDIO_DRIVER is not set ++# CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set ++# CONFIG_SWCONFIG_B53_SPI_DRIVER is not set ++# CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set ++# CONFIG_SWCONFIG_LEDS is not set ++# CONFIG_SW_SYNC is not set ++# CONFIG_SX9500 is not set ++# CONFIG_SXGBE_ETH is not set ++# CONFIG_SYNCLINK_CS is not set ++# CONFIG_SYNC_FILE is not set ++# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set ++CONFIG_SYN_COOKIES=y ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_SYSCTL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_SYSFS=y ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_SYSFS_DEPRECATED_V2 is not set ++# CONFIG_SYSFS_SYSCALL is not set ++# CONFIG_SYSTEMPORT is not set ++# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_SYSTEM_TRUSTED_KEYRING is not set ++CONFIG_SYSTEM_TRUSTED_KEYS="" ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_SYSV_FS is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_T5403 is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_TASK_XACCT is not set ++# CONFIG_TC35815 is not set ++# CONFIG_TCG_ATMEL is not set ++# CONFIG_TCG_CRB is not set ++# CONFIG_TCG_INFINEON is not set ++# CONFIG_TCG_NSC is not set ++# CONFIG_TCG_ST33_I2C is not set ++# CONFIG_TCG_TIS is not set ++# CONFIG_TCG_TIS_I2C_ATMEL is not set ++# CONFIG_TCG_TIS_I2C_INFINEON is not set ++# CONFIG_TCG_TIS_I2C_NUVOTON is not set ++# CONFIG_TCG_TIS_SPI is not set ++# CONFIG_TCG_TIS_ST33ZP24_I2C is not set ++# CONFIG_TCG_TIS_ST33ZP24_SPI is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_TCG_VTPM_PROXY is not set ++# CONFIG_TCG_XEN is not set ++# CONFIG_TCIC is not set ++CONFIG_TCP_CONG_ADVANCED=y ++# CONFIG_TCP_CONG_BBR is not set ++# CONFIG_TCP_CONG_BIC is not set ++# CONFIG_TCP_CONG_CDG is not set ++CONFIG_TCP_CONG_CUBIC=y ++# CONFIG_TCP_CONG_DCTCP is not set ++# CONFIG_TCP_CONG_HSTCP is not set ++# CONFIG_TCP_CONG_HTCP is not set ++# CONFIG_TCP_CONG_HYBLA is not set ++# CONFIG_TCP_CONG_ILLINOIS is not set ++# CONFIG_TCP_CONG_LP is not set ++# CONFIG_TCP_CONG_NV is not set ++# CONFIG_TCP_CONG_SCALABLE is not set ++# CONFIG_TCP_CONG_VEGAS is not set ++# CONFIG_TCP_CONG_VENO is not set ++# CONFIG_TCP_CONG_WESTWOOD is not set ++# CONFIG_TCP_CONG_YEAH is not set ++# CONFIG_TCP_MD5SIG is not set ++# CONFIG_TCS3414 is not set ++# CONFIG_TCS3472 is not set ++# CONFIG_TEE is not set ++# CONFIG_TEGRA_AHB is not set ++# CONFIG_TEGRA_HOST1X is not set ++# CONFIG_TEHUTI is not set ++# CONFIG_TERANETICS_PHY is not set ++# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set ++# CONFIG_TEST_BITMAP is not set ++# CONFIG_TEST_BPF is not set ++# CONFIG_TEST_FIRMWARE is not set ++# CONFIG_TEST_HASH is not set ++# CONFIG_TEST_HEXDUMP is not set ++# CONFIG_TEST_KASAN is not set ++# CONFIG_TEST_KMOD is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_TEST_LKM is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_TEST_PRINTF is not set ++# CONFIG_TEST_RHASHTABLE is not set ++# CONFIG_TEST_SORT is not set ++# CONFIG_TEST_STATIC_KEYS is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_SYSCTL is not set ++# CONFIG_TEST_UDELAY is not set ++# CONFIG_TEST_USER_COPY is not set ++# CONFIG_TEST_UUID is not set ++CONFIG_TEXTSEARCH=y ++# CONFIG_TEXTSEARCH_BM is not set ++# CONFIG_TEXTSEARCH_FSM is not set ++# CONFIG_TEXTSEARCH_KMP is not set ++# CONFIG_THERMAL is not set ++# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set ++# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set ++# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set ++# CONFIG_THERMAL_EMULATION is not set ++# CONFIG_THERMAL_GOV_BANG_BANG is not set ++# CONFIG_THERMAL_GOV_FAIR_SHARE is not set ++# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set ++# CONFIG_THERMAL_GOV_USER_SPACE is not set ++# CONFIG_THERMAL_HWMON is not set ++# CONFIG_THERMAL_WRITABLE_TRIPS is not set ++# CONFIG_THINKPAD_ACPI is not set ++CONFIG_THIN_ARCHIVES=y ++# CONFIG_THRUSTMASTER_FF is not set ++# CONFIG_THUNDERBOLT is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_TICK_CPU_ACCOUNTING is not set ++CONFIG_TICK_ONESHOT=y ++# CONFIG_TIFM_CORE is not set ++# CONFIG_TIGON3 is not set ++# CONFIG_TIMB_DMA is not set ++CONFIG_TIMERFD=y ++# CONFIG_TIMER_STATS is not set ++CONFIG_TINY_RCU=y ++# CONFIG_TIPC is not set ++# CONFIG_TI_ADC081C is not set ++# CONFIG_TI_ADC0832 is not set ++# CONFIG_TI_ADC084S021 is not set ++# CONFIG_TI_ADC108S102 is not set ++# CONFIG_TI_ADC12138 is not set ++# CONFIG_TI_ADC128S052 is not set ++# CONFIG_TI_ADC161S626 is not set ++# CONFIG_TI_ADS1015 is not set ++# CONFIG_TI_ADS7950 is not set ++# CONFIG_TI_ADS8688 is not set ++# CONFIG_TI_AM335X_ADC is not set ++# CONFIG_TI_CPSW is not set ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TI_CPTS is not set ++# CONFIG_TI_DAC7512 is not set ++# CONFIG_TI_DAVINCI_CPDMA is not set ++# CONFIG_TI_DAVINCI_MDIO is not set ++# CONFIG_TI_ST is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_TI_TLC4541 is not set ++# CONFIG_TLAN is not set ++# CONFIG_TLS is not set ++# CONFIG_TMD_HERMES is not set ++# CONFIG_TMP006 is not set ++# CONFIG_TMP007 is not set ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_POSIX_ACL is not set ++CONFIG_TMPFS_XATTR=y ++# CONFIG_TOPSTAR_LAPTOP is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_TOSHIBA_HAPS is not set ++# CONFIG_TOUCHSCREEN_88PM860X is not set ++# CONFIG_TOUCHSCREEN_AD7877 is not set ++# CONFIG_TOUCHSCREEN_AD7879 is not set ++# CONFIG_TOUCHSCREEN_AD7879_I2C is not set ++# CONFIG_TOUCHSCREEN_AD7879_SPI is not set ++# CONFIG_TOUCHSCREEN_ADS7846 is not set ++# CONFIG_TOUCHSCREEN_AR1021_I2C is not set ++# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set ++# CONFIG_TOUCHSCREEN_ATMEL_MXT_T37 is not set ++# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set ++# CONFIG_TOUCHSCREEN_BU21013 is not set ++# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set ++# CONFIG_TOUCHSCREEN_COLIBRI_VF50 is not set ++# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set ++# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set ++# CONFIG_TOUCHSCREEN_CYTTSP4_I2C is not set ++# CONFIG_TOUCHSCREEN_CYTTSP4_SPI is not set ++# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set ++# CONFIG_TOUCHSCREEN_CYTTSP_I2C is not set ++# CONFIG_TOUCHSCREEN_CYTTSP_SPI is not set ++# CONFIG_TOUCHSCREEN_DA9034 is not set ++# CONFIG_TOUCHSCREEN_DA9052 is not set ++# CONFIG_TOUCHSCREEN_DYNAPRO is not set ++# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set ++# CONFIG_TOUCHSCREEN_EETI is not set ++# CONFIG_TOUCHSCREEN_EGALAX is not set ++# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set ++# CONFIG_TOUCHSCREEN_EKTF2127 is not set ++# CONFIG_TOUCHSCREEN_ELAN is not set ++# CONFIG_TOUCHSCREEN_ELO is not set ++# CONFIG_TOUCHSCREEN_FUJITSU is not set ++# CONFIG_TOUCHSCREEN_GOODIX is not set ++# CONFIG_TOUCHSCREEN_GUNZE is not set ++# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set ++# CONFIG_TOUCHSCREEN_HP600 is not set ++# CONFIG_TOUCHSCREEN_HP7XX is not set ++# CONFIG_TOUCHSCREEN_HTCPEN is not set ++# CONFIG_TOUCHSCREEN_ILI210X is not set ++# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set ++# CONFIG_TOUCHSCREEN_INEXIO is not set ++# CONFIG_TOUCHSCREEN_IPAQ_MICRO is not set ++# CONFIG_TOUCHSCREEN_IPROC is not set ++# CONFIG_TOUCHSCREEN_LPC32XX is not set ++# CONFIG_TOUCHSCREEN_MAX11801 is not set ++# CONFIG_TOUCHSCREEN_MC13783 is not set ++# CONFIG_TOUCHSCREEN_MCS5000 is not set ++# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set ++# CONFIG_TOUCHSCREEN_MIGOR is not set ++# CONFIG_TOUCHSCREEN_MK712 is not set ++# CONFIG_TOUCHSCREEN_MMS114 is not set ++# CONFIG_TOUCHSCREEN_MTOUCH is not set ++# CONFIG_TOUCHSCREEN_MX25 is not set ++# CONFIG_TOUCHSCREEN_MXS_LRADC is not set ++# CONFIG_TOUCHSCREEN_PCAP is not set ++# CONFIG_TOUCHSCREEN_PENMOUNT is not set ++# CONFIG_TOUCHSCREEN_PIXCIR is not set ++# CONFIG_TOUCHSCREEN_PROPERTIES is not set ++# CONFIG_TOUCHSCREEN_RM_TS is not set ++# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set ++# CONFIG_TOUCHSCREEN_S3C2410 is not set ++# CONFIG_TOUCHSCREEN_SILEAD is not set ++# CONFIG_TOUCHSCREEN_SIS_I2C is not set ++# CONFIG_TOUCHSCREEN_ST1232 is not set ++# CONFIG_TOUCHSCREEN_STMFTS is not set ++# CONFIG_TOUCHSCREEN_STMPE is not set ++# CONFIG_TOUCHSCREEN_SUN4I is not set ++# CONFIG_TOUCHSCREEN_SUR40 is not set ++# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set ++# CONFIG_TOUCHSCREEN_SX8654 is not set ++# CONFIG_TOUCHSCREEN_TI_AM335X_TSC is not set ++# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set ++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set ++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set ++# CONFIG_TOUCHSCREEN_TPS6507X is not set ++# CONFIG_TOUCHSCREEN_TS4800 is not set ++# CONFIG_TOUCHSCREEN_TSC2004 is not set ++# CONFIG_TOUCHSCREEN_TSC2005 is not set ++# CONFIG_TOUCHSCREEN_TSC2007 is not set ++# CONFIG_TOUCHSCREEN_TSC2007_IIO is not set ++# CONFIG_TOUCHSCREEN_TSC200X_CORE is not set ++# CONFIG_TOUCHSCREEN_TSC_SERIO is not set ++# CONFIG_TOUCHSCREEN_UCB1400 is not set ++# CONFIG_TOUCHSCREEN_USB_3M is not set ++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set ++# CONFIG_TOUCHSCREEN_USB_DMC_TSC10 is not set ++# CONFIG_TOUCHSCREEN_USB_E2I is not set ++# CONFIG_TOUCHSCREEN_USB_EASYTOUCH is not set ++# CONFIG_TOUCHSCREEN_USB_EGALAX is not set ++# CONFIG_TOUCHSCREEN_USB_ELO is not set ++# CONFIG_TOUCHSCREEN_USB_ETT_TC45USB is not set ++# CONFIG_TOUCHSCREEN_USB_ETURBO is not set ++# CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH is not set ++# CONFIG_TOUCHSCREEN_USB_GOTOP is not set ++# CONFIG_TOUCHSCREEN_USB_GUNZE is not set ++# CONFIG_TOUCHSCREEN_USB_IDEALTEK is not set ++# CONFIG_TOUCHSCREEN_USB_IRTOUCH is not set ++# CONFIG_TOUCHSCREEN_USB_ITM is not set ++# CONFIG_TOUCHSCREEN_USB_JASTEC is not set ++# CONFIG_TOUCHSCREEN_USB_NEXIO is not set ++# CONFIG_TOUCHSCREEN_USB_PANJIT is not set ++# CONFIG_TOUCHSCREEN_USB_ZYTRONIC is not set ++# CONFIG_TOUCHSCREEN_W90X900 is not set ++# CONFIG_TOUCHSCREEN_WACOM_I2C is not set ++# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set ++# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set ++# CONFIG_TOUCHSCREEN_WM831X is not set ++# CONFIG_TOUCHSCREEN_WM9705 is not set ++# CONFIG_TOUCHSCREEN_WM9712 is not set ++# CONFIG_TOUCHSCREEN_WM9713 is not set ++# CONFIG_TOUCHSCREEN_WM97XX is not set ++# CONFIG_TOUCHSCREEN_WM97XX_ATMEL is not set ++# CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set ++# CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE is not set ++# CONFIG_TOUCHSCREEN_ZET6223 is not set ++# CONFIG_TOUCHSCREEN_ZFORCE is not set ++# CONFIG_TPL0102 is not set ++# CONFIG_TPS6105X is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_TPS6507X is not set ++# CONFIG_TRACEPOINT_BENCHMARK is not set ++# CONFIG_TRACER_SNAPSHOT is not set ++# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set ++# CONFIG_TRACE_BRANCH_PROFILING is not set ++# CONFIG_TRACE_EVAL_MAP_FILE is not set ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++# CONFIG_TRACE_SINK is not set ++# CONFIG_TRACING_EVENTS_GPIO is not set ++CONFIG_TRACING_SUPPORT=y ++CONFIG_TRAD_SIGNALS=y ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_TREE_RCU is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_TRIM_UNUSED_KSYMS is not set ++# CONFIG_TRUSTED_KEYS is not set ++# CONFIG_TSL2583 is not set ++# CONFIG_TSL2x7x is not set ++# CONFIG_TSL4531 is not set ++# CONFIG_TSYS01 is not set ++# CONFIG_TSYS02D is not set ++# CONFIG_TTPCI_EEPROM is not set ++CONFIG_TTY=y ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_TUN is not set ++# CONFIG_TUN_VNET_CROSS_LE is not set ++# CONFIG_TWL4030_CORE is not set ++# CONFIG_TWL4030_MADC is not set ++# CONFIG_TWL6030_GPADC is not set ++# CONFIG_TWL6040_CORE is not set ++# CONFIG_TYPEC_TCPM is not set ++# CONFIG_TYPEC_UCSI is not set ++# CONFIG_TYPHOON is not set ++# CONFIG_UACCESS_WITH_MEMCPY is not set ++# CONFIG_UBIFS_ATIME_SUPPORT is not set ++# CONFIG_UBIFS_FS_ENCRYPTION is not set ++# CONFIG_UBIFS_FS_SECURITY is not set ++# CONFIG_UBSAN is not set ++# CONFIG_UCB1400_CORE is not set ++# CONFIG_UCSI is not set ++# CONFIG_UDF_FS is not set ++CONFIG_UDF_NLS=y ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_UFS_FS is not set ++# CONFIG_UHID is not set ++CONFIG_UID16=y ++# CONFIG_UIO is not set ++# CONFIG_ULTRA is not set ++# CONFIG_ULTRIX_PARTITION is not set ++CONFIG_UNIX=y ++CONFIG_UNIX98_PTYS=y ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_UNIX_DIAG is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_UPROBES is not set ++# CONFIG_UPROBE_EVENTS is not set ++# CONFIG_US5182D is not set ++# CONFIG_USB is not set ++# CONFIG_USBIP_CORE is not set ++CONFIG_USBIP_VHCI_HC_PORTS=8 ++CONFIG_USBIP_VHCI_NR_HCS=1 ++# CONFIG_USBIP_VUDC is not set ++# CONFIG_USBPCWATCHDOG is not set ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_ADUTUX is not set ++CONFIG_USB_ALI_M5632=y ++# CONFIG_USB_AMD5536UDC is not set ++CONFIG_USB_AN2720=y ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARMLINUX=y ++# CONFIG_USB_ATM is not set ++# CONFIG_USB_BDC_UDC is not set ++CONFIG_USB_BELKIN=y ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_CHAOSKEY is not set ++# CONFIG_USB_CHIPIDEA is not set ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_CXACRU is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DSBR is not set ++# CONFIG_USB_DUMMY_HCD is not set ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_DWC2_DEBUG is not set ++# CONFIG_USB_DWC2_DUAL_ROLE is not set ++# CONFIG_USB_DWC2_HOST is not set ++# CONFIG_USB_DWC2_PERIPHERAL is not set ++# CONFIG_USB_DWC3 is not set ++# CONFIG_USB_DWC3_EXYNOS is not set ++# CONFIG_USB_DWC3_KEYSTONE is not set ++# CONFIG_USB_DWC3_OF_SIMPLE is not set ++# CONFIG_USB_DWC3_PCI is not set ++# CONFIG_USB_DWC3_QCOM is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_EHCI_ATH79 is not set ++# CONFIG_USB_EHCI_HCD is not set ++# CONFIG_USB_EHCI_HCD_AT91 is not set ++# CONFIG_USB_EHCI_HCD_OMAP is not set ++# CONFIG_USB_EHCI_HCD_PPC_OF is not set ++# CONFIG_USB_EHCI_MSM is not set ++# CONFIG_USB_EHCI_MV is not set ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++# CONFIG_USB_EHSET_TEST_FIXTURE is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EPSON2888 is not set ++# CONFIG_USB_EZUSB_FX2 is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_FSL_USB2 is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_FUNCTIONFS is not set ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_GADGET is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_GSPCA is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_G_NOKIA is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_WEBCAM is not set ++# CONFIG_USB_HCD_TEST_MODE is not set ++# CONFIG_USB_HID is not set ++# CONFIG_USB_HIDDEV is not set ++# CONFIG_USB_HSIC_USB3503 is not set ++# CONFIG_USB_HSIC_USB4604 is not set ++# CONFIG_USB_HSO is not set ++# CONFIG_USB_HUB_USB251XB is not set ++# CONFIG_USB_HWA_HCD is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_IMX21_HCD is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_ISP1760 is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_KBD is not set ++# CONFIG_USB_KC2190 is not set ++# CONFIG_USB_LAN78XX is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set ++# CONFIG_USB_LED_TRIG is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LINK_LAYER_TEST is not set ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_MASS_STORAGE is not set ++# CONFIG_USB_MAX3421_HCD is not set ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USB_MIDI_GADGET is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_MOUSE is not set ++# CONFIG_USB_MSM_OTG is not set ++# CONFIG_USB_MTU3 is not set ++# CONFIG_USB_MUSB_HDRC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MXS_PHY is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_NET_AX88179_178A is not set ++# CONFIG_USB_NET_AX8817X is not set ++# CONFIG_USB_NET_CDCETHER is not set ++# CONFIG_USB_NET_CDC_EEM is not set ++# CONFIG_USB_NET_CDC_MBIM is not set ++# CONFIG_USB_NET_CDC_NCM is not set ++# CONFIG_USB_NET_CDC_SUBSET is not set ++# CONFIG_USB_NET_CH9200 is not set ++# CONFIG_USB_NET_CX82310_ETH is not set ++# CONFIG_USB_NET_DM9601 is not set ++# CONFIG_USB_NET_DRIVERS is not set ++# CONFIG_USB_NET_GL620A is not set ++# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set ++# CONFIG_USB_NET_INT51X1 is not set ++# CONFIG_USB_NET_KALMIA is not set ++# CONFIG_USB_NET_MCS7830 is not set ++# CONFIG_USB_NET_NET1080 is not set ++# CONFIG_USB_NET_PLUSB is not set ++# CONFIG_USB_NET_QMI_WWAN is not set ++# CONFIG_USB_NET_RNDIS_HOST is not set ++# CONFIG_USB_NET_RNDIS_WLAN is not set ++# CONFIG_USB_NET_SMSC75XX is not set ++# CONFIG_USB_NET_SMSC95XX is not set ++# CONFIG_USB_NET_SR9700 is not set ++# CONFIG_USB_NET_SR9800 is not set ++# CONFIG_USB_NET_ZAURUS is not set ++# CONFIG_USB_OHCI_HCD is not set ++# CONFIG_USB_OHCI_HCD_PCI is not set ++# CONFIG_USB_OHCI_HCD_PPC_OF is not set ++# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set ++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set ++# CONFIG_USB_OHCI_HCD_SSB is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_PCI is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_PWC_INPUT_EVDEV is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_RCAR_PHY is not set ++# CONFIG_USB_RENESAS_USBHS is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_RTL8152 is not set ++# CONFIG_USB_S2255 is not set ++# CONFIG_USB_SERIAL is not set ++# CONFIG_USB_SERIAL_AIRCABLE is not set ++# CONFIG_USB_SERIAL_ARK3116 is not set ++# CONFIG_USB_SERIAL_BELKIN is not set ++# CONFIG_USB_SERIAL_CH341 is not set ++# CONFIG_USB_SERIAL_CP210X is not set ++# CONFIG_USB_SERIAL_CYBERJACK is not set ++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set ++# CONFIG_USB_SERIAL_DEBUG is not set ++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set ++# CONFIG_USB_SERIAL_EDGEPORT is not set ++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set ++# CONFIG_USB_SERIAL_EMPEG is not set ++# CONFIG_USB_SERIAL_F81232 is not set ++# CONFIG_USB_SERIAL_F8153X is not set ++# CONFIG_USB_SERIAL_FTDI_SIO is not set ++# CONFIG_USB_SERIAL_GARMIN is not set ++CONFIG_USB_SERIAL_GENERIC=y ++# CONFIG_USB_SERIAL_IPAQ is not set ++# CONFIG_USB_SERIAL_IPW is not set ++# CONFIG_USB_SERIAL_IR is not set ++# CONFIG_USB_SERIAL_IUU is not set ++# CONFIG_USB_SERIAL_KEYSPAN is not set ++CONFIG_USB_SERIAL_KEYSPAN_MPR=y ++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set ++CONFIG_USB_SERIAL_KEYSPAN_USA18X=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19W=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28X=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y ++CONFIG_USB_SERIAL_KEYSPAN_USA49W=y ++CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y ++# CONFIG_USB_SERIAL_KLSI is not set ++# CONFIG_USB_SERIAL_KOBIL_SCT is not set ++# CONFIG_USB_SERIAL_MCT_U232 is not set ++# CONFIG_USB_SERIAL_METRO is not set ++# CONFIG_USB_SERIAL_MOS7715_PARPORT is not set ++# CONFIG_USB_SERIAL_MOS7720 is not set ++# CONFIG_USB_SERIAL_MOS7840 is not set ++# CONFIG_USB_SERIAL_MXUPORT is not set ++# CONFIG_USB_SERIAL_NAVMAN is not set ++# CONFIG_USB_SERIAL_OMNINET is not set ++# CONFIG_USB_SERIAL_OPTICON is not set ++# CONFIG_USB_SERIAL_OPTION is not set ++# CONFIG_USB_SERIAL_OTI6858 is not set ++# CONFIG_USB_SERIAL_PL2303 is not set ++# CONFIG_USB_SERIAL_QCAUX is not set ++# CONFIG_USB_SERIAL_QT2 is not set ++# CONFIG_USB_SERIAL_QUALCOMM is not set ++# CONFIG_USB_SERIAL_SAFE is not set ++CONFIG_USB_SERIAL_SAFE_PADDED=y ++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set ++# CONFIG_USB_SERIAL_SIMPLE is not set ++# CONFIG_USB_SERIAL_SPCP8X5 is not set ++# CONFIG_USB_SERIAL_SSU100 is not set ++# CONFIG_USB_SERIAL_SYMBOL is not set ++# CONFIG_USB_SERIAL_TI is not set ++# CONFIG_USB_SERIAL_UPD78F0730 is not set ++# CONFIG_USB_SERIAL_VISOR is not set ++# CONFIG_USB_SERIAL_WHITEHEAT is not set ++# CONFIG_USB_SERIAL_WISHBONE is not set ++# CONFIG_USB_SERIAL_XIRCOM is not set ++# CONFIG_USB_SERIAL_XSENS_MT is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_SIERRA_NET is not set ++# CONFIG_USB_SISUSBVGA is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_SNP_UDC_PLAT is not set ++# CONFIG_USB_SPEEDTOUCH is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_STORAGE is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_SUPPORT is not set ++# CONFIG_USB_SWITCH_FSA9480 is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_TMC is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_UAS is not set ++# CONFIG_USB_UEAGLEATM is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_USB_ULPI_BUS is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_USB_USS720 is not set ++# CONFIG_USB_VIDEO_CLASS is not set ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++# CONFIG_USB_VL600 is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_WHCI_HCD is not set ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++# CONFIG_USB_XHCI_HCD is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_TEGRA is not set ++# CONFIG_USB_XUSBATM is not set ++# CONFIG_USB_YUREX is not set ++# CONFIG_USB_ZD1201 is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USELIB is not set ++# CONFIG_USERFAULTFD is not set ++# CONFIG_USE_OF is not set ++# CONFIG_UTS_NS is not set ++# CONFIG_UWB is not set ++# CONFIG_U_SERIAL_CONSOLE is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++# CONFIG_VCNL4000 is not set ++# CONFIG_VDSO is not set ++# CONFIG_VEML6070 is not set ++# CONFIG_VETH is not set ++# CONFIG_VEXPRESS_CONFIG is not set ++# CONFIG_VF610_ADC is not set ++# CONFIG_VF610_DAC is not set ++# CONFIG_VFAT_FS is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VGA_ARB is not set ++# CONFIG_VGA_SWITCHEROO is not set ++# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set ++# CONFIG_VHOST_NET is not set ++# CONFIG_VHOST_VSOCK is not set ++# CONFIG_VIA_RHINE is not set ++# CONFIG_VIA_VELOCITY is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7180 is not set ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT848 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_CAFE_CCIC is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_CX231XX is not set ++# CONFIG_VIDEO_CX2341X is not set ++# CONFIG_VIDEO_CX25840 is not set ++# CONFIG_VIDEO_CX88 is not set ++# CONFIG_VIDEO_DEV is not set ++# CONFIG_VIDEO_DM6446_CCDC is not set ++# CONFIG_VIDEO_DT3155 is not set ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++# CONFIG_VIDEO_GO7007 is not set ++# CONFIG_VIDEO_HDPVR is not set ++# CONFIG_VIDEO_HEXIUM_GEMINI is not set ++# CONFIG_VIDEO_HEXIUM_ORION is not set ++# CONFIG_VIDEO_IR_I2C is not set ++# CONFIG_VIDEO_IVTV is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_M52790 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_MXB is not set ++# CONFIG_VIDEO_NOON010PC30 is not set ++# CONFIG_VIDEO_OMAP2_VOUT is not set ++# CONFIG_VIDEO_OV2640 is not set ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV6650 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_PVRUSB2 is not set ++# CONFIG_VIDEO_SAA6588 is not set ++# CONFIG_VIDEO_SAA6752HS is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7134 is not set ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_SH_MOBILE_CEU is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_THS8200 is not set ++# CONFIG_VIDEO_TIMBERDALE is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_TM6000 is not set ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++# CONFIG_VIDEO_USBTV is not set ++# CONFIG_VIDEO_USBVISION is not set ++# CONFIG_VIDEO_V4L2 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_VPX3220 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_ZORAN is not set ++# CONFIG_VIRTIO_BALLOON is not set ++# CONFIG_VIRTIO_BLK_SCSI is not set ++# CONFIG_VIRTIO_INPUT is not set ++# CONFIG_VIRTIO_MMIO is not set ++# CONFIG_VIRTIO_PCI is not set ++# CONFIG_VIRTUALIZATION is not set ++# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set ++# CONFIG_VIRT_DRIVERS is not set ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_VL6180 is not set ++CONFIG_VLAN_8021Q=y ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_VLAN_8021Q_MVRP is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_VMSPLIT_1G is not set ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_2G_OPT is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_3G_OPT is not set ++# CONFIG_VMWARE_PVSCSI is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_VM_EVENT_COUNTERS is not set ++# CONFIG_VOP_BUS is not set ++# CONFIG_VORTEX is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_VT is not set ++# CONFIG_VT6655 is not set ++# CONFIG_VT6656 is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_VXGE is not set ++# CONFIG_VXLAN is not set ++# CONFIG_VZ89X is not set ++# CONFIG_W1 is not set ++# CONFIG_W1_CON is not set ++# CONFIG_W1_MASTER_DS1WM is not set ++# CONFIG_W1_MASTER_DS2482 is not set ++# CONFIG_W1_MASTER_DS2490 is not set ++# CONFIG_W1_MASTER_GPIO is not set ++# CONFIG_W1_MASTER_MATROX is not set ++# CONFIG_W1_SLAVE_DS2405 is not set ++# CONFIG_W1_SLAVE_DS2406 is not set ++# CONFIG_W1_SLAVE_DS2408 is not set ++# CONFIG_W1_SLAVE_DS2413 is not set ++# CONFIG_W1_SLAVE_DS2423 is not set ++# CONFIG_W1_SLAVE_DS2431 is not set ++# CONFIG_W1_SLAVE_DS2433 is not set ++# CONFIG_W1_SLAVE_DS2438 is not set ++# CONFIG_W1_SLAVE_DS2760 is not set ++# CONFIG_W1_SLAVE_DS2780 is not set ++# CONFIG_W1_SLAVE_DS2781 is not set ++# CONFIG_W1_SLAVE_DS2805 is not set ++# CONFIG_W1_SLAVE_DS28E04 is not set ++# CONFIG_W1_SLAVE_SMEM is not set ++# CONFIG_W1_SLAVE_THERM is not set ++# CONFIG_W83627HF_WDT is not set ++# CONFIG_W83877F_WDT is not set ++# CONFIG_W83977F_WDT is not set ++# CONFIG_WAN is not set ++# CONFIG_WANXL is not set ++# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_CORE is not set ++CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set ++# CONFIG_WATCHDOG_SYSFS is not set ++# CONFIG_WD80x3 is not set ++# CONFIG_WDAT_WDT is not set ++# CONFIG_WDTPCI is not set ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PRIV=y ++CONFIG_WEXT_PROC=y ++CONFIG_WEXT_SPY=y ++CONFIG_WILINK_PLATFORM_DATA=y ++# CONFIG_WIMAX is not set ++CONFIG_WIRELESS=y ++CONFIG_WIRELESS_EXT=y ++# CONFIG_WIRELESS_WDS is not set ++# CONFIG_WIZNET_W5100 is not set ++# CONFIG_WIZNET_W5300 is not set ++# CONFIG_WL1251 is not set ++# CONFIG_WL12XX is not set ++# CONFIG_WL18XX is not set ++CONFIG_WLAN=y ++# CONFIG_WLAN_VENDOR_ADMTEK is not set ++# CONFIG_WLAN_VENDOR_ATH is not set ++# CONFIG_WLAN_VENDOR_ATMEL is not set ++# CONFIG_WLAN_VENDOR_BROADCOM is not set ++# CONFIG_WLAN_VENDOR_CISCO is not set ++# CONFIG_WLAN_VENDOR_INTEL is not set ++# CONFIG_WLAN_VENDOR_INTERSIL is not set ++# CONFIG_WLAN_VENDOR_MARVELL is not set ++# CONFIG_WLAN_VENDOR_MEDIATEK is not set ++# CONFIG_WLAN_VENDOR_QUANTENNA is not set ++# CONFIG_WLAN_VENDOR_RALINK is not set ++# CONFIG_WLAN_VENDOR_REALTEK is not set ++# CONFIG_WLAN_VENDOR_RSI is not set ++# CONFIG_WLAN_VENDOR_ST is not set ++# CONFIG_WLAN_VENDOR_TI is not set ++# CONFIG_WLAN_VENDOR_ZYDAS is not set ++# CONFIG_WLCORE is not set ++CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_WW_MUTEX_SELFTEST is not set ++# CONFIG_X25 is not set ++# CONFIG_X509_CERTIFICATE_PARSER is not set ++# CONFIG_X86_PKG_TEMP_THERMAL is not set ++CONFIG_X86_SYSFB=y ++# CONFIG_XEN is not set ++CONFIG_XFRM=y ++# CONFIG_XFRM_IPCOMP is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_XFS_POSIX_ACL is not set ++# CONFIG_XFS_QUOTA is not set ++# CONFIG_XFS_RT is not set ++# CONFIG_XFS_WARN is not set ++# CONFIG_XILINX_AXI_EMAC is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_EMACLITE is not set ++# CONFIG_XILINX_GMII2RGMII is not set ++# CONFIG_XILINX_LL_TEMAC is not set ++# CONFIG_XILINX_WATCHDOG is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_XILLYBUS is not set ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_XMON is not set ++CONFIG_XZ_DEC=y ++# CONFIG_XZ_DEC_ARM is not set ++# CONFIG_XZ_DEC_ARMTHUMB is not set ++# CONFIG_XZ_DEC_BCJ is not set ++# CONFIG_XZ_DEC_IA64 is not set ++# CONFIG_XZ_DEC_POWERPC is not set ++# CONFIG_XZ_DEC_SPARC is not set ++# CONFIG_XZ_DEC_TEST is not set ++# CONFIG_XZ_DEC_X86 is not set ++# CONFIG_YAM is not set ++# CONFIG_YELLOWFIN is not set ++# CONFIG_YENTA is not set ++# CONFIG_YENTA_O2 is not set ++# CONFIG_YENTA_RICOH is not set ++# CONFIG_YENTA_TI is not set ++# CONFIG_YENTA_TOSHIBA is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZD1211RW is not set ++# CONFIG_ZD1211RW_DEBUG is not set ++# CONFIG_ZEROPLUS_FF is not set ++# CONFIG_ZIIRAVE_WATCHDOG is not set ++# CONFIG_ZISOFS is not set ++# CONFIG_ZLIB_DEFLATE is not set ++# CONFIG_ZLIB_INFLATE is not set ++CONFIG_ZONE_DMA=y ++# CONFIG_ZPA2326 is not set ++# CONFIG_ZPOOL is not set ++# CONFIG_ZRAM is not set ++# CONFIG_ZSMALLOC is not set ++# CONFIG_ZX_TDM is not set +diff --git a/target/linux/generic/hack-4.14/204-module_strip.patch b/target/linux/generic/hack-4.14/204-module_strip.patch +new file mode 100644 +index 0000000000..c53963c530 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/204-module_strip.patch +@@ -0,0 +1,208 @@ ++From a779a482fb9b9f8fcdf8b2519c789b4b9bb5dd05 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 16:56:48 +0200 ++Subject: build: add a hack for removing non-essential module info ++ ++Signed-off-by: Felix Fietkau ++--- ++ include/linux/module.h | 13 ++++++++----- ++ include/linux/moduleparam.h | 15 ++++++++++++--- ++ init/Kconfig | 7 +++++++ ++ kernel/module.c | 5 ++++- ++ scripts/mod/modpost.c | 12 ++++++++++++ ++ 5 files changed, 43 insertions(+), 9 deletions(-) ++ ++--- a/include/linux/module.h +++++ b/include/linux/module.h ++@@ -158,6 +158,7 @@ extern void cleanup_module(void); ++ ++ /* Generic info of form tag = "info" */ ++ #define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info) +++#define MODULE_INFO_STRIP(tag, info) __MODULE_INFO_STRIP(tag, tag, info) ++ ++ /* For userspace: you can also call me... */ ++ #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias) ++@@ -201,12 +202,12 @@ extern void cleanup_module(void); ++ * Author(s), use "Name " or just "Name", for multiple ++ * authors use multiple MODULE_AUTHOR() statements/lines. ++ */ ++-#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author) +++#define MODULE_AUTHOR(_author) MODULE_INFO_STRIP(author, _author) ++ ++ /* What your module does. */ ++-#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description) +++#define MODULE_DESCRIPTION(_description) MODULE_INFO_STRIP(description, _description) ++ ++-#ifdef MODULE +++#if defined(MODULE) && !defined(CONFIG_MODULE_STRIPPED) ++ /* Creates an alias so file2alias.c can find device table. */ ++ #define MODULE_DEVICE_TABLE(type, name) \ ++ extern typeof(name) __mod_##type##__##name##_device_table \ ++@@ -233,7 +234,9 @@ extern typeof(name) __mod_##type##__##na ++ */ ++ ++ #if defined(MODULE) || !defined(CONFIG_SYSFS) ++-#define MODULE_VERSION(_version) MODULE_INFO(version, _version) +++#define MODULE_VERSION(_version) MODULE_INFO_STRIP(version, _version) +++#elif defined(CONFIG_MODULE_STRIPPED) +++#define MODULE_VERSION(_version) __MODULE_INFO_DISABLED(version) ++ #else ++ #define MODULE_VERSION(_version) \ ++ static struct module_version_attribute ___modver_attr = { \ ++@@ -255,7 +258,7 @@ extern typeof(name) __mod_##type##__##na ++ /* Optional firmware file (or files) needed by the module ++ * format is simply firmware file name. Multiple firmware ++ * files require multiple MODULE_FIRMWARE() specifiers */ ++-#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware) +++#define MODULE_FIRMWARE(_firmware) MODULE_INFO_STRIP(firmware, _firmware) ++ ++ struct notifier_block; ++ ++--- a/include/linux/moduleparam.h +++++ b/include/linux/moduleparam.h ++@@ -17,6 +17,16 @@ ++ /* Chosen so that structs with an unsigned long line up. */ ++ #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) ++ +++/* This struct is here for syntactic coherency, it is not used */ +++#define __MODULE_INFO_DISABLED(name) \ +++ struct __UNIQUE_ID(name) {} +++ +++#ifdef CONFIG_MODULE_STRIPPED +++#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name) +++#else +++#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info) +++#endif +++ ++ #ifdef MODULE ++ #define __MODULE_INFO(tag, name, info) \ ++ static const char __UNIQUE_ID(name)[] \ ++@@ -24,8 +34,7 @@ static const char __UNIQUE_ID(name)[] ++ = __stringify(tag) "=" info ++ #else /* !MODULE */ ++ /* This struct is here for syntactic coherency, it is not used */ ++-#define __MODULE_INFO(tag, name, info) \ ++- struct __UNIQUE_ID(name) {} +++#define __MODULE_INFO(tag, name, info) __MODULE_INFO_DISABLED(name) ++ #endif ++ #define __MODULE_PARM_TYPE(name, _type) \ ++ __MODULE_INFO(parmtype, name##type, #name ":" _type) ++@@ -33,7 +42,7 @@ static const char __UNIQUE_ID(name)[] ++ /* One for each parameter, describing how to use it. Some files do ++ multiple of these per line, so can't just use MODULE_INFO. */ ++ #define MODULE_PARM_DESC(_parm, desc) \ ++- __MODULE_INFO(parm, _parm, #_parm ":" desc) +++ __MODULE_INFO_STRIP(parm, _parm, #_parm ":" desc) ++ ++ struct kernel_param; ++ ++--- a/init/Kconfig +++++ b/init/Kconfig ++@@ -1903,6 +1903,13 @@ config TRIM_UNUSED_KSYMS ++ ++ If unsure, or if you need to build out-of-tree modules, say N. ++ +++config MODULE_STRIPPED +++ bool "Reduce module size" +++ depends on MODULES +++ help +++ Remove module parameter descriptions, author info, version, aliases, +++ device tables, etc. +++ ++ endif # MODULES ++ ++ config MODULES_TREE_LOOKUP ++--- a/kernel/module.c +++++ b/kernel/module.c ++@@ -3024,9 +3024,11 @@ static struct module *setup_load_info(st ++ ++ static int check_modinfo(struct module *mod, struct load_info *info, int flags) ++ { ++- const char *modmagic = get_modinfo(info, "vermagic"); ++ int err; ++ +++#ifndef CONFIG_MODULE_STRIPPED +++ const char *modmagic = get_modinfo(info, "vermagic"); +++ ++ if (flags & MODULE_INIT_IGNORE_VERMAGIC) ++ modmagic = NULL; ++ ++@@ -3047,6 +3049,7 @@ static int check_modinfo(struct module * ++ mod->name); ++ add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK); ++ } +++#endif ++ ++ check_modinfo_retpoline(mod, info); ++ ++--- a/scripts/mod/modpost.c +++++ b/scripts/mod/modpost.c ++@@ -1996,7 +1996,9 @@ static void read_symbols(char *modname) ++ symname = remove_dot(info.strtab + sym->st_name); ++ ++ handle_modversions(mod, &info, sym, symname); +++#ifndef CONFIG_MODULE_STRIPPED ++ handle_moddevtable(mod, &info, sym, symname); +++#endif ++ } ++ if (!is_vmlinux(modname) || ++ (is_vmlinux(modname) && vmlinux_section_warnings)) ++@@ -2157,8 +2159,10 @@ static void add_header(struct buffer *b, ++ buf_printf(b, "#include \n"); ++ buf_printf(b, "#include \n"); ++ buf_printf(b, "\n"); +++#ifndef CONFIG_MODULE_STRIPPED ++ buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); ++ buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n"); +++#endif ++ buf_printf(b, "\n"); ++ buf_printf(b, "__visible struct module __this_module\n"); ++ buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); ++@@ -2175,8 +2179,10 @@ static void add_header(struct buffer *b, ++ ++ static void add_intree_flag(struct buffer *b, int is_intree) ++ { +++#ifndef CONFIG_MODULE_STRIPPED ++ if (is_intree) ++ buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); +++#endif ++ } ++ ++ /* Cannot check for assembler */ ++@@ -2189,10 +2195,12 @@ static void add_retpoline(struct buffer ++ ++ static void add_staging_flag(struct buffer *b, const char *name) ++ { +++#ifndef CONFIG_MODULE_STRIPPED ++ static const char *staging_dir = "drivers/staging"; ++ ++ if (strncmp(staging_dir, name, strlen(staging_dir)) == 0) ++ buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); +++#endif ++ } ++ ++ /** ++@@ -2291,11 +2299,13 @@ static void add_depends(struct buffer *b ++ ++ static void add_srcversion(struct buffer *b, struct module *mod) ++ { +++#ifndef CONFIG_MODULE_STRIPPED ++ if (mod->srcversion[0]) { ++ buf_printf(b, "\n"); ++ buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n", ++ mod->srcversion); ++ } +++#endif ++ } ++ ++ static void write_if_changed(struct buffer *b, const char *fname) ++@@ -2532,7 +2542,9 @@ int main(int argc, char **argv) ++ add_staging_flag(&buf, mod->name); ++ err |= add_versions(&buf, mod); ++ add_depends(&buf, mod, modules); +++#ifndef CONFIG_MODULE_STRIPPED ++ add_moddevtable(&buf, mod); +++#endif ++ add_srcversion(&buf, mod); ++ ++ sprintf(fname, "%s.mod.c", mod->name); +diff --git a/target/linux/generic/hack-4.14/207-disable-modorder.patch b/target/linux/generic/hack-4.14/207-disable-modorder.patch +new file mode 100644 +index 0000000000..0cfb4d33ec +--- /dev/null ++++ b/target/linux/generic/hack-4.14/207-disable-modorder.patch +@@ -0,0 +1,44 @@ ++From c9ef4ab0f54356ee9f91d9676ea0ec123840ddc7 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 16:57:33 +0200 ++Subject: kernel: do not build modules.order ++ ++It is not needed for anything on the system and skipping this saves some ++build time, especially in cases where there is nothing to do. ++ ++lede-commit: afc1675833a7bf5df094f59f7250369520646d04 ++Signed-off-by: Felix Fietkau ++--- ++ Makefile | 2 -- ++ scripts/Makefile.build | 2 +- ++ 2 files changed, 1 insertion(+), 3 deletions(-) ++ ++--- a/Makefile +++++ b/Makefile ++@@ -1260,7 +1260,6 @@ endif ++ ++ PHONY += modules ++ modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin ++- $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order ++ @$(kecho) ' Building modules, stage 2.'; ++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost ++ ++@@ -1289,7 +1288,6 @@ _modinst_: ++ rm -f $(MODLIB)/build ; \ ++ ln -s $(CURDIR) $(MODLIB)/build ; \ ++ fi ++- @cp -f $(objtree)/modules.order $(MODLIB)/ ++ @cp -f $(objtree)/modules.builtin $(MODLIB)/ ++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst ++ ++--- a/scripts/Makefile.build +++++ b/scripts/Makefile.build ++@@ -94,7 +94,7 @@ modorder-target := $(obj)/modules.order ++ # We keep a list of all modules in $(MODVERDIR) ++ ++ __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ ++- $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \ +++ $(if $(KBUILD_MODULES),$(obj-m)) \ ++ $(subdir-ym) $(always) ++ @: ++ +diff --git a/target/linux/generic/hack-4.14/210-darwin_scripts_include.patch b/target/linux/generic/hack-4.14/210-darwin_scripts_include.patch +new file mode 100644 +index 0000000000..95c7ea4232 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/210-darwin_scripts_include.patch +@@ -0,0 +1,3065 @@ ++From db7c30dcd9a0391bf13b62c9f91e144d762ef43a Mon Sep 17 00:00:00 2001 ++From: Florian Fainelli ++Date: Fri, 7 Jul 2017 17:00:49 +0200 ++Subject: Add an OSX specific patch to make the kernel be compiled ++ ++lede-commit: 3fc2a24f0422b2f55f9ed43f116db3111f700526 ++Signed-off-by: Florian Fainelli ++--- ++ scripts/kconfig/Makefile | 3 + ++ scripts/mod/elf.h | 3007 ++++++++++++++++++++++++++++++++++++++++++++ ++ scripts/mod/mk_elfconfig.c | 4 + ++ scripts/mod/modpost.h | 4 + ++ 4 files changed, 3018 insertions(+) ++ create mode 100644 scripts/mod/elf.h ++ ++--- a/scripts/kconfig/Makefile +++++ b/scripts/kconfig/Makefile ++@@ -164,6 +164,9 @@ check-lxdialog := $(srctree)/$(src)/lxd ++ # we really need to do so. (Do not call gcc as part of make mrproper) ++ HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \ ++ -DLOCALE +++ifeq ($(shell uname -s),Darwin) +++HOST_LOADLIBES += -lncurses +++endif ++ ++ # =========================================================================== ++ # Shared Makefile for the various kconfig executables: ++--- /dev/null +++++ b/scripts/mod/elf.h ++@@ -0,0 +1,3007 @@ +++/* This file defines standard ELF types, structures, and macros. +++ Copyright (C) 1995-2012 Free Software Foundation, Inc. +++ This file is part of the GNU C Library. +++ +++ The GNU C Library is free software; you can redistribute it and/or +++ modify it under the terms of the GNU Lesser General Public +++ License as published by the Free Software Foundation; either +++ version 2.1 of the License, or (at your option) any later version. +++ +++ The GNU C Library 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 +++ Lesser General Public License for more details. +++ +++ You should have received a copy of the GNU Lesser General Public +++ License along with the GNU C Library; if not, see +++ . */ +++ +++#ifndef _ELF_H +++#define _ELF_H 1 +++ +++/* Standard ELF types. */ +++ +++#include +++ +++/* Type for a 16-bit quantity. */ +++typedef uint16_t Elf32_Half; +++typedef uint16_t Elf64_Half; +++ +++/* Types for signed and unsigned 32-bit quantities. */ +++typedef uint32_t Elf32_Word; +++typedef int32_t Elf32_Sword; +++typedef uint32_t Elf64_Word; +++typedef int32_t Elf64_Sword; +++ +++/* Types for signed and unsigned 64-bit quantities. */ +++typedef uint64_t Elf32_Xword; +++typedef int64_t Elf32_Sxword; +++typedef uint64_t Elf64_Xword; +++typedef int64_t Elf64_Sxword; +++ +++/* Type of addresses. */ +++typedef uint32_t Elf32_Addr; +++typedef uint64_t Elf64_Addr; +++ +++/* Type of file offsets. */ +++typedef uint32_t Elf32_Off; +++typedef uint64_t Elf64_Off; +++ +++/* Type for section indices, which are 16-bit quantities. */ +++typedef uint16_t Elf32_Section; +++typedef uint16_t Elf64_Section; +++ +++/* Type for version symbol information. */ +++typedef Elf32_Half Elf32_Versym; +++typedef Elf64_Half Elf64_Versym; +++ +++ +++/* The ELF file header. This appears at the start of every ELF file. */ +++ +++#define EI_NIDENT (16) +++ +++typedef struct +++{ +++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ +++ Elf32_Half e_type; /* Object file type */ +++ Elf32_Half e_machine; /* Architecture */ +++ Elf32_Word e_version; /* Object file version */ +++ Elf32_Addr e_entry; /* Entry point virtual address */ +++ Elf32_Off e_phoff; /* Program header table file offset */ +++ Elf32_Off e_shoff; /* Section header table file offset */ +++ Elf32_Word e_flags; /* Processor-specific flags */ +++ Elf32_Half e_ehsize; /* ELF header size in bytes */ +++ Elf32_Half e_phentsize; /* Program header table entry size */ +++ Elf32_Half e_phnum; /* Program header table entry count */ +++ Elf32_Half e_shentsize; /* Section header table entry size */ +++ Elf32_Half e_shnum; /* Section header table entry count */ +++ Elf32_Half e_shstrndx; /* Section header string table index */ +++} Elf32_Ehdr; +++ +++typedef struct +++{ +++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ +++ Elf64_Half e_type; /* Object file type */ +++ Elf64_Half e_machine; /* Architecture */ +++ Elf64_Word e_version; /* Object file version */ +++ Elf64_Addr e_entry; /* Entry point virtual address */ +++ Elf64_Off e_phoff; /* Program header table file offset */ +++ Elf64_Off e_shoff; /* Section header table file offset */ +++ Elf64_Word e_flags; /* Processor-specific flags */ +++ Elf64_Half e_ehsize; /* ELF header size in bytes */ +++ Elf64_Half e_phentsize; /* Program header table entry size */ +++ Elf64_Half e_phnum; /* Program header table entry count */ +++ Elf64_Half e_shentsize; /* Section header table entry size */ +++ Elf64_Half e_shnum; /* Section header table entry count */ +++ Elf64_Half e_shstrndx; /* Section header string table index */ +++} Elf64_Ehdr; +++ +++/* Fields in the e_ident array. The EI_* macros are indices into the +++ array. The macros under each EI_* macro are the values the byte +++ may have. */ +++ +++#define EI_MAG0 0 /* File identification byte 0 index */ +++#define ELFMAG0 0x7f /* Magic number byte 0 */ +++ +++#define EI_MAG1 1 /* File identification byte 1 index */ +++#define ELFMAG1 'E' /* Magic number byte 1 */ +++ +++#define EI_MAG2 2 /* File identification byte 2 index */ +++#define ELFMAG2 'L' /* Magic number byte 2 */ +++ +++#define EI_MAG3 3 /* File identification byte 3 index */ +++#define ELFMAG3 'F' /* Magic number byte 3 */ +++ +++/* Conglomeration of the identification bytes, for easy testing as a word. */ +++#define ELFMAG "\177ELF" +++#define SELFMAG 4 +++ +++#define EI_CLASS 4 /* File class byte index */ +++#define ELFCLASSNONE 0 /* Invalid class */ +++#define ELFCLASS32 1 /* 32-bit objects */ +++#define ELFCLASS64 2 /* 64-bit objects */ +++#define ELFCLASSNUM 3 +++ +++#define EI_DATA 5 /* Data encoding byte index */ +++#define ELFDATANONE 0 /* Invalid data encoding */ +++#define ELFDATA2LSB 1 /* 2's complement, little endian */ +++#define ELFDATA2MSB 2 /* 2's complement, big endian */ +++#define ELFDATANUM 3 +++ +++#define EI_VERSION 6 /* File version byte index */ +++ /* Value must be EV_CURRENT */ +++ +++#define EI_OSABI 7 /* OS ABI identification */ +++#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +++#define ELFOSABI_SYSV 0 /* Alias. */ +++#define ELFOSABI_HPUX 1 /* HP-UX */ +++#define ELFOSABI_NETBSD 2 /* NetBSD. */ +++#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ +++#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ +++#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +++#define ELFOSABI_AIX 7 /* IBM AIX. */ +++#define ELFOSABI_IRIX 8 /* SGI Irix. */ +++#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +++#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +++#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +++#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +++#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ +++#define ELFOSABI_ARM 97 /* ARM */ +++#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ +++ +++#define EI_ABIVERSION 8 /* ABI version */ +++ +++#define EI_PAD 9 /* Byte index of padding bytes */ +++ +++/* Legal values for e_type (object file type). */ +++ +++#define ET_NONE 0 /* No file type */ +++#define ET_REL 1 /* Relocatable file */ +++#define ET_EXEC 2 /* Executable file */ +++#define ET_DYN 3 /* Shared object file */ +++#define ET_CORE 4 /* Core file */ +++#define ET_NUM 5 /* Number of defined types */ +++#define ET_LOOS 0xfe00 /* OS-specific range start */ +++#define ET_HIOS 0xfeff /* OS-specific range end */ +++#define ET_LOPROC 0xff00 /* Processor-specific range start */ +++#define ET_HIPROC 0xffff /* Processor-specific range end */ +++ +++/* Legal values for e_machine (architecture). */ +++ +++#define EM_NONE 0 /* No machine */ +++#define EM_M32 1 /* AT&T WE 32100 */ +++#define EM_SPARC 2 /* SUN SPARC */ +++#define EM_386 3 /* Intel 80386 */ +++#define EM_68K 4 /* Motorola m68k family */ +++#define EM_88K 5 /* Motorola m88k family */ +++#define EM_860 7 /* Intel 80860 */ +++#define EM_MIPS 8 /* MIPS R3000 big-endian */ +++#define EM_S370 9 /* IBM System/370 */ +++#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ +++ +++#define EM_PARISC 15 /* HPPA */ +++#define EM_VPP500 17 /* Fujitsu VPP500 */ +++#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +++#define EM_960 19 /* Intel 80960 */ +++#define EM_PPC 20 /* PowerPC */ +++#define EM_PPC64 21 /* PowerPC 64-bit */ +++#define EM_S390 22 /* IBM S390 */ +++ +++#define EM_V800 36 /* NEC V800 series */ +++#define EM_FR20 37 /* Fujitsu FR20 */ +++#define EM_RH32 38 /* TRW RH-32 */ +++#define EM_RCE 39 /* Motorola RCE */ +++#define EM_ARM 40 /* ARM */ +++#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +++#define EM_SH 42 /* Hitachi SH */ +++#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +++#define EM_TRICORE 44 /* Siemens Tricore */ +++#define EM_ARC 45 /* Argonaut RISC Core */ +++#define EM_H8_300 46 /* Hitachi H8/300 */ +++#define EM_H8_300H 47 /* Hitachi H8/300H */ +++#define EM_H8S 48 /* Hitachi H8S */ +++#define EM_H8_500 49 /* Hitachi H8/500 */ +++#define EM_IA_64 50 /* Intel Merced */ +++#define EM_MIPS_X 51 /* Stanford MIPS-X */ +++#define EM_COLDFIRE 52 /* Motorola Coldfire */ +++#define EM_68HC12 53 /* Motorola M68HC12 */ +++#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +++#define EM_PCP 55 /* Siemens PCP */ +++#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +++#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +++#define EM_STARCORE 58 /* Motorola Start*Core processor */ +++#define EM_ME16 59 /* Toyota ME16 processor */ +++#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +++#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +++#define EM_X86_64 62 /* AMD x86-64 architecture */ +++#define EM_PDSP 63 /* Sony DSP Processor */ +++ +++#define EM_FX66 66 /* Siemens FX66 microcontroller */ +++#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +++#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +++#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +++#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +++#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +++#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +++#define EM_SVX 73 /* Silicon Graphics SVx */ +++#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +++#define EM_VAX 75 /* Digital VAX */ +++#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +++#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +++#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +++#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +++#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +++#define EM_HUANY 81 /* Harvard University machine-independent object files */ +++#define EM_PRISM 82 /* SiTera Prism */ +++#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +++#define EM_FR30 84 /* Fujitsu FR30 */ +++#define EM_D10V 85 /* Mitsubishi D10V */ +++#define EM_D30V 86 /* Mitsubishi D30V */ +++#define EM_V850 87 /* NEC v850 */ +++#define EM_M32R 88 /* Mitsubishi M32R */ +++#define EM_MN10300 89 /* Matsushita MN10300 */ +++#define EM_MN10200 90 /* Matsushita MN10200 */ +++#define EM_PJ 91 /* picoJava */ +++#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +++#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +++#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +++#define EM_TILEPRO 188 /* Tilera TILEPro */ +++#define EM_TILEGX 191 /* Tilera TILE-Gx */ +++#define EM_NUM 192 +++ +++/* If it is necessary to assign new unofficial EM_* values, please +++ pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the +++ chances of collision with official or non-GNU unofficial values. */ +++ +++#define EM_ALPHA 0x9026 +++ +++/* Legal values for e_version (version). */ +++ +++#define EV_NONE 0 /* Invalid ELF version */ +++#define EV_CURRENT 1 /* Current version */ +++#define EV_NUM 2 +++ +++/* Section header. */ +++ +++typedef struct +++{ +++ Elf32_Word sh_name; /* Section name (string tbl index) */ +++ Elf32_Word sh_type; /* Section type */ +++ Elf32_Word sh_flags; /* Section flags */ +++ Elf32_Addr sh_addr; /* Section virtual addr at execution */ +++ Elf32_Off sh_offset; /* Section file offset */ +++ Elf32_Word sh_size; /* Section size in bytes */ +++ Elf32_Word sh_link; /* Link to another section */ +++ Elf32_Word sh_info; /* Additional section information */ +++ Elf32_Word sh_addralign; /* Section alignment */ +++ Elf32_Word sh_entsize; /* Entry size if section holds table */ +++} Elf32_Shdr; +++ +++typedef struct +++{ +++ Elf64_Word sh_name; /* Section name (string tbl index) */ +++ Elf64_Word sh_type; /* Section type */ +++ Elf64_Xword sh_flags; /* Section flags */ +++ Elf64_Addr sh_addr; /* Section virtual addr at execution */ +++ Elf64_Off sh_offset; /* Section file offset */ +++ Elf64_Xword sh_size; /* Section size in bytes */ +++ Elf64_Word sh_link; /* Link to another section */ +++ Elf64_Word sh_info; /* Additional section information */ +++ Elf64_Xword sh_addralign; /* Section alignment */ +++ Elf64_Xword sh_entsize; /* Entry size if section holds table */ +++} Elf64_Shdr; +++ +++/* Special section indices. */ +++ +++#define SHN_UNDEF 0 /* Undefined section */ +++#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +++#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +++#define SHN_BEFORE 0xff00 /* Order section before all others +++ (Solaris). */ +++#define SHN_AFTER 0xff01 /* Order section after all others +++ (Solaris). */ +++#define SHN_HIPROC 0xff1f /* End of processor-specific */ +++#define SHN_LOOS 0xff20 /* Start of OS-specific */ +++#define SHN_HIOS 0xff3f /* End of OS-specific */ +++#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +++#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +++#define SHN_XINDEX 0xffff /* Index is in extra table. */ +++#define SHN_HIRESERVE 0xffff /* End of reserved indices */ +++ +++/* Legal values for sh_type (section type). */ +++ +++#define SHT_NULL 0 /* Section header table entry unused */ +++#define SHT_PROGBITS 1 /* Program data */ +++#define SHT_SYMTAB 2 /* Symbol table */ +++#define SHT_STRTAB 3 /* String table */ +++#define SHT_RELA 4 /* Relocation entries with addends */ +++#define SHT_HASH 5 /* Symbol hash table */ +++#define SHT_DYNAMIC 6 /* Dynamic linking information */ +++#define SHT_NOTE 7 /* Notes */ +++#define SHT_NOBITS 8 /* Program space with no data (bss) */ +++#define SHT_REL 9 /* Relocation entries, no addends */ +++#define SHT_SHLIB 10 /* Reserved */ +++#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +++#define SHT_INIT_ARRAY 14 /* Array of constructors */ +++#define SHT_FINI_ARRAY 15 /* Array of destructors */ +++#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +++#define SHT_GROUP 17 /* Section group */ +++#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +++#define SHT_NUM 19 /* Number of defined types. */ +++#define SHT_LOOS 0x60000000 /* Start OS-specific. */ +++#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ +++#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +++#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +++#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +++#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +++#define SHT_SUNW_move 0x6ffffffa +++#define SHT_SUNW_COMDAT 0x6ffffffb +++#define SHT_SUNW_syminfo 0x6ffffffc +++#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +++#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +++#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +++#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +++#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +++#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +++#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +++#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +++#define SHT_HIUSER 0x8fffffff /* End of application-specific */ +++ +++/* Legal values for sh_flags (section flags). */ +++ +++#define SHF_WRITE (1 << 0) /* Writable */ +++#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +++#define SHF_EXECINSTR (1 << 2) /* Executable */ +++#define SHF_MERGE (1 << 4) /* Might be merged */ +++#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +++#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +++#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +++#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling +++ required */ +++#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +++#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +++#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +++#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +++#define SHF_ORDERED (1 << 30) /* Special ordering requirement +++ (Solaris). */ +++#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless +++ referenced or allocated (Solaris).*/ +++ +++/* Section group handling. */ +++#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ +++ +++/* Symbol table entry. */ +++ +++typedef struct +++{ +++ Elf32_Word st_name; /* Symbol name (string tbl index) */ +++ Elf32_Addr st_value; /* Symbol value */ +++ Elf32_Word st_size; /* Symbol size */ +++ unsigned char st_info; /* Symbol type and binding */ +++ unsigned char st_other; /* Symbol visibility */ +++ Elf32_Section st_shndx; /* Section index */ +++} Elf32_Sym; +++ +++typedef struct +++{ +++ Elf64_Word st_name; /* Symbol name (string tbl index) */ +++ unsigned char st_info; /* Symbol type and binding */ +++ unsigned char st_other; /* Symbol visibility */ +++ Elf64_Section st_shndx; /* Section index */ +++ Elf64_Addr st_value; /* Symbol value */ +++ Elf64_Xword st_size; /* Symbol size */ +++} Elf64_Sym; +++ +++/* The syminfo section if available contains additional information about +++ every dynamic symbol. */ +++ +++typedef struct +++{ +++ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ +++ Elf32_Half si_flags; /* Per symbol flags */ +++} Elf32_Syminfo; +++ +++typedef struct +++{ +++ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ +++ Elf64_Half si_flags; /* Per symbol flags */ +++} Elf64_Syminfo; +++ +++/* Possible values for si_boundto. */ +++#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +++#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +++#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ +++ +++/* Possible bitmasks for si_flags. */ +++#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +++#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +++#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +++#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy +++ loaded */ +++/* Syminfo version values. */ +++#define SYMINFO_NONE 0 +++#define SYMINFO_CURRENT 1 +++#define SYMINFO_NUM 2 +++ +++ +++/* How to extract and insert information held in the st_info field. */ +++ +++#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +++#define ELF32_ST_TYPE(val) ((val) & 0xf) +++#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) +++ +++/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +++#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +++#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +++#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) +++ +++/* Legal values for ST_BIND subfield of st_info (symbol binding). */ +++ +++#define STB_LOCAL 0 /* Local symbol */ +++#define STB_GLOBAL 1 /* Global symbol */ +++#define STB_WEAK 2 /* Weak symbol */ +++#define STB_NUM 3 /* Number of defined types. */ +++#define STB_LOOS 10 /* Start of OS-specific */ +++#define STB_GNU_UNIQUE 10 /* Unique symbol. */ +++#define STB_HIOS 12 /* End of OS-specific */ +++#define STB_LOPROC 13 /* Start of processor-specific */ +++#define STB_HIPROC 15 /* End of processor-specific */ +++ +++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ +++ +++#define STT_NOTYPE 0 /* Symbol type is unspecified */ +++#define STT_OBJECT 1 /* Symbol is a data object */ +++#define STT_FUNC 2 /* Symbol is a code object */ +++#define STT_SECTION 3 /* Symbol associated with a section */ +++#define STT_FILE 4 /* Symbol's name is file name */ +++#define STT_COMMON 5 /* Symbol is a common data object */ +++#define STT_TLS 6 /* Symbol is thread-local data object*/ +++#define STT_NUM 7 /* Number of defined types. */ +++#define STT_LOOS 10 /* Start of OS-specific */ +++#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ +++#define STT_HIOS 12 /* End of OS-specific */ +++#define STT_LOPROC 13 /* Start of processor-specific */ +++#define STT_HIPROC 15 /* End of processor-specific */ +++ +++ +++/* Symbol table indices are found in the hash buckets and chain table +++ of a symbol hash table section. This special index value indicates +++ the end of a chain, meaning no further symbols are found in that bucket. */ +++ +++#define STN_UNDEF 0 /* End of a chain. */ +++ +++ +++/* How to extract and insert information held in the st_other field. */ +++ +++#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) +++ +++/* For ELF64 the definitions are the same. */ +++#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) +++ +++/* Symbol visibility specification encoded in the st_other field. */ +++#define STV_DEFAULT 0 /* Default symbol visibility rules */ +++#define STV_INTERNAL 1 /* Processor specific hidden class */ +++#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +++#define STV_PROTECTED 3 /* Not preemptible, not exported */ +++ +++ +++/* Relocation table entry without addend (in section of type SHT_REL). */ +++ +++typedef struct +++{ +++ Elf32_Addr r_offset; /* Address */ +++ Elf32_Word r_info; /* Relocation type and symbol index */ +++} Elf32_Rel; +++ +++/* I have seen two different definitions of the Elf64_Rel and +++ Elf64_Rela structures, so we'll leave them out until Novell (or +++ whoever) gets their act together. */ +++/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ +++ +++typedef struct +++{ +++ Elf64_Addr r_offset; /* Address */ +++ Elf64_Xword r_info; /* Relocation type and symbol index */ +++} Elf64_Rel; +++ +++/* Relocation table entry with addend (in section of type SHT_RELA). */ +++ +++typedef struct +++{ +++ Elf32_Addr r_offset; /* Address */ +++ Elf32_Word r_info; /* Relocation type and symbol index */ +++ Elf32_Sword r_addend; /* Addend */ +++} Elf32_Rela; +++ +++typedef struct +++{ +++ Elf64_Addr r_offset; /* Address */ +++ Elf64_Xword r_info; /* Relocation type and symbol index */ +++ Elf64_Sxword r_addend; /* Addend */ +++} Elf64_Rela; +++ +++/* How to extract and insert information held in the r_info field. */ +++ +++#define ELF32_R_SYM(val) ((val) >> 8) +++#define ELF32_R_TYPE(val) ((val) & 0xff) +++#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) +++ +++#define ELF64_R_SYM(i) ((i) >> 32) +++#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +++#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) +++ +++/* Program segment header. */ +++ +++typedef struct +++{ +++ Elf32_Word p_type; /* Segment type */ +++ Elf32_Off p_offset; /* Segment file offset */ +++ Elf32_Addr p_vaddr; /* Segment virtual address */ +++ Elf32_Addr p_paddr; /* Segment physical address */ +++ Elf32_Word p_filesz; /* Segment size in file */ +++ Elf32_Word p_memsz; /* Segment size in memory */ +++ Elf32_Word p_flags; /* Segment flags */ +++ Elf32_Word p_align; /* Segment alignment */ +++} Elf32_Phdr; +++ +++typedef struct +++{ +++ Elf64_Word p_type; /* Segment type */ +++ Elf64_Word p_flags; /* Segment flags */ +++ Elf64_Off p_offset; /* Segment file offset */ +++ Elf64_Addr p_vaddr; /* Segment virtual address */ +++ Elf64_Addr p_paddr; /* Segment physical address */ +++ Elf64_Xword p_filesz; /* Segment size in file */ +++ Elf64_Xword p_memsz; /* Segment size in memory */ +++ Elf64_Xword p_align; /* Segment alignment */ +++} Elf64_Phdr; +++ +++/* Special value for e_phnum. This indicates that the real number of +++ program headers is too large to fit into e_phnum. Instead the real +++ value is in the field sh_info of section 0. */ +++ +++#define PN_XNUM 0xffff +++ +++/* Legal values for p_type (segment type). */ +++ +++#define PT_NULL 0 /* Program header table entry unused */ +++#define PT_LOAD 1 /* Loadable program segment */ +++#define PT_DYNAMIC 2 /* Dynamic linking information */ +++#define PT_INTERP 3 /* Program interpreter */ +++#define PT_NOTE 4 /* Auxiliary information */ +++#define PT_SHLIB 5 /* Reserved */ +++#define PT_PHDR 6 /* Entry for header table itself */ +++#define PT_TLS 7 /* Thread-local storage segment */ +++#define PT_NUM 8 /* Number of defined types */ +++#define PT_LOOS 0x60000000 /* Start of OS-specific */ +++#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +++#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +++#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +++#define PT_LOSUNW 0x6ffffffa +++#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +++#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +++#define PT_HISUNW 0x6fffffff +++#define PT_HIOS 0x6fffffff /* End of OS-specific */ +++#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +++#define PT_HIPROC 0x7fffffff /* End of processor-specific */ +++ +++/* Legal values for p_flags (segment flags). */ +++ +++#define PF_X (1 << 0) /* Segment is executable */ +++#define PF_W (1 << 1) /* Segment is writable */ +++#define PF_R (1 << 2) /* Segment is readable */ +++#define PF_MASKOS 0x0ff00000 /* OS-specific */ +++#define PF_MASKPROC 0xf0000000 /* Processor-specific */ +++ +++/* Legal values for note segment descriptor types for core files. */ +++ +++#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +++#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +++#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +++#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +++#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +++#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +++#define NT_AUXV 6 /* Contains copy of auxv array */ +++#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +++#define NT_ASRS 8 /* Contains copy of asrset struct */ +++#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +++#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +++#define NT_PRCRED 14 /* Contains copy of prcred struct */ +++#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +++#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +++#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +++#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ +++#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ +++#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ +++#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ +++#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ +++#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +++#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ +++#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ +++ +++/* Legal values for the note segment descriptor types for object files. */ +++ +++#define NT_VERSION 1 /* Contains a version string. */ +++ +++ +++/* Dynamic section entry. */ +++ +++typedef struct +++{ +++ Elf32_Sword d_tag; /* Dynamic entry type */ +++ union +++ { +++ Elf32_Word d_val; /* Integer value */ +++ Elf32_Addr d_ptr; /* Address value */ +++ } d_un; +++} Elf32_Dyn; +++ +++typedef struct +++{ +++ Elf64_Sxword d_tag; /* Dynamic entry type */ +++ union +++ { +++ Elf64_Xword d_val; /* Integer value */ +++ Elf64_Addr d_ptr; /* Address value */ +++ } d_un; +++} Elf64_Dyn; +++ +++/* Legal values for d_tag (dynamic entry type). */ +++ +++#define DT_NULL 0 /* Marks end of dynamic section */ +++#define DT_NEEDED 1 /* Name of needed library */ +++#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +++#define DT_PLTGOT 3 /* Processor defined value */ +++#define DT_HASH 4 /* Address of symbol hash table */ +++#define DT_STRTAB 5 /* Address of string table */ +++#define DT_SYMTAB 6 /* Address of symbol table */ +++#define DT_RELA 7 /* Address of Rela relocs */ +++#define DT_RELASZ 8 /* Total size of Rela relocs */ +++#define DT_RELAENT 9 /* Size of one Rela reloc */ +++#define DT_STRSZ 10 /* Size of string table */ +++#define DT_SYMENT 11 /* Size of one symbol table entry */ +++#define DT_INIT 12 /* Address of init function */ +++#define DT_FINI 13 /* Address of termination function */ +++#define DT_SONAME 14 /* Name of shared object */ +++#define DT_RPATH 15 /* Library search path (deprecated) */ +++#define DT_SYMBOLIC 16 /* Start symbol search here */ +++#define DT_REL 17 /* Address of Rel relocs */ +++#define DT_RELSZ 18 /* Total size of Rel relocs */ +++#define DT_RELENT 19 /* Size of one Rel reloc */ +++#define DT_PLTREL 20 /* Type of reloc in PLT */ +++#define DT_DEBUG 21 /* For debugging; unspecified */ +++#define DT_TEXTREL 22 /* Reloc might modify .text */ +++#define DT_JMPREL 23 /* Address of PLT relocs */ +++#define DT_BIND_NOW 24 /* Process relocations of object */ +++#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +++#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +++#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +++#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +++#define DT_RUNPATH 29 /* Library search path */ +++#define DT_FLAGS 30 /* Flags for the object being loaded */ +++#define DT_ENCODING 32 /* Start of encoded range */ +++#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +++#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +++#define DT_NUM 34 /* Number used */ +++#define DT_LOOS 0x6000000d /* Start of OS-specific */ +++#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +++#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +++#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +++#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ +++ +++/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the +++ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's +++ approach. */ +++#define DT_VALRNGLO 0x6ffffd00 +++#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +++#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +++#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +++#define DT_CHECKSUM 0x6ffffdf8 +++#define DT_PLTPADSZ 0x6ffffdf9 +++#define DT_MOVEENT 0x6ffffdfa +++#define DT_MOVESZ 0x6ffffdfb +++#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +++#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting +++ the following DT_* entry. */ +++#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +++#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +++#define DT_VALRNGHI 0x6ffffdff +++#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +++#define DT_VALNUM 12 +++ +++/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the +++ Dyn.d_un.d_ptr field of the Elf*_Dyn structure. +++ +++ If any adjustment is made to the ELF object after it has been +++ built these entries will need to be adjusted. */ +++#define DT_ADDRRNGLO 0x6ffffe00 +++#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ +++#define DT_TLSDESC_PLT 0x6ffffef6 +++#define DT_TLSDESC_GOT 0x6ffffef7 +++#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +++#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +++#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +++#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +++#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +++#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +++#define DT_MOVETAB 0x6ffffefe /* Move table. */ +++#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +++#define DT_ADDRRNGHI 0x6ffffeff +++#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +++#define DT_ADDRNUM 11 +++ +++/* The versioning entry types. The next are defined as part of the +++ GNU extension. */ +++#define DT_VERSYM 0x6ffffff0 +++ +++#define DT_RELACOUNT 0x6ffffff9 +++#define DT_RELCOUNT 0x6ffffffa +++ +++/* These were chosen by Sun. */ +++#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +++#define DT_VERDEF 0x6ffffffc /* Address of version definition +++ table */ +++#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +++#define DT_VERNEED 0x6ffffffe /* Address of table with needed +++ versions */ +++#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +++#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +++#define DT_VERSIONTAGNUM 16 +++ +++/* Sun added these machine-independent extensions in the "processor-specific" +++ range. Be compatible. */ +++#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +++#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +++#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +++#define DT_EXTRANUM 3 +++ +++/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +++#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +++#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +++#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +++#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +++#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ +++ +++/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 +++ entry in the dynamic section. */ +++#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +++#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +++#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +++#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +++#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +++#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +++#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +++#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +++#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +++#define DF_1_TRANS 0x00000200 +++#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +++#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +++#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +++#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +++#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +++#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +++#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ +++ +++/* Flags for the feature selection in DT_FEATURE_1. */ +++#define DTF_1_PARINIT 0x00000001 +++#define DTF_1_CONFEXP 0x00000002 +++ +++/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +++#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +++#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not +++ generally available. */ +++ +++/* Version definition sections. */ +++ +++typedef struct +++{ +++ Elf32_Half vd_version; /* Version revision */ +++ Elf32_Half vd_flags; /* Version information */ +++ Elf32_Half vd_ndx; /* Version Index */ +++ Elf32_Half vd_cnt; /* Number of associated aux entries */ +++ Elf32_Word vd_hash; /* Version name hash value */ +++ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ +++ Elf32_Word vd_next; /* Offset in bytes to next verdef +++ entry */ +++} Elf32_Verdef; +++ +++typedef struct +++{ +++ Elf64_Half vd_version; /* Version revision */ +++ Elf64_Half vd_flags; /* Version information */ +++ Elf64_Half vd_ndx; /* Version Index */ +++ Elf64_Half vd_cnt; /* Number of associated aux entries */ +++ Elf64_Word vd_hash; /* Version name hash value */ +++ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ +++ Elf64_Word vd_next; /* Offset in bytes to next verdef +++ entry */ +++} Elf64_Verdef; +++ +++ +++/* Legal values for vd_version (version revision). */ +++#define VER_DEF_NONE 0 /* No version */ +++#define VER_DEF_CURRENT 1 /* Current version */ +++#define VER_DEF_NUM 2 /* Given version number */ +++ +++/* Legal values for vd_flags (version information flags). */ +++#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +++#define VER_FLG_WEAK 0x2 /* Weak version identifier */ +++ +++/* Versym symbol index values. */ +++#define VER_NDX_LOCAL 0 /* Symbol is local. */ +++#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +++#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +++#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ +++ +++/* Auxialiary version information. */ +++ +++typedef struct +++{ +++ Elf32_Word vda_name; /* Version or dependency names */ +++ Elf32_Word vda_next; /* Offset in bytes to next verdaux +++ entry */ +++} Elf32_Verdaux; +++ +++typedef struct +++{ +++ Elf64_Word vda_name; /* Version or dependency names */ +++ Elf64_Word vda_next; /* Offset in bytes to next verdaux +++ entry */ +++} Elf64_Verdaux; +++ +++ +++/* Version dependency section. */ +++ +++typedef struct +++{ +++ Elf32_Half vn_version; /* Version of structure */ +++ Elf32_Half vn_cnt; /* Number of associated aux entries */ +++ Elf32_Word vn_file; /* Offset of filename for this +++ dependency */ +++ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ +++ Elf32_Word vn_next; /* Offset in bytes to next verneed +++ entry */ +++} Elf32_Verneed; +++ +++typedef struct +++{ +++ Elf64_Half vn_version; /* Version of structure */ +++ Elf64_Half vn_cnt; /* Number of associated aux entries */ +++ Elf64_Word vn_file; /* Offset of filename for this +++ dependency */ +++ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ +++ Elf64_Word vn_next; /* Offset in bytes to next verneed +++ entry */ +++} Elf64_Verneed; +++ +++ +++/* Legal values for vn_version (version revision). */ +++#define VER_NEED_NONE 0 /* No version */ +++#define VER_NEED_CURRENT 1 /* Current version */ +++#define VER_NEED_NUM 2 /* Given version number */ +++ +++/* Auxiliary needed version information. */ +++ +++typedef struct +++{ +++ Elf32_Word vna_hash; /* Hash value of dependency name */ +++ Elf32_Half vna_flags; /* Dependency specific information */ +++ Elf32_Half vna_other; /* Unused */ +++ Elf32_Word vna_name; /* Dependency name string offset */ +++ Elf32_Word vna_next; /* Offset in bytes to next vernaux +++ entry */ +++} Elf32_Vernaux; +++ +++typedef struct +++{ +++ Elf64_Word vna_hash; /* Hash value of dependency name */ +++ Elf64_Half vna_flags; /* Dependency specific information */ +++ Elf64_Half vna_other; /* Unused */ +++ Elf64_Word vna_name; /* Dependency name string offset */ +++ Elf64_Word vna_next; /* Offset in bytes to next vernaux +++ entry */ +++} Elf64_Vernaux; +++ +++ +++/* Legal values for vna_flags. */ +++#define VER_FLG_WEAK 0x2 /* Weak version identifier */ +++ +++ +++/* Auxiliary vector. */ +++ +++/* This vector is normally only used by the program interpreter. The +++ usual definition in an ABI supplement uses the name auxv_t. The +++ vector is not usually defined in a standard file, but it +++ can't hurt. We rename it to avoid conflicts. The sizes of these +++ types are an arrangement between the exec server and the program +++ interpreter, so we don't fully specify them here. */ +++ +++typedef struct +++{ +++ uint32_t a_type; /* Entry type */ +++ union +++ { +++ uint32_t a_val; /* Integer value */ +++ /* We use to have pointer elements added here. We cannot do that, +++ though, since it does not work when using 32-bit definitions +++ on 64-bit platforms and vice versa. */ +++ } a_un; +++} Elf32_auxv_t; +++ +++typedef struct +++{ +++ uint64_t a_type; /* Entry type */ +++ union +++ { +++ uint64_t a_val; /* Integer value */ +++ /* We use to have pointer elements added here. We cannot do that, +++ though, since it does not work when using 32-bit definitions +++ on 64-bit platforms and vice versa. */ +++ } a_un; +++} Elf64_auxv_t; +++ +++/* Legal values for a_type (entry type). */ +++ +++#define AT_NULL 0 /* End of vector */ +++#define AT_IGNORE 1 /* Entry should be ignored */ +++#define AT_EXECFD 2 /* File descriptor of program */ +++#define AT_PHDR 3 /* Program headers for program */ +++#define AT_PHENT 4 /* Size of program header entry */ +++#define AT_PHNUM 5 /* Number of program headers */ +++#define AT_PAGESZ 6 /* System page size */ +++#define AT_BASE 7 /* Base address of interpreter */ +++#define AT_FLAGS 8 /* Flags */ +++#define AT_ENTRY 9 /* Entry point of program */ +++#define AT_NOTELF 10 /* Program is not ELF */ +++#define AT_UID 11 /* Real uid */ +++#define AT_EUID 12 /* Effective uid */ +++#define AT_GID 13 /* Real gid */ +++#define AT_EGID 14 /* Effective gid */ +++#define AT_CLKTCK 17 /* Frequency of times() */ +++ +++/* Some more special a_type values describing the hardware. */ +++#define AT_PLATFORM 15 /* String identifying platform. */ +++#define AT_HWCAP 16 /* Machine dependent hints about +++ processor capabilities. */ +++ +++/* This entry gives some information about the FPU initialization +++ performed by the kernel. */ +++#define AT_FPUCW 18 /* Used FPU control word. */ +++ +++/* Cache block sizes. */ +++#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +++#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +++#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ +++ +++/* A special ignored value for PPC, used by the kernel to control the +++ interpretation of the AUXV. Must be > 16. */ +++#define AT_IGNOREPPC 22 /* Entry should be ignored. */ +++ +++#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ +++ +++#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ +++ +++#define AT_RANDOM 25 /* Address of 16 random bytes. */ +++ +++#define AT_EXECFN 31 /* Filename of executable. */ +++ +++/* Pointer to the global system page used for system calls and other +++ nice things. */ +++#define AT_SYSINFO 32 +++#define AT_SYSINFO_EHDR 33 +++ +++/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains +++ log2 of line size; mask those to get cache size. */ +++#define AT_L1I_CACHESHAPE 34 +++#define AT_L1D_CACHESHAPE 35 +++#define AT_L2_CACHESHAPE 36 +++#define AT_L3_CACHESHAPE 37 +++ +++/* Note section contents. Each entry in the note section begins with +++ a header of a fixed form. */ +++ +++typedef struct +++{ +++ Elf32_Word n_namesz; /* Length of the note's name. */ +++ Elf32_Word n_descsz; /* Length of the note's descriptor. */ +++ Elf32_Word n_type; /* Type of the note. */ +++} Elf32_Nhdr; +++ +++typedef struct +++{ +++ Elf64_Word n_namesz; /* Length of the note's name. */ +++ Elf64_Word n_descsz; /* Length of the note's descriptor. */ +++ Elf64_Word n_type; /* Type of the note. */ +++} Elf64_Nhdr; +++ +++/* Known names of notes. */ +++ +++/* Solaris entries in the note section have this name. */ +++#define ELF_NOTE_SOLARIS "SUNW Solaris" +++ +++/* Note entries for GNU systems have this name. */ +++#define ELF_NOTE_GNU "GNU" +++ +++ +++/* Defined types of notes for Solaris. */ +++ +++/* Value of descriptor (one word) is desired pagesize for the binary. */ +++#define ELF_NOTE_PAGESIZE_HINT 1 +++ +++ +++/* Defined note types for GNU systems. */ +++ +++/* ABI information. The descriptor consists of words: +++ word 0: OS descriptor +++ word 1: major version of the ABI +++ word 2: minor version of the ABI +++ word 3: subminor version of the ABI +++*/ +++#define NT_GNU_ABI_TAG 1 +++#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ +++ +++/* Known OSes. These values can appear in word 0 of an +++ NT_GNU_ABI_TAG note section entry. */ +++#define ELF_NOTE_OS_LINUX 0 +++#define ELF_NOTE_OS_GNU 1 +++#define ELF_NOTE_OS_SOLARIS2 2 +++#define ELF_NOTE_OS_FREEBSD 3 +++ +++/* Synthetic hwcap information. The descriptor begins with two words: +++ word 0: number of entries +++ word 1: bitmask of enabled entries +++ Then follow variable-length entries, one byte followed by a +++ '\0'-terminated hwcap name string. The byte gives the bit +++ number to test if enabled, (1U << bit) & bitmask. */ +++#define NT_GNU_HWCAP 2 +++ +++/* Build ID bits as generated by ld --build-id. +++ The descriptor consists of any nonzero number of bytes. */ +++#define NT_GNU_BUILD_ID 3 +++ +++/* Version note generated by GNU gold containing a version string. */ +++#define NT_GNU_GOLD_VERSION 4 +++ +++ +++/* Move records. */ +++typedef struct +++{ +++ Elf32_Xword m_value; /* Symbol value. */ +++ Elf32_Word m_info; /* Size and index. */ +++ Elf32_Word m_poffset; /* Symbol offset. */ +++ Elf32_Half m_repeat; /* Repeat count. */ +++ Elf32_Half m_stride; /* Stride info. */ +++} Elf32_Move; +++ +++typedef struct +++{ +++ Elf64_Xword m_value; /* Symbol value. */ +++ Elf64_Xword m_info; /* Size and index. */ +++ Elf64_Xword m_poffset; /* Symbol offset. */ +++ Elf64_Half m_repeat; /* Repeat count. */ +++ Elf64_Half m_stride; /* Stride info. */ +++} Elf64_Move; +++ +++/* Macro to construct move records. */ +++#define ELF32_M_SYM(info) ((info) >> 8) +++#define ELF32_M_SIZE(info) ((unsigned char) (info)) +++#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) +++ +++#define ELF64_M_SYM(info) ELF32_M_SYM (info) +++#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +++#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) +++ +++ +++/* Motorola 68k specific definitions. */ +++ +++/* Values for Elf32_Ehdr.e_flags. */ +++#define EF_CPU32 0x00810000 +++ +++/* m68k relocs. */ +++ +++#define R_68K_NONE 0 /* No reloc */ +++#define R_68K_32 1 /* Direct 32 bit */ +++#define R_68K_16 2 /* Direct 16 bit */ +++#define R_68K_8 3 /* Direct 8 bit */ +++#define R_68K_PC32 4 /* PC relative 32 bit */ +++#define R_68K_PC16 5 /* PC relative 16 bit */ +++#define R_68K_PC8 6 /* PC relative 8 bit */ +++#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +++#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +++#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +++#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +++#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +++#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +++#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +++#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +++#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +++#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +++#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +++#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +++#define R_68K_COPY 19 /* Copy symbol at runtime */ +++#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +++#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +++#define R_68K_RELATIVE 22 /* Adjust by program base */ +++#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ +++#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ +++#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ +++#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ +++#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ +++#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ +++#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ +++#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ +++#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ +++#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ +++#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ +++#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ +++#define R_68K_TLS_LE32 37 /* 32 bit offset relative to +++ static TLS block */ +++#define R_68K_TLS_LE16 38 /* 16 bit offset relative to +++ static TLS block */ +++#define R_68K_TLS_LE8 39 /* 8 bit offset relative to +++ static TLS block */ +++#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ +++#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ +++#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ +++/* Keep this the last entry. */ +++#define R_68K_NUM 43 +++ +++/* Intel 80386 specific definitions. */ +++ +++/* i386 relocs. */ +++ +++#define R_386_NONE 0 /* No reloc */ +++#define R_386_32 1 /* Direct 32 bit */ +++#define R_386_PC32 2 /* PC relative 32 bit */ +++#define R_386_GOT32 3 /* 32 bit GOT entry */ +++#define R_386_PLT32 4 /* 32 bit PLT address */ +++#define R_386_COPY 5 /* Copy symbol at runtime */ +++#define R_386_GLOB_DAT 6 /* Create GOT entry */ +++#define R_386_JMP_SLOT 7 /* Create PLT entry */ +++#define R_386_RELATIVE 8 /* Adjust by program base */ +++#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +++#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +++#define R_386_32PLT 11 +++#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +++#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS +++ block offset */ +++#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block +++ offset */ +++#define R_386_TLS_LE 17 /* Offset relative to static TLS +++ block */ +++#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of +++ general dynamic thread local data */ +++#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of +++ local dynamic thread local data +++ in LE code */ +++#define R_386_16 20 +++#define R_386_PC16 21 +++#define R_386_8 22 +++#define R_386_PC8 23 +++#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic +++ thread local data */ +++#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +++#define R_386_TLS_GD_CALL 26 /* Relocation for call to +++ __tls_get_addr() */ +++#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +++#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic +++ thread local data in LE code */ +++#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +++#define R_386_TLS_LDM_CALL 30 /* Relocation for call to +++ __tls_get_addr() in LDM code */ +++#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +++#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +++#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS +++ block offset */ +++#define R_386_TLS_LE_32 34 /* Negated offset relative to static +++ TLS block */ +++#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +++#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +++#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +++/* 38? */ +++#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ +++#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS +++ descriptor for +++ relaxation. */ +++#define R_386_TLS_DESC 41 /* TLS descriptor containing +++ pointer to code and to +++ argument, returning the TLS +++ offset for the symbol. */ +++#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ +++/* Keep this the last entry. */ +++#define R_386_NUM 43 +++ +++/* SUN SPARC specific definitions. */ +++ +++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ +++ +++#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ +++ +++/* Values for Elf64_Ehdr.e_flags. */ +++ +++#define EF_SPARCV9_MM 3 +++#define EF_SPARCV9_TSO 0 +++#define EF_SPARCV9_PSO 1 +++#define EF_SPARCV9_RMO 2 +++#define EF_SPARC_LEDATA 0x800000 /* little endian data */ +++#define EF_SPARC_EXT_MASK 0xFFFF00 +++#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +++#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ +++#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +++#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ +++ +++/* SPARC relocs. */ +++ +++#define R_SPARC_NONE 0 /* No reloc */ +++#define R_SPARC_8 1 /* Direct 8 bit */ +++#define R_SPARC_16 2 /* Direct 16 bit */ +++#define R_SPARC_32 3 /* Direct 32 bit */ +++#define R_SPARC_DISP8 4 /* PC relative 8 bit */ +++#define R_SPARC_DISP16 5 /* PC relative 16 bit */ +++#define R_SPARC_DISP32 6 /* PC relative 32 bit */ +++#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ +++#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ +++#define R_SPARC_HI22 9 /* High 22 bit */ +++#define R_SPARC_22 10 /* Direct 22 bit */ +++#define R_SPARC_13 11 /* Direct 13 bit */ +++#define R_SPARC_LO10 12 /* Truncated 10 bit */ +++#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ +++#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ +++#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ +++#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ +++#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ +++#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ +++#define R_SPARC_COPY 19 /* Copy symbol at runtime */ +++#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ +++#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ +++#define R_SPARC_RELATIVE 22 /* Adjust by program base */ +++#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ +++ +++/* Additional Sparc64 relocs. */ +++ +++#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ +++#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ +++#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ +++#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ +++#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ +++#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ +++#define R_SPARC_10 30 /* Direct 10 bit */ +++#define R_SPARC_11 31 /* Direct 11 bit */ +++#define R_SPARC_64 32 /* Direct 64 bit */ +++#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ +++#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ +++#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ +++#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ +++#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ +++#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ +++#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ +++#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ +++#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ +++#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */ +++#define R_SPARC_7 43 /* Direct 7 bit */ +++#define R_SPARC_5 44 /* Direct 5 bit */ +++#define R_SPARC_6 45 /* Direct 6 bit */ +++#define R_SPARC_DISP64 46 /* PC relative 64 bit */ +++#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ +++#define R_SPARC_HIX22 48 /* High 22 bit complemented */ +++#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ +++#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ +++#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ +++#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ +++#define R_SPARC_REGISTER 53 /* Global register usage */ +++#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ +++#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ +++#define R_SPARC_TLS_GD_HI22 56 +++#define R_SPARC_TLS_GD_LO10 57 +++#define R_SPARC_TLS_GD_ADD 58 +++#define R_SPARC_TLS_GD_CALL 59 +++#define R_SPARC_TLS_LDM_HI22 60 +++#define R_SPARC_TLS_LDM_LO10 61 +++#define R_SPARC_TLS_LDM_ADD 62 +++#define R_SPARC_TLS_LDM_CALL 63 +++#define R_SPARC_TLS_LDO_HIX22 64 +++#define R_SPARC_TLS_LDO_LOX10 65 +++#define R_SPARC_TLS_LDO_ADD 66 +++#define R_SPARC_TLS_IE_HI22 67 +++#define R_SPARC_TLS_IE_LO10 68 +++#define R_SPARC_TLS_IE_LD 69 +++#define R_SPARC_TLS_IE_LDX 70 +++#define R_SPARC_TLS_IE_ADD 71 +++#define R_SPARC_TLS_LE_HIX22 72 +++#define R_SPARC_TLS_LE_LOX10 73 +++#define R_SPARC_TLS_DTPMOD32 74 +++#define R_SPARC_TLS_DTPMOD64 75 +++#define R_SPARC_TLS_DTPOFF32 76 +++#define R_SPARC_TLS_DTPOFF64 77 +++#define R_SPARC_TLS_TPOFF32 78 +++#define R_SPARC_TLS_TPOFF64 79 +++#define R_SPARC_GOTDATA_HIX22 80 +++#define R_SPARC_GOTDATA_LOX10 81 +++#define R_SPARC_GOTDATA_OP_HIX22 82 +++#define R_SPARC_GOTDATA_OP_LOX10 83 +++#define R_SPARC_GOTDATA_OP 84 +++#define R_SPARC_H34 85 +++#define R_SPARC_SIZE32 86 +++#define R_SPARC_SIZE64 87 +++#define R_SPARC_WDISP10 88 +++#define R_SPARC_JMP_IREL 248 +++#define R_SPARC_IRELATIVE 249 +++#define R_SPARC_GNU_VTINHERIT 250 +++#define R_SPARC_GNU_VTENTRY 251 +++#define R_SPARC_REV32 252 +++/* Keep this the last entry. */ +++#define R_SPARC_NUM 253 +++ +++/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ +++ +++#define DT_SPARC_REGISTER 0x70000001 +++#define DT_SPARC_NUM 2 +++ +++/* MIPS R3000 specific definitions. */ +++ +++/* Legal values for e_flags field of Elf32_Ehdr. */ +++ +++#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ +++#define EF_MIPS_PIC 2 /* Contains PIC code */ +++#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ +++#define EF_MIPS_XGOT 8 +++#define EF_MIPS_64BIT_WHIRL 16 +++#define EF_MIPS_ABI2 32 +++#define EF_MIPS_ABI_ON32 64 +++#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ +++ +++/* Legal values for MIPS architecture level. */ +++ +++#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +++#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +++#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +++#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +++#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +++#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +++#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ +++ +++/* The following are non-official names and should not be used. */ +++ +++#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +++#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +++#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +++#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +++#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +++#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +++#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ +++ +++/* Special section indices. */ +++ +++#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +++#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +++#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +++#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +++#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ +++ +++/* Legal values for sh_type field of Elf32_Shdr. */ +++ +++#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +++#define SHT_MIPS_MSYM 0x70000001 +++#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +++#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +++#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +++#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ +++#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ +++#define SHT_MIPS_PACKAGE 0x70000007 +++#define SHT_MIPS_PACKSYM 0x70000008 +++#define SHT_MIPS_RELD 0x70000009 +++#define SHT_MIPS_IFACE 0x7000000b +++#define SHT_MIPS_CONTENT 0x7000000c +++#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ +++#define SHT_MIPS_SHDR 0x70000010 +++#define SHT_MIPS_FDESC 0x70000011 +++#define SHT_MIPS_EXTSYM 0x70000012 +++#define SHT_MIPS_DENSE 0x70000013 +++#define SHT_MIPS_PDESC 0x70000014 +++#define SHT_MIPS_LOCSYM 0x70000015 +++#define SHT_MIPS_AUXSYM 0x70000016 +++#define SHT_MIPS_OPTSYM 0x70000017 +++#define SHT_MIPS_LOCSTR 0x70000018 +++#define SHT_MIPS_LINE 0x70000019 +++#define SHT_MIPS_RFDESC 0x7000001a +++#define SHT_MIPS_DELTASYM 0x7000001b +++#define SHT_MIPS_DELTAINST 0x7000001c +++#define SHT_MIPS_DELTACLASS 0x7000001d +++#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ +++#define SHT_MIPS_DELTADECL 0x7000001f +++#define SHT_MIPS_SYMBOL_LIB 0x70000020 +++#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +++#define SHT_MIPS_TRANSLATE 0x70000022 +++#define SHT_MIPS_PIXIE 0x70000023 +++#define SHT_MIPS_XLATE 0x70000024 +++#define SHT_MIPS_XLATE_DEBUG 0x70000025 +++#define SHT_MIPS_WHIRL 0x70000026 +++#define SHT_MIPS_EH_REGION 0x70000027 +++#define SHT_MIPS_XLATE_OLD 0x70000028 +++#define SHT_MIPS_PDR_EXCEPTION 0x70000029 +++ +++/* Legal values for sh_flags field of Elf32_Shdr. */ +++ +++#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ +++#define SHF_MIPS_MERGE 0x20000000 +++#define SHF_MIPS_ADDR 0x40000000 +++#define SHF_MIPS_STRINGS 0x80000000 +++#define SHF_MIPS_NOSTRIP 0x08000000 +++#define SHF_MIPS_LOCAL 0x04000000 +++#define SHF_MIPS_NAMES 0x02000000 +++#define SHF_MIPS_NODUPE 0x01000000 +++ +++ +++/* Symbol tables. */ +++ +++/* MIPS specific values for `st_other'. */ +++#define STO_MIPS_DEFAULT 0x0 +++#define STO_MIPS_INTERNAL 0x1 +++#define STO_MIPS_HIDDEN 0x2 +++#define STO_MIPS_PROTECTED 0x3 +++#define STO_MIPS_PLT 0x8 +++#define STO_MIPS_SC_ALIGN_UNUSED 0xff +++ +++/* MIPS specific values for `st_info'. */ +++#define STB_MIPS_SPLIT_COMMON 13 +++ +++/* Entries found in sections of type SHT_MIPS_GPTAB. */ +++ +++typedef union +++{ +++ struct +++ { +++ Elf32_Word gt_current_g_value; /* -G value used for compilation */ +++ Elf32_Word gt_unused; /* Not used */ +++ } gt_header; /* First entry in section */ +++ struct +++ { +++ Elf32_Word gt_g_value; /* If this value were used for -G */ +++ Elf32_Word gt_bytes; /* This many bytes would be used */ +++ } gt_entry; /* Subsequent entries in section */ +++} Elf32_gptab; +++ +++/* Entry found in sections of type SHT_MIPS_REGINFO. */ +++ +++typedef struct +++{ +++ Elf32_Word ri_gprmask; /* General registers used */ +++ Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ +++ Elf32_Sword ri_gp_value; /* $gp register value */ +++} Elf32_RegInfo; +++ +++/* Entries found in sections of type SHT_MIPS_OPTIONS. */ +++ +++typedef struct +++{ +++ unsigned char kind; /* Determines interpretation of the +++ variable part of descriptor. */ +++ unsigned char size; /* Size of descriptor, including header. */ +++ Elf32_Section section; /* Section header index of section affected, +++ 0 for global options. */ +++ Elf32_Word info; /* Kind-specific information. */ +++} Elf_Options; +++ +++/* Values for `kind' field in Elf_Options. */ +++ +++#define ODK_NULL 0 /* Undefined. */ +++#define ODK_REGINFO 1 /* Register usage information. */ +++#define ODK_EXCEPTIONS 2 /* Exception processing options. */ +++#define ODK_PAD 3 /* Section padding options. */ +++#define ODK_HWPATCH 4 /* Hardware workarounds performed */ +++#define ODK_FILL 5 /* record the fill value used by the linker. */ +++#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ +++#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ +++#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ +++ +++/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ +++ +++#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ +++#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ +++#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ +++#define OEX_SMM 0x20000 /* Force sequential memory mode? */ +++#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ +++#define OEX_PRECISEFP OEX_FPDBUG +++#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ +++ +++#define OEX_FPU_INVAL 0x10 +++#define OEX_FPU_DIV0 0x08 +++#define OEX_FPU_OFLO 0x04 +++#define OEX_FPU_UFLO 0x02 +++#define OEX_FPU_INEX 0x01 +++ +++/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ +++ +++#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ +++#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ +++#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ +++#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ +++ +++#define OPAD_PREFIX 0x1 +++#define OPAD_POSTFIX 0x2 +++#define OPAD_SYMBOL 0x4 +++ +++/* Entry found in `.options' section. */ +++ +++typedef struct +++{ +++ Elf32_Word hwp_flags1; /* Extra flags. */ +++ Elf32_Word hwp_flags2; /* Extra flags. */ +++} Elf_Options_Hw; +++ +++/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ +++ +++#define OHWA0_R4KEOP_CHECKED 0x00000001 +++#define OHWA1_R4KEOP_CLEAN 0x00000002 +++ +++/* MIPS relocs. */ +++ +++#define R_MIPS_NONE 0 /* No reloc */ +++#define R_MIPS_16 1 /* Direct 16 bit */ +++#define R_MIPS_32 2 /* Direct 32 bit */ +++#define R_MIPS_REL32 3 /* PC relative 32 bit */ +++#define R_MIPS_26 4 /* Direct 26 bit shifted */ +++#define R_MIPS_HI16 5 /* High 16 bit */ +++#define R_MIPS_LO16 6 /* Low 16 bit */ +++#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +++#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +++#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +++#define R_MIPS_PC16 10 /* PC relative 16 bit */ +++#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +++#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +++ +++#define R_MIPS_SHIFT5 16 +++#define R_MIPS_SHIFT6 17 +++#define R_MIPS_64 18 +++#define R_MIPS_GOT_DISP 19 +++#define R_MIPS_GOT_PAGE 20 +++#define R_MIPS_GOT_OFST 21 +++#define R_MIPS_GOT_HI16 22 +++#define R_MIPS_GOT_LO16 23 +++#define R_MIPS_SUB 24 +++#define R_MIPS_INSERT_A 25 +++#define R_MIPS_INSERT_B 26 +++#define R_MIPS_DELETE 27 +++#define R_MIPS_HIGHER 28 +++#define R_MIPS_HIGHEST 29 +++#define R_MIPS_CALL_HI16 30 +++#define R_MIPS_CALL_LO16 31 +++#define R_MIPS_SCN_DISP 32 +++#define R_MIPS_REL16 33 +++#define R_MIPS_ADD_IMMEDIATE 34 +++#define R_MIPS_PJUMP 35 +++#define R_MIPS_RELGOT 36 +++#define R_MIPS_JALR 37 +++#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ +++#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ +++#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ +++#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ +++#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ +++#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ +++#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ +++#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ +++#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ +++#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ +++#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ +++#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ +++#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ +++#define R_MIPS_GLOB_DAT 51 +++#define R_MIPS_COPY 126 +++#define R_MIPS_JUMP_SLOT 127 +++/* Keep this the last entry. */ +++#define R_MIPS_NUM 128 +++ +++/* Legal values for p_type field of Elf32_Phdr. */ +++ +++#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +++#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ +++#define PT_MIPS_OPTIONS 0x70000002 +++ +++/* Special program header types. */ +++ +++#define PF_MIPS_LOCAL 0x10000000 +++ +++/* Legal values for d_tag field of Elf32_Dyn. */ +++ +++#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ +++#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +++#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ +++#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +++#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +++#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ +++#define DT_MIPS_MSYM 0x70000007 +++#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ +++#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ +++#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ +++#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ +++#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ +++#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ +++#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +++#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ +++#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +++#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ +++#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ +++#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in +++ DT_MIPS_DELTA_CLASS. */ +++#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ +++#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in +++ DT_MIPS_DELTA_INSTANCE. */ +++#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ +++#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in +++ DT_MIPS_DELTA_RELOC. */ +++#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta +++ relocations refer to. */ +++#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in +++ DT_MIPS_DELTA_SYM. */ +++#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the +++ class declaration. */ +++#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in +++ DT_MIPS_DELTA_CLASSSYM. */ +++#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ +++#define DT_MIPS_PIXIE_INIT 0x70000023 +++#define DT_MIPS_SYMBOL_LIB 0x70000024 +++#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +++#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +++#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +++#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +++#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ +++#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ +++#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +++#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ +++#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve +++ function stored in GOT. */ +++#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added +++ by rld on dlopen() calls. */ +++#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ +++#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ +++#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ +++/* The address of .got.plt in an executable using the new non-PIC ABI. */ +++#define DT_MIPS_PLTGOT 0x70000032 +++/* The base of the PLT in an executable using the new non-PIC ABI if that +++ PLT is writable. For a non-writable PLT, this is omitted or has a zero +++ value. */ +++#define DT_MIPS_RWPLT 0x70000034 +++#define DT_MIPS_NUM 0x35 +++ +++/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ +++ +++#define RHF_NONE 0 /* No flags */ +++#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ +++#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ +++#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ +++#define RHF_NO_MOVE (1 << 3) +++#define RHF_SGI_ONLY (1 << 4) +++#define RHF_GUARANTEE_INIT (1 << 5) +++#define RHF_DELTA_C_PLUS_PLUS (1 << 6) +++#define RHF_GUARANTEE_START_INIT (1 << 7) +++#define RHF_PIXIE (1 << 8) +++#define RHF_DEFAULT_DELAY_LOAD (1 << 9) +++#define RHF_REQUICKSTART (1 << 10) +++#define RHF_REQUICKSTARTED (1 << 11) +++#define RHF_CORD (1 << 12) +++#define RHF_NO_UNRES_UNDEF (1 << 13) +++#define RHF_RLD_ORDER_SAFE (1 << 14) +++ +++/* Entries found in sections of type SHT_MIPS_LIBLIST. */ +++ +++typedef struct +++{ +++ Elf32_Word l_name; /* Name (string table index) */ +++ Elf32_Word l_time_stamp; /* Timestamp */ +++ Elf32_Word l_checksum; /* Checksum */ +++ Elf32_Word l_version; /* Interface version */ +++ Elf32_Word l_flags; /* Flags */ +++} Elf32_Lib; +++ +++typedef struct +++{ +++ Elf64_Word l_name; /* Name (string table index) */ +++ Elf64_Word l_time_stamp; /* Timestamp */ +++ Elf64_Word l_checksum; /* Checksum */ +++ Elf64_Word l_version; /* Interface version */ +++ Elf64_Word l_flags; /* Flags */ +++} Elf64_Lib; +++ +++ +++/* Legal values for l_flags. */ +++ +++#define LL_NONE 0 +++#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +++#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +++#define LL_REQUIRE_MINOR (1 << 2) +++#define LL_EXPORTS (1 << 3) +++#define LL_DELAY_LOAD (1 << 4) +++#define LL_DELTA (1 << 5) +++ +++/* Entries found in sections of type SHT_MIPS_CONFLICT. */ +++ +++typedef Elf32_Addr Elf32_Conflict; +++ +++ +++/* HPPA specific definitions. */ +++ +++/* Legal values for e_flags field of Elf32_Ehdr. */ +++ +++#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +++#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +++#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +++#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +++#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch +++ prediction. */ +++#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +++#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ +++ +++/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ +++ +++#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +++#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +++#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ +++ +++/* Additional section indeces. */ +++ +++#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared +++ symbols in ANSI C. */ +++#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ +++ +++/* Legal values for sh_type field of Elf32_Shdr. */ +++ +++#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +++#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +++#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ +++ +++/* Legal values for sh_flags field of Elf32_Shdr. */ +++ +++#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +++#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +++#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ +++ +++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ +++ +++#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ +++ +++#define STT_HP_OPAQUE (STT_LOOS + 0x1) +++#define STT_HP_STUB (STT_LOOS + 0x2) +++ +++/* HPPA relocs. */ +++ +++#define R_PARISC_NONE 0 /* No reloc. */ +++#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +++#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +++#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +++#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +++#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +++#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +++#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +++#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +++#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +++#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +++#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +++#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +++#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +++#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +++#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +++#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +++#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +++#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +++#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +++#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +++#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +++#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +++#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +++#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +++#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +++#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +++#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */ +++#define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */ +++#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +++#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +++#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +++#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +++#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +++#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +++#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +++#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +++#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +++#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +++#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +++#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +++#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +++#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +++#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +++#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +++#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +++#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +++#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +++#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +++#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +++#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +++#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +++#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +++#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +++#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +++#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +++#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +++#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +++#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +++#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +++#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +++#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +++#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +++#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +++#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +++#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +++#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +++#define R_PARISC_LORESERVE 128 +++#define R_PARISC_COPY 128 /* Copy relocation. */ +++#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +++#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +++#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +++#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +++#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +++#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +++#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +++#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +++#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +++#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +++#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +++#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +++#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +++#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +++#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +++#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +++#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +++#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +++#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +++#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +++#define R_PARISC_GNU_VTENTRY 232 +++#define R_PARISC_GNU_VTINHERIT 233 +++#define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */ +++#define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */ +++#define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */ +++#define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */ +++#define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */ +++#define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */ +++#define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */ +++#define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */ +++#define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */ +++#define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */ +++#define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */ +++#define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */ +++#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L +++#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R +++#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L +++#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R +++#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 +++#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 +++#define R_PARISC_HIRESERVE 255 +++ +++/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ +++ +++#define PT_HP_TLS (PT_LOOS + 0x0) +++#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +++#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +++#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +++#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +++#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +++#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +++#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +++#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +++#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +++#define PT_HP_PARALLEL (PT_LOOS + 0x10) +++#define PT_HP_FASTBIND (PT_LOOS + 0x11) +++#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +++#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +++#define PT_HP_STACK (PT_LOOS + 0x14) +++ +++#define PT_PARISC_ARCHEXT 0x70000000 +++#define PT_PARISC_UNWIND 0x70000001 +++ +++/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ +++ +++#define PF_PARISC_SBP 0x08000000 +++ +++#define PF_HP_PAGE_SIZE 0x00100000 +++#define PF_HP_FAR_SHARED 0x00200000 +++#define PF_HP_NEAR_SHARED 0x00400000 +++#define PF_HP_CODE 0x01000000 +++#define PF_HP_MODIFY 0x02000000 +++#define PF_HP_LAZYSWAP 0x04000000 +++#define PF_HP_SBP 0x08000000 +++ +++ +++/* Alpha specific definitions. */ +++ +++/* Legal values for e_flags field of Elf64_Ehdr. */ +++ +++#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ +++#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ +++ +++/* Legal values for sh_type field of Elf64_Shdr. */ +++ +++/* These two are primerily concerned with ECOFF debugging info. */ +++#define SHT_ALPHA_DEBUG 0x70000001 +++#define SHT_ALPHA_REGINFO 0x70000002 +++ +++/* Legal values for sh_flags field of Elf64_Shdr. */ +++ +++#define SHF_ALPHA_GPREL 0x10000000 +++ +++/* Legal values for st_other field of Elf64_Sym. */ +++#define STO_ALPHA_NOPV 0x80 /* No PV required. */ +++#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ +++ +++/* Alpha relocs. */ +++ +++#define R_ALPHA_NONE 0 /* No reloc */ +++#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +++#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +++#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +++#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +++#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +++#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +++#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +++#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +++#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +++#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +++#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +++#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ +++#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ +++#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ +++#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +++#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +++#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +++#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ +++#define R_ALPHA_TLS_GD_HI 28 +++#define R_ALPHA_TLSGD 29 +++#define R_ALPHA_TLS_LDM 30 +++#define R_ALPHA_DTPMOD64 31 +++#define R_ALPHA_GOTDTPREL 32 +++#define R_ALPHA_DTPREL64 33 +++#define R_ALPHA_DTPRELHI 34 +++#define R_ALPHA_DTPRELLO 35 +++#define R_ALPHA_DTPREL16 36 +++#define R_ALPHA_GOTTPREL 37 +++#define R_ALPHA_TPREL64 38 +++#define R_ALPHA_TPRELHI 39 +++#define R_ALPHA_TPRELLO 40 +++#define R_ALPHA_TPREL16 41 +++/* Keep this the last entry. */ +++#define R_ALPHA_NUM 46 +++ +++/* Magic values of the LITUSE relocation addend. */ +++#define LITUSE_ALPHA_ADDR 0 +++#define LITUSE_ALPHA_BASE 1 +++#define LITUSE_ALPHA_BYTOFF 2 +++#define LITUSE_ALPHA_JSR 3 +++#define LITUSE_ALPHA_TLS_GD 4 +++#define LITUSE_ALPHA_TLS_LDM 5 +++ +++/* Legal values for d_tag of Elf64_Dyn. */ +++#define DT_ALPHA_PLTRO (DT_LOPROC + 0) +++#define DT_ALPHA_NUM 1 +++ +++/* PowerPC specific declarations */ +++ +++/* Values for Elf32/64_Ehdr.e_flags. */ +++#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ +++ +++/* Cygnus local bits below */ +++#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +++#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib +++ flag */ +++ +++/* PowerPC relocations defined by the ABIs */ +++#define R_PPC_NONE 0 +++#define R_PPC_ADDR32 1 /* 32bit absolute address */ +++#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +++#define R_PPC_ADDR16 3 /* 16bit absolute address */ +++#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +++#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +++#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +++#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +++#define R_PPC_ADDR14_BRTAKEN 8 +++#define R_PPC_ADDR14_BRNTAKEN 9 +++#define R_PPC_REL24 10 /* PC relative 26 bit */ +++#define R_PPC_REL14 11 /* PC relative 16 bit */ +++#define R_PPC_REL14_BRTAKEN 12 +++#define R_PPC_REL14_BRNTAKEN 13 +++#define R_PPC_GOT16 14 +++#define R_PPC_GOT16_LO 15 +++#define R_PPC_GOT16_HI 16 +++#define R_PPC_GOT16_HA 17 +++#define R_PPC_PLTREL24 18 +++#define R_PPC_COPY 19 +++#define R_PPC_GLOB_DAT 20 +++#define R_PPC_JMP_SLOT 21 +++#define R_PPC_RELATIVE 22 +++#define R_PPC_LOCAL24PC 23 +++#define R_PPC_UADDR32 24 +++#define R_PPC_UADDR16 25 +++#define R_PPC_REL32 26 +++#define R_PPC_PLT32 27 +++#define R_PPC_PLTREL32 28 +++#define R_PPC_PLT16_LO 29 +++#define R_PPC_PLT16_HI 30 +++#define R_PPC_PLT16_HA 31 +++#define R_PPC_SDAREL16 32 +++#define R_PPC_SECTOFF 33 +++#define R_PPC_SECTOFF_LO 34 +++#define R_PPC_SECTOFF_HI 35 +++#define R_PPC_SECTOFF_HA 36 +++ +++/* PowerPC relocations defined for the TLS access ABI. */ +++#define R_PPC_TLS 67 /* none (sym+add)@tls */ +++#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +++#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +++#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +++#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +++#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +++#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +++#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +++#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +++#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +++#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +++#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +++#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +++#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +++#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +++#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +++#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +++#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +++#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +++#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +++#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ +++#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ +++#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +++#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +++#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ +++#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ +++#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ +++#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ +++ +++/* The remaining relocs are from the Embedded ELF ABI, and are not +++ in the SVR4 ELF ABI. */ +++#define R_PPC_EMB_NADDR32 101 +++#define R_PPC_EMB_NADDR16 102 +++#define R_PPC_EMB_NADDR16_LO 103 +++#define R_PPC_EMB_NADDR16_HI 104 +++#define R_PPC_EMB_NADDR16_HA 105 +++#define R_PPC_EMB_SDAI16 106 +++#define R_PPC_EMB_SDA2I16 107 +++#define R_PPC_EMB_SDA2REL 108 +++#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +++#define R_PPC_EMB_MRKREF 110 +++#define R_PPC_EMB_RELSEC16 111 +++#define R_PPC_EMB_RELST_LO 112 +++#define R_PPC_EMB_RELST_HI 113 +++#define R_PPC_EMB_RELST_HA 114 +++#define R_PPC_EMB_BIT_FLD 115 +++#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ +++ +++/* Diab tool relocations. */ +++#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +++#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +++#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +++#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +++#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +++#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ +++ +++/* GNU extension to support local ifunc. */ +++#define R_PPC_IRELATIVE 248 +++ +++/* GNU relocs used in PIC code sequences. */ +++#define R_PPC_REL16 249 /* half16 (sym+add-.) */ +++#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */ +++#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */ +++#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */ +++ +++/* This is a phony reloc to handle any old fashioned TOC16 references +++ that may still be in object files. */ +++#define R_PPC_TOC16 255 +++ +++/* PowerPC specific values for the Dyn d_tag field. */ +++#define DT_PPC_GOT (DT_LOPROC + 0) +++#define DT_PPC_NUM 1 +++ +++/* PowerPC64 relocations defined by the ABIs */ +++#define R_PPC64_NONE R_PPC_NONE +++#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ +++#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ +++#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ +++#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ +++#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ +++#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +++#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ +++#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +++#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +++#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ +++#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ +++#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +++#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +++#define R_PPC64_GOT16 R_PPC_GOT16 +++#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +++#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +++#define R_PPC64_GOT16_HA R_PPC_GOT16_HA +++ +++#define R_PPC64_COPY R_PPC_COPY +++#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +++#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +++#define R_PPC64_RELATIVE R_PPC_RELATIVE +++ +++#define R_PPC64_UADDR32 R_PPC_UADDR32 +++#define R_PPC64_UADDR16 R_PPC_UADDR16 +++#define R_PPC64_REL32 R_PPC_REL32 +++#define R_PPC64_PLT32 R_PPC_PLT32 +++#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +++#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +++#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +++#define R_PPC64_PLT16_HA R_PPC_PLT16_HA +++ +++#define R_PPC64_SECTOFF R_PPC_SECTOFF +++#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +++#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +++#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +++#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ +++#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ +++#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ +++#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ +++#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ +++#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ +++#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ +++#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ +++#define R_PPC64_PLT64 45 /* doubleword64 L + A */ +++#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ +++#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ +++#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ +++#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ +++#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ +++#define R_PPC64_TOC 51 /* doubleword64 .TOC */ +++#define R_PPC64_PLTGOT16 52 /* half16* M + A */ +++#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ +++#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ +++#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ +++ +++#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ +++#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ +++#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ +++#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ +++#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ +++#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ +++#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ +++#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ +++#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ +++#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ +++#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ +++ +++/* PowerPC64 relocations defined for the TLS access ABI. */ +++#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +++#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +++#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +++#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +++#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +++#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +++#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +++#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +++#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +++#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +++#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +++#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +++#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +++#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +++#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +++#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +++#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +++#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +++#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +++#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +++#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ +++#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ +++#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +++#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +++#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ +++#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ +++#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ +++#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ +++#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +++#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ +++#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ +++#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ +++#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ +++#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ +++#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +++#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ +++#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ +++#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ +++#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ +++#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ +++ +++/* GNU extension to support local ifunc. */ +++#define R_PPC64_JMP_IREL 247 +++#define R_PPC64_IRELATIVE 248 +++#define R_PPC64_REL16 249 /* half16 (sym+add-.) */ +++#define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */ +++#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ +++#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ +++ +++/* PowerPC64 specific values for the Dyn d_tag field. */ +++#define DT_PPC64_GLINK (DT_LOPROC + 0) +++#define DT_PPC64_OPD (DT_LOPROC + 1) +++#define DT_PPC64_OPDSZ (DT_LOPROC + 2) +++#define DT_PPC64_NUM 3 +++ +++ +++/* ARM specific declarations */ +++ +++/* Processor specific flags for the ELF header e_flags field. */ +++#define EF_ARM_RELEXEC 0x01 +++#define EF_ARM_HASENTRY 0x02 +++#define EF_ARM_INTERWORK 0x04 +++#define EF_ARM_APCS_26 0x08 +++#define EF_ARM_APCS_FLOAT 0x10 +++#define EF_ARM_PIC 0x20 +++#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +++#define EF_ARM_NEW_ABI 0x80 +++#define EF_ARM_OLD_ABI 0x100 +++#define EF_ARM_SOFT_FLOAT 0x200 +++#define EF_ARM_VFP_FLOAT 0x400 +++#define EF_ARM_MAVERICK_FLOAT 0x800 +++ +++ +++/* Other constants defined in the ARM ELF spec. version B-01. */ +++/* NB. These conflict with values defined above. */ +++#define EF_ARM_SYMSARESORTED 0x04 +++#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +++#define EF_ARM_MAPSYMSFIRST 0x10 +++#define EF_ARM_EABIMASK 0XFF000000 +++ +++/* Constants defined in AAELF. */ +++#define EF_ARM_BE8 0x00800000 +++#define EF_ARM_LE8 0x00400000 +++ +++#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +++#define EF_ARM_EABI_UNKNOWN 0x00000000 +++#define EF_ARM_EABI_VER1 0x01000000 +++#define EF_ARM_EABI_VER2 0x02000000 +++#define EF_ARM_EABI_VER3 0x03000000 +++#define EF_ARM_EABI_VER4 0x04000000 +++#define EF_ARM_EABI_VER5 0x05000000 +++ +++/* Additional symbol types for Thumb. */ +++#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +++#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ +++ +++/* ARM-specific values for sh_flags */ +++#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +++#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined +++ in the input to a link step. */ +++ +++/* ARM-specific program header flags */ +++#define PF_ARM_SB 0x10000000 /* Segment contains the location +++ addressed by the static base. */ +++#define PF_ARM_PI 0x20000000 /* Position-independent segment. */ +++#define PF_ARM_ABS 0x40000000 /* Absolute segment. */ +++ +++/* Processor specific values for the Phdr p_type field. */ +++#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ +++ +++/* Processor specific values for the Shdr sh_type field. */ +++#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ +++#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ +++#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ +++ +++ +++/* ARM relocs. */ +++ +++#define R_ARM_NONE 0 /* No reloc */ +++#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +++#define R_ARM_ABS32 2 /* Direct 32 bit */ +++#define R_ARM_REL32 3 /* PC relative 32 bit */ +++#define R_ARM_PC13 4 +++#define R_ARM_ABS16 5 /* Direct 16 bit */ +++#define R_ARM_ABS12 6 /* Direct 12 bit */ +++#define R_ARM_THM_ABS5 7 +++#define R_ARM_ABS8 8 /* Direct 8 bit */ +++#define R_ARM_SBREL32 9 +++#define R_ARM_THM_PC22 10 +++#define R_ARM_THM_PC8 11 +++#define R_ARM_AMP_VCALL9 12 +++#define R_ARM_SWI24 13 /* Obsolete static relocation. */ +++#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */ +++#define R_ARM_THM_SWI8 14 +++#define R_ARM_XPC25 15 +++#define R_ARM_THM_XPC22 16 +++#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +++#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +++#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +++#define R_ARM_COPY 20 /* Copy symbol at runtime */ +++#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +++#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +++#define R_ARM_RELATIVE 23 /* Adjust by program base */ +++#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +++#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +++#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +++#define R_ARM_PLT32 27 /* 32 bit PLT address */ +++#define R_ARM_ALU_PCREL_7_0 32 +++#define R_ARM_ALU_PCREL_15_8 33 +++#define R_ARM_ALU_PCREL_23_15 34 +++#define R_ARM_LDR_SBREL_11_0 35 +++#define R_ARM_ALU_SBREL_19_12 36 +++#define R_ARM_ALU_SBREL_27_20 37 +++#define R_ARM_TLS_GOTDESC 90 +++#define R_ARM_TLS_CALL 91 +++#define R_ARM_TLS_DESCSEQ 92 +++#define R_ARM_THM_TLS_CALL 93 +++#define R_ARM_GNU_VTENTRY 100 +++#define R_ARM_GNU_VTINHERIT 101 +++#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ +++#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +++#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic +++ thread local data */ +++#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic +++ thread local data */ +++#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS +++ block */ +++#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of +++ static TLS block offset */ +++#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static +++ TLS block */ +++#define R_ARM_THM_TLS_DESCSEQ 129 +++#define R_ARM_IRELATIVE 160 +++#define R_ARM_RXPC25 249 +++#define R_ARM_RSBREL32 250 +++#define R_ARM_THM_RPC22 251 +++#define R_ARM_RREL32 252 +++#define R_ARM_RABS22 253 +++#define R_ARM_RPC24 254 +++#define R_ARM_RBASE 255 +++/* Keep this the last entry. */ +++#define R_ARM_NUM 256 +++ +++/* IA-64 specific declarations. */ +++ +++/* Processor specific flags for the Ehdr e_flags field. */ +++#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ +++#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ +++#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ +++ +++/* Processor specific values for the Phdr p_type field. */ +++#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ +++#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ +++#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) +++#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) +++#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) +++ +++/* Processor specific flags for the Phdr p_flags field. */ +++#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ +++ +++/* Processor specific values for the Shdr sh_type field. */ +++#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ +++#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ +++ +++/* Processor specific flags for the Shdr sh_flags field. */ +++#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ +++#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ +++ +++/* Processor specific values for the Dyn d_tag field. */ +++#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +++#define DT_IA_64_NUM 1 +++ +++/* IA-64 relocations. */ +++#define R_IA64_NONE 0x00 /* none */ +++#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ +++#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ +++#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ +++#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ +++#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ +++#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ +++#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ +++#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ +++#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ +++#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ +++#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ +++#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ +++#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ +++#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ +++#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ +++#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ +++#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ +++#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ +++#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ +++#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ +++#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ +++#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ +++#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ +++#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ +++#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ +++#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ +++#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ +++#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ +++#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ +++#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ +++#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ +++#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ +++#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ +++#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ +++#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ +++#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ +++#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ +++#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ +++#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ +++#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ +++#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ +++#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ +++#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ +++#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ +++#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ +++#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ +++#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ +++#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ +++#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ +++#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ +++#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ +++#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ +++#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ +++#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ +++#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ +++#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ +++#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ +++#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ +++#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ +++#define R_IA64_COPY 0x84 /* copy relocation */ +++#define R_IA64_SUB 0x85 /* Addend and symbol difference */ +++#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ +++#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ +++#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ +++#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ +++#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ +++#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ +++#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ +++#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ +++#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ +++#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ +++#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ +++#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ +++#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ +++#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ +++#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ +++#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ +++#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ +++#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ +++#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ +++ +++/* SH specific declarations */ +++ +++/* Processor specific flags for the ELF header e_flags field. */ +++#define EF_SH_MACH_MASK 0x1f +++#define EF_SH_UNKNOWN 0x0 +++#define EF_SH1 0x1 +++#define EF_SH2 0x2 +++#define EF_SH3 0x3 +++#define EF_SH_DSP 0x4 +++#define EF_SH3_DSP 0x5 +++#define EF_SH4AL_DSP 0x6 +++#define EF_SH3E 0x8 +++#define EF_SH4 0x9 +++#define EF_SH2E 0xb +++#define EF_SH4A 0xc +++#define EF_SH2A 0xd +++#define EF_SH4_NOFPU 0x10 +++#define EF_SH4A_NOFPU 0x11 +++#define EF_SH4_NOMMU_NOFPU 0x12 +++#define EF_SH2A_NOFPU 0x13 +++#define EF_SH3_NOMMU 0x14 +++#define EF_SH2A_SH4_NOFPU 0x15 +++#define EF_SH2A_SH3_NOFPU 0x16 +++#define EF_SH2A_SH4 0x17 +++#define EF_SH2A_SH3E 0x18 +++ +++/* SH relocs. */ +++#define R_SH_NONE 0 +++#define R_SH_DIR32 1 +++#define R_SH_REL32 2 +++#define R_SH_DIR8WPN 3 +++#define R_SH_IND12W 4 +++#define R_SH_DIR8WPL 5 +++#define R_SH_DIR8WPZ 6 +++#define R_SH_DIR8BP 7 +++#define R_SH_DIR8W 8 +++#define R_SH_DIR8L 9 +++#define R_SH_SWITCH16 25 +++#define R_SH_SWITCH32 26 +++#define R_SH_USES 27 +++#define R_SH_COUNT 28 +++#define R_SH_ALIGN 29 +++#define R_SH_CODE 30 +++#define R_SH_DATA 31 +++#define R_SH_LABEL 32 +++#define R_SH_SWITCH8 33 +++#define R_SH_GNU_VTINHERIT 34 +++#define R_SH_GNU_VTENTRY 35 +++#define R_SH_TLS_GD_32 144 +++#define R_SH_TLS_LD_32 145 +++#define R_SH_TLS_LDO_32 146 +++#define R_SH_TLS_IE_32 147 +++#define R_SH_TLS_LE_32 148 +++#define R_SH_TLS_DTPMOD32 149 +++#define R_SH_TLS_DTPOFF32 150 +++#define R_SH_TLS_TPOFF32 151 +++#define R_SH_GOT32 160 +++#define R_SH_PLT32 161 +++#define R_SH_COPY 162 +++#define R_SH_GLOB_DAT 163 +++#define R_SH_JMP_SLOT 164 +++#define R_SH_RELATIVE 165 +++#define R_SH_GOTOFF 166 +++#define R_SH_GOTPC 167 +++/* Keep this the last entry. */ +++#define R_SH_NUM 256 +++ +++/* S/390 specific definitions. */ +++ +++/* Valid values for the e_flags field. */ +++ +++#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ +++ +++/* Additional s390 relocs */ +++ +++#define R_390_NONE 0 /* No reloc. */ +++#define R_390_8 1 /* Direct 8 bit. */ +++#define R_390_12 2 /* Direct 12 bit. */ +++#define R_390_16 3 /* Direct 16 bit. */ +++#define R_390_32 4 /* Direct 32 bit. */ +++#define R_390_PC32 5 /* PC relative 32 bit. */ +++#define R_390_GOT12 6 /* 12 bit GOT offset. */ +++#define R_390_GOT32 7 /* 32 bit GOT offset. */ +++#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +++#define R_390_COPY 9 /* Copy symbol at runtime. */ +++#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +++#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +++#define R_390_RELATIVE 12 /* Adjust by program base. */ +++#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ +++#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +++#define R_390_GOT16 15 /* 16 bit GOT offset. */ +++#define R_390_PC16 16 /* PC relative 16 bit. */ +++#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +++#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +++#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +++#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +++#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +++#define R_390_64 22 /* Direct 64 bit. */ +++#define R_390_PC64 23 /* PC relative 64 bit. */ +++#define R_390_GOT64 24 /* 64 bit GOT offset. */ +++#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +++#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +++#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ +++#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ +++#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ +++#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ +++#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ +++#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ +++#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ +++#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ +++#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ +++#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ +++#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ +++#define R_390_TLS_GDCALL 38 /* Tag for function call in general +++ dynamic TLS code. */ +++#define R_390_TLS_LDCALL 39 /* Tag for function call in local +++ dynamic TLS code. */ +++#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic +++ thread local data. */ +++#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic +++ thread local data. */ +++#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS +++ block offset. */ +++#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS +++ block offset. */ +++#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS +++ block offset. */ +++#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic +++ thread local data in LE code. */ +++#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic +++ thread local data in LE code. */ +++#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for +++ negated static TLS block offset. */ +++#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for +++ negated static TLS block offset. */ +++#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for +++ negated static TLS block offset. */ +++#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to +++ static TLS block. */ +++#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to +++ static TLS block. */ +++#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS +++ block. */ +++#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS +++ block. */ +++#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ +++#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ +++#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS +++ block. */ +++#define R_390_20 57 /* Direct 20 bit. */ +++#define R_390_GOT20 58 /* 20 bit GOT offset. */ +++#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ +++#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS +++ block offset. */ +++#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */ +++/* Keep this the last entry. */ +++#define R_390_NUM 62 +++ +++ +++/* CRIS relocations. */ +++#define R_CRIS_NONE 0 +++#define R_CRIS_8 1 +++#define R_CRIS_16 2 +++#define R_CRIS_32 3 +++#define R_CRIS_8_PCREL 4 +++#define R_CRIS_16_PCREL 5 +++#define R_CRIS_32_PCREL 6 +++#define R_CRIS_GNU_VTINHERIT 7 +++#define R_CRIS_GNU_VTENTRY 8 +++#define R_CRIS_COPY 9 +++#define R_CRIS_GLOB_DAT 10 +++#define R_CRIS_JUMP_SLOT 11 +++#define R_CRIS_RELATIVE 12 +++#define R_CRIS_16_GOT 13 +++#define R_CRIS_32_GOT 14 +++#define R_CRIS_16_GOTPLT 15 +++#define R_CRIS_32_GOTPLT 16 +++#define R_CRIS_32_GOTREL 17 +++#define R_CRIS_32_PLT_GOTREL 18 +++#define R_CRIS_32_PLT_PCREL 19 +++ +++#define R_CRIS_NUM 20 +++ +++ +++/* AMD x86-64 relocations. */ +++#define R_X86_64_NONE 0 /* No reloc */ +++#define R_X86_64_64 1 /* Direct 64 bit */ +++#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +++#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +++#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +++#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +++#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +++#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +++#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +++#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative +++ offset to GOT */ +++#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +++#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +++#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +++#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +++#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +++#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +++#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +++#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +++#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +++#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset +++ to two GOT entries for GD symbol */ +++#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset +++ to two GOT entries for LD symbol */ +++#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +++#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset +++ to GOT entry for IE symbol */ +++#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ +++#define R_X86_64_PC64 24 /* PC relative 64 bit */ +++#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ +++#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative +++ offset to GOT */ +++#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ +++#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset +++ to GOT entry */ +++#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ +++#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ +++#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset +++ to PLT entry */ +++#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ +++#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ +++#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +++#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS +++ descriptor. */ +++#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +++#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ +++#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ +++ +++#define R_X86_64_NUM 39 +++ +++ +++/* AM33 relocations. */ +++#define R_MN10300_NONE 0 /* No reloc. */ +++#define R_MN10300_32 1 /* Direct 32 bit. */ +++#define R_MN10300_16 2 /* Direct 16 bit. */ +++#define R_MN10300_8 3 /* Direct 8 bit. */ +++#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ +++#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ +++#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ +++#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ +++#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ +++#define R_MN10300_24 9 /* Direct 24 bit. */ +++#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ +++#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ +++#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ +++#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ +++#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ +++#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ +++#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ +++#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ +++#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ +++#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ +++#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ +++#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ +++#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ +++#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ +++ +++#define R_MN10300_NUM 24 +++ +++ +++/* M32R relocs. */ +++#define R_M32R_NONE 0 /* No reloc. */ +++#define R_M32R_16 1 /* Direct 16 bit. */ +++#define R_M32R_32 2 /* Direct 32 bit. */ +++#define R_M32R_24 3 /* Direct 24 bit. */ +++#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ +++#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ +++#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ +++#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ +++#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ +++#define R_M32R_LO16 9 /* Low 16 bit. */ +++#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ +++#define R_M32R_GNU_VTINHERIT 11 +++#define R_M32R_GNU_VTENTRY 12 +++/* M32R relocs use SHT_RELA. */ +++#define R_M32R_16_RELA 33 /* Direct 16 bit. */ +++#define R_M32R_32_RELA 34 /* Direct 32 bit. */ +++#define R_M32R_24_RELA 35 /* Direct 24 bit. */ +++#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ +++#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ +++#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ +++#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ +++#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ +++#define R_M32R_LO16_RELA 41 /* Low 16 bit */ +++#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ +++#define R_M32R_RELA_GNU_VTINHERIT 43 +++#define R_M32R_RELA_GNU_VTENTRY 44 +++#define R_M32R_REL32 45 /* PC relative 32 bit. */ +++ +++#define R_M32R_GOT24 48 /* 24 bit GOT entry */ +++#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ +++#define R_M32R_COPY 50 /* Copy symbol at runtime */ +++#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ +++#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ +++#define R_M32R_RELATIVE 53 /* Adjust by program base */ +++#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ +++#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ +++#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned +++ low */ +++#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed +++ low */ +++#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ +++#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to +++ GOT with unsigned low */ +++#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to +++ GOT with signed low */ +++#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to +++ GOT */ +++#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT +++ with unsigned low */ +++#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT +++ with signed low */ +++#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ +++#define R_M32R_NUM 256 /* Keep this the last entry. */ +++ +++ +++/* TILEPro relocations. */ +++#define R_TILEPRO_NONE 0 /* No reloc */ +++#define R_TILEPRO_32 1 /* Direct 32 bit */ +++#define R_TILEPRO_16 2 /* Direct 16 bit */ +++#define R_TILEPRO_8 3 /* Direct 8 bit */ +++#define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */ +++#define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */ +++#define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */ +++#define R_TILEPRO_LO16 7 /* Low 16 bit */ +++#define R_TILEPRO_HI16 8 /* High 16 bit */ +++#define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */ +++#define R_TILEPRO_COPY 10 /* Copy relocation */ +++#define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */ +++#define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */ +++#define R_TILEPRO_RELATIVE 13 /* Adjust by program base */ +++#define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */ +++#define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */ +++#define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */ +++#define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */ +++#define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */ +++#define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */ +++#define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */ +++#define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */ +++#define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */ +++#define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */ +++#define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */ +++#define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */ +++#define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */ +++#define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */ +++#define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */ +++#define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */ +++#define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */ +++#define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */ +++#define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */ +++#define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */ +++#define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */ +++#define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */ +++#define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */ +++#define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */ +++#define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */ +++#define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */ +++#define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */ +++#define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */ +++#define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */ +++#define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */ +++#define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */ +++#define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */ +++#define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */ +++#define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */ +++#define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */ +++#define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */ +++#define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */ +++#define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */ +++#define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */ +++#define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */ +++#define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */ +++#define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */ +++/* Relocs 56-59 are currently not defined. */ +++#define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */ +++#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */ +++#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */ +++#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */ +++#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */ +++#define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */ +++#define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */ +++#define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */ +++#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */ +++#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */ +++#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */ +++#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */ +++#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */ +++#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */ +++#define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */ +++#define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */ +++#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */ +++#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */ +++#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */ +++#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */ +++#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */ +++#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */ +++#define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */ +++#define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */ +++#define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */ +++#define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */ +++#define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */ +++#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */ +++#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */ +++#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */ +++#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */ +++#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */ +++#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */ +++ +++#define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ +++#define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ +++ +++#define R_TILEPRO_NUM 130 +++ +++ +++/* TILE-Gx relocations. */ +++#define R_TILEGX_NONE 0 /* No reloc */ +++#define R_TILEGX_64 1 /* Direct 64 bit */ +++#define R_TILEGX_32 2 /* Direct 32 bit */ +++#define R_TILEGX_16 3 /* Direct 16 bit */ +++#define R_TILEGX_8 4 /* Direct 8 bit */ +++#define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */ +++#define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */ +++#define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */ +++#define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */ +++#define R_TILEGX_HW0 9 /* hword 0 16-bit */ +++#define R_TILEGX_HW1 10 /* hword 1 16-bit */ +++#define R_TILEGX_HW2 11 /* hword 2 16-bit */ +++#define R_TILEGX_HW3 12 /* hword 3 16-bit */ +++#define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */ +++#define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */ +++#define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */ +++#define R_TILEGX_COPY 16 /* Copy relocation */ +++#define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */ +++#define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */ +++#define R_TILEGX_RELATIVE 19 /* Adjust by program base */ +++#define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */ +++#define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */ +++#define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */ +++#define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */ +++#define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */ +++#define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */ +++#define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */ +++#define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */ +++#define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */ +++#define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */ +++#define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */ +++#define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */ +++#define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */ +++#define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */ +++#define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */ +++#define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */ +++#define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */ +++#define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */ +++#define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */ +++#define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */ +++#define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */ +++#define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */ +++#define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */ +++#define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */ +++#define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */ +++#define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */ +++#define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */ +++#define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */ +++#define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */ +++#define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */ +++#define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */ +++#define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */ +++#define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */ +++#define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */ +++#define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */ +++#define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */ +++#define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */ +++#define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */ +++#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */ +++#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */ +++#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */ +++#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */ +++#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */ +++#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */ +++#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */ +++#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */ +++/* Relocs 66-71 are currently not defined. */ +++#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */ +++#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */ +++#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */ +++#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */ +++/* Relocs 76-77 are currently not defined. */ +++#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */ +++#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */ +++#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */ +++#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */ +++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */ +++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */ +++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */ +++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */ +++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */ +++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */ +++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */ +++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */ +++/* Relocs 90-91 are currently not defined. */ +++#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */ +++#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */ +++/* Relocs 94-99 are currently not defined. */ +++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */ +++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */ +++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */ +++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */ +++/* Relocs 104-105 are currently not defined. */ +++#define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */ +++#define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */ +++#define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */ +++#define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */ +++#define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */ +++#define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */ +++#define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */ +++#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */ +++#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */ +++#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */ +++#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */ +++#define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */ +++#define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */ +++#define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */ +++#define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */ +++#define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */ +++ +++#define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ +++#define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ +++ +++#define R_TILEGX_NUM 130 +++ +++#endif /* elf.h */ ++--- a/scripts/mod/mk_elfconfig.c +++++ b/scripts/mod/mk_elfconfig.c ++@@ -2,7 +2,11 @@ ++ #include ++ #include ++ #include +++#ifndef __APPLE__ ++ #include +++#else +++#include "elf.h" +++#endif ++ ++ int ++ main(int argc, char **argv) ++--- a/scripts/mod/modpost.h +++++ b/scripts/mod/modpost.h ++@@ -8,7 +8,11 @@ ++ #include ++ #include ++ #include +++#if !(defined(__APPLE__) || defined(__CYGWIN__)) ++ #include +++#else +++#include "elf.h" +++#endif ++ ++ #include "elfconfig.h" ++ +diff --git a/target/linux/generic/hack-4.14/211-host_tools_portability.patch b/target/linux/generic/hack-4.14/211-host_tools_portability.patch +new file mode 100644 +index 0000000000..d806df8a5f +--- /dev/null ++++ b/target/linux/generic/hack-4.14/211-host_tools_portability.patch +@@ -0,0 +1,40 @@ ++From 7f698012384ccb1ed10cc758acfd085096fdb307 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:02:03 +0200 ++Subject: kernel: fix linux 4.9 host tools portability issues ++ ++Signed-off-by: Felix Fietkau ++--- ++ tools/build/Build.include | 2 +- ++ tools/perf/pmu-events/jevents.c | 1 + ++ tools/perf/pmu-events/json.c | 1 - ++ 3 files changed, 2 insertions(+), 2 deletions(-) ++ ++--- a/tools/build/Build.include +++++ b/tools/build/Build.include ++@@ -98,4 +98,4 @@ cxx_flags = -Wp,-MD,$(depfile) -Wp,-MT,$ ++ ### ++ ## HOSTCC C flags ++ ++-host_c_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj)) +++host_c_flags = -MD -MF $(depfile) -MT $@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj)) ++--- a/tools/perf/pmu-events/jevents.c +++++ b/tools/perf/pmu-events/jevents.c ++@@ -35,6 +35,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++--- a/tools/perf/pmu-events/json.c +++++ b/tools/perf/pmu-events/json.c ++@@ -38,7 +38,6 @@ ++ #include ++ #include "jsmn.h" ++ #include "json.h" ++-#include ++ ++ ++ static char *mapfile(const char *fn, size_t *size) +diff --git a/target/linux/generic/hack-4.14/212-byteshift_portability.patch b/target/linux/generic/hack-4.14/212-byteshift_portability.patch +new file mode 100644 +index 0000000000..1a5ac87988 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/212-byteshift_portability.patch +@@ -0,0 +1,65 @@ ++From 48232d3d931c95953ce2ddfe7da7bb164aef6a73 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:03:16 +0200 ++Subject: linux-3.6: fix portability of some includes files in tools/ used on the host ++ ++lede-commit: 6040b1d29ab1f047c5e49b748abcb6a3196add28 ++Signed-off-by: Felix Fietkau ++--- ++ tools/include/tools/be_byteshift.h | 4 ++++ ++ tools/include/tools/le_byteshift.h | 4 ++++ ++ tools/include/tools/linux_types.h | 22 ++++++++++++++++++++++ ++ 3 files changed, 30 insertions(+) ++ create mode 100644 tools/include/tools/linux_types.h ++ ++--- a/tools/include/tools/be_byteshift.h +++++ b/tools/include/tools/be_byteshift.h ++@@ -2,6 +2,10 @@ ++ #ifndef _TOOLS_BE_BYTESHIFT_H ++ #define _TOOLS_BE_BYTESHIFT_H ++ +++#ifndef __linux__ +++#include "linux_types.h" +++#endif +++ ++ #include ++ ++ static inline uint16_t __get_unaligned_be16(const uint8_t *p) ++--- a/tools/include/tools/le_byteshift.h +++++ b/tools/include/tools/le_byteshift.h ++@@ -2,6 +2,10 @@ ++ #ifndef _TOOLS_LE_BYTESHIFT_H ++ #define _TOOLS_LE_BYTESHIFT_H ++ +++#ifndef __linux__ +++#include "linux_types.h" +++#endif +++ ++ #include ++ ++ static inline uint16_t __get_unaligned_le16(const uint8_t *p) ++--- /dev/null +++++ b/tools/include/tools/linux_types.h ++@@ -0,0 +1,22 @@ +++#ifndef __LINUX_TYPES_H +++#define __LINUX_TYPES_H +++ +++#include +++ +++typedef uint8_t __u8; +++typedef uint8_t __be8; +++typedef uint8_t __le8; +++ +++typedef uint16_t __u16; +++typedef uint16_t __be16; +++typedef uint16_t __le16; +++ +++typedef uint32_t __u32; +++typedef uint32_t __be32; +++typedef uint32_t __le32; +++ +++typedef uint64_t __u64; +++typedef uint64_t __be64; +++typedef uint64_t __le64; +++ +++#endif +diff --git a/target/linux/generic/hack-4.14/214-spidev_h_portability.patch b/target/linux/generic/hack-4.14/214-spidev_h_portability.patch +new file mode 100644 +index 0000000000..093f600c85 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/214-spidev_h_portability.patch +@@ -0,0 +1,24 @@ ++From be9be95ff10e16a5b4ad36f903978d0cc5747024 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:04:08 +0200 ++Subject: kernel: fix linux/spi/spidev.h portability issues with musl ++ ++Felix will try to get this define included into musl ++ ++lede-commit: 795e7cf60de19e7a076a46874fab7bb88b43bbff ++Signed-off-by: Felix Fietkau ++--- ++ include/uapi/linux/spi/spidev.h | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/include/uapi/linux/spi/spidev.h +++++ b/include/uapi/linux/spi/spidev.h ++@@ -113,7 +113,7 @@ struct spi_ioc_transfer { ++ ++ /* not all platforms use or _IOC_TYPECHECK() ... */ ++ #define SPI_MSGSIZE(N) \ ++- ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ +++ ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << 13)) \ ++ ? ((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-4.14/220-gc_sections.patch b/target/linux/generic/hack-4.14/220-gc_sections.patch +new file mode 100644 +index 0000000000..6a4475fc6e +--- /dev/null ++++ b/target/linux/generic/hack-4.14/220-gc_sections.patch +@@ -0,0 +1,258 @@ ++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/Makefile +++++ b/Makefile ++@@ -272,6 +272,11 @@ else ++ scripts/Kbuild.include: ; ++ include scripts/Kbuild.include ++ +++ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION +++KBUILD_CFLAGS_KERNEL += $(call cc-option,-ffunction-sections,) +++KBUILD_CFLAGS_KERNEL += $(call cc-option,-fdata-sections,) +++endif +++ ++ # Read KERNELRELEASE from include/config/kernel.release (if it exists) ++ KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) ++ KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) ++@@ -779,11 +784,6 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH ++ KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once) ++ endif ++ ++-ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION ++-KBUILD_CFLAGS += $(call cc-option,-ffunction-sections,) ++-KBUILD_CFLAGS += $(call cc-option,-fdata-sections,) ++-endif ++- ++ # arch Makefile may override CC so keep this after arch Makefile is included ++ NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) ++ CHECKFLAGS += $(NOSTDINC_FLAGS) ++--- a/arch/arm/Kconfig +++++ b/arch/arm/Kconfig ++@@ -91,6 +91,7 @@ config ARM ++ select HAVE_UID16 ++ select HAVE_VIRT_CPU_ACCOUNTING_GEN ++ select IRQ_FORCED_THREADING +++ select LD_DEAD_CODE_DATA_ELIMINATION ++ select MODULES_USE_ELF_REL ++ select NO_BOOTMEM ++ select OF_EARLY_FLATTREE if OF ++--- a/arch/arm/boot/compressed/Makefile +++++ b/arch/arm/boot/compressed/Makefile ++@@ -103,6 +103,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 ++@@ -18,7 +18,7 @@ ++ #define PROC_INFO \ ++ . = ALIGN(4); \ ++ VMLINUX_SYMBOL(__proc_info_begin) = .; \ ++- *(.proc.info.init) \ +++ KEEP(*(.proc.info.init)) \ ++ VMLINUX_SYMBOL(__proc_info_end) = .; ++ ++ #define HYPERVISOR_TEXT \ ++@@ -29,11 +29,11 @@ ++ #define IDMAP_TEXT \ ++ ALIGN_FUNCTION(); \ ++ VMLINUX_SYMBOL(__idmap_text_start) = .; \ ++- *(.idmap.text) \ +++ KEEP(*(.idmap.text)) \ ++ VMLINUX_SYMBOL(__idmap_text_end) = .; \ ++ . = ALIGN(PAGE_SIZE); \ ++ VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \ ++- *(.hyp.idmap.text) \ +++ KEEP(*(.hyp.idmap.text)) \ ++ VMLINUX_SYMBOL(__hyp_idmap_text_end) = .; ++ ++ #ifdef CONFIG_HOTPLUG_CPU ++@@ -106,7 +106,7 @@ SECTIONS ++ _stext = .; /* Text and read-only data */ ++ IDMAP_TEXT ++ __exception_text_start = .; ++- *(.exception.text) +++ KEEP(*(.exception.text)) ++ __exception_text_end = .; ++ IRQENTRY_TEXT ++ SOFTIRQENTRY_TEXT ++@@ -135,7 +135,7 @@ SECTIONS ++ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { ++ __start___ex_table = .; ++ #ifdef CONFIG_MMU ++- *(__ex_table) +++ KEEP(*(__ex_table)) ++ #endif ++ __stop___ex_table = .; ++ } ++@@ -147,12 +147,12 @@ SECTIONS ++ . = 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 = .; ++ } ++ #endif ++@@ -172,14 +172,14 @@ SECTIONS ++ */ ++ __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 = .; ++@@ -195,24 +195,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 = .; ++ } ++ .init.data : { ++--- a/arch/mips/Kconfig +++++ b/arch/mips/Kconfig ++@@ -40,6 +40,7 @@ config MIPS ++ select HAVE_CBPF_JIT if (!64BIT && !CPU_MICROMIPS) ++ select HAVE_EBPF_JIT if (64BIT && !CPU_MICROMIPS) ++ select HAVE_CC_STACKPROTECTOR +++ select LD_DEAD_CODE_DATA_ELIMINATION ++ select HAVE_CONTEXT_TRACKING ++ select HAVE_COPY_THREAD_TLS ++ select HAVE_C_RECORDMCOUNT ++--- a/arch/mips/kernel/vmlinux.lds.S +++++ b/arch/mips/kernel/vmlinux.lds.S ++@@ -72,7 +72,7 @@ SECTIONS ++ /* Exception table for data bus errors */ ++ __dbe_table : { ++ __start___dbe_table = .; ++- *(__dbe_table) +++ KEEP(*(__dbe_table)) ++ __stop___dbe_table = .; ++ } ++ ++@@ -123,7 +123,7 @@ SECTIONS ++ . = ALIGN(4); ++ .mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) { ++ __mips_machines_start = .; ++- *(.mips.machines.init) +++ KEEP(*(.mips.machines.init)) ++ __mips_machines_end = .; ++ } ++ ++--- a/include/asm-generic/vmlinux.lds.h +++++ b/include/asm-generic/vmlinux.lds.h ++@@ -105,7 +105,7 @@ ++ #ifdef CONFIG_FTRACE_MCOUNT_RECORD ++ #define MCOUNT_REC() . = ALIGN(8); \ ++ VMLINUX_SYMBOL(__start_mcount_loc) = .; \ ++- *(__mcount_loc) \ +++ KEEP(*(__mcount_loc)) \ ++ VMLINUX_SYMBOL(__stop_mcount_loc) = .; ++ #else ++ #define MCOUNT_REC() ++@@ -113,7 +113,7 @@ ++ ++ #ifdef CONFIG_TRACE_BRANCH_PROFILING ++ #define LIKELY_PROFILE() VMLINUX_SYMBOL(__start_annotated_branch_profile) = .; \ ++- *(_ftrace_annotated_branch) \ +++ KEEP(*(_ftrace_annotated_branch)) \ ++ VMLINUX_SYMBOL(__stop_annotated_branch_profile) = .; ++ #else ++ #define LIKELY_PROFILE() ++@@ -121,7 +121,7 @@ ++ ++ #ifdef CONFIG_PROFILE_ALL_BRANCHES ++ #define BRANCH_PROFILE() VMLINUX_SYMBOL(__start_branch_profile) = .; \ ++- *(_ftrace_branch) \ +++ KEEP(*(_ftrace_branch)) \ ++ VMLINUX_SYMBOL(__stop_branch_profile) = .; ++ #else ++ #define BRANCH_PROFILE() ++@@ -237,7 +237,8 @@ ++ LIKELY_PROFILE() \ ++ BRANCH_PROFILE() \ ++ TRACE_PRINTKS() \ ++- TRACEPOINT_STR() +++ TRACEPOINT_STR() \ +++ *(.data.[a-zA-Z_]*) ++ ++ /* ++ * Data section helpers ++@@ -497,7 +498,7 @@ ++ #define ENTRY_TEXT \ ++ ALIGN_FUNCTION(); \ ++ VMLINUX_SYMBOL(__entry_text_start) = .; \ ++- *(.entry.text) \ +++ KEEP(*(.entry.text)) \ ++ VMLINUX_SYMBOL(__entry_text_end) = .; ++ ++ #define IRQENTRY_TEXT \ ++@@ -604,7 +605,7 @@ ++ . = ALIGN(sbss_align); \ ++ .sbss : AT(ADDR(.sbss) - LOAD_OFFSET) { \ ++ *(.dynsbss) \ ++- *(.sbss) \ +++ *(.sbss .sbss.*) \ ++ *(.scommon) \ ++ } ++ +diff --git a/target/linux/generic/hack-4.14/221-module_exports.patch b/target/linux/generic/hack-4.14/221-module_exports.patch +new file mode 100644 +index 0000000000..003175c223 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/221-module_exports.patch +@@ -0,0 +1,101 @@ ++From b14784e7883390c20ed3ff904892255404a5914b Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:05:53 +0200 ++Subject: add an optional config option for stripping all unnecessary symbol exports from the kernel image ++ ++lede-commit: bb5a40c64b7c4f4848509fa0a6625055fc9e66cc ++Signed-off-by: Felix Fietkau ++--- ++ include/asm-generic/vmlinux.lds.h | 18 +++++++++++++++--- ++ include/linux/export.h | 9 ++++++++- ++ scripts/Makefile.build | 2 +- ++ 3 files changed, 24 insertions(+), 5 deletions(-) ++ ++--- a/include/asm-generic/vmlinux.lds.h +++++ b/include/asm-generic/vmlinux.lds.h ++@@ -54,6 +54,16 @@ ++ #define LOAD_OFFSET 0 ++ #endif ++ +++#ifndef SYMTAB_KEEP +++#define SYMTAB_KEEP KEEP(*(SORT(___ksymtab+*))) +++#define SYMTAB_KEEP_GPL KEEP(*(SORT(___ksymtab_gpl+*))) +++#endif +++ +++#ifndef SYMTAB_DISCARD +++#define SYMTAB_DISCARD +++#define SYMTAB_DISCARD_GPL +++#endif +++ ++ #include ++ ++ /* Align . to a 8 byte boundary equals to maximum function alignment. */ ++@@ -342,14 +352,14 @@ ++ /* Kernel symbol table: Normal symbols */ \ ++ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ ++ VMLINUX_SYMBOL(__start___ksymtab) = .; \ ++- KEEP(*(SORT(___ksymtab+*))) \ +++ SYMTAB_KEEP \ ++ VMLINUX_SYMBOL(__stop___ksymtab) = .; \ ++ } \ ++ \ ++ /* Kernel symbol table: GPL-only symbols */ \ ++ __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \ ++ VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \ ++- KEEP(*(SORT(___ksymtab_gpl+*))) \ +++ SYMTAB_KEEP_GPL \ ++ VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ ++ } \ ++ \ ++@@ -411,7 +421,7 @@ ++ \ ++ /* Kernel symbol table: strings */ \ ++ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ ++- *(__ksymtab_strings) \ +++ *(__ksymtab_strings+*) \ ++ } \ ++ \ ++ /* __*init sections */ \ ++@@ -796,6 +806,8 @@ ++ EXIT_TEXT \ ++ EXIT_DATA \ ++ EXIT_CALL \ +++ SYMTAB_DISCARD \ +++ SYMTAB_DISCARD_GPL \ ++ *(.discard) \ ++ *(.discard.*) \ ++ } ++--- a/include/linux/export.h +++++ b/include/linux/export.h ++@@ -60,12 +60,19 @@ extern struct module __this_module; ++ #define __CRC_SYMBOL(sym, sec) ++ #endif ++ +++#ifdef MODULE +++#define __EXPORT_SUFFIX(sym) +++#else +++#define __EXPORT_SUFFIX(sym) "+" #sym +++#endif +++ ++ /* For every exported symbol, place a struct in the __ksymtab section */ ++ #define ___EXPORT_SYMBOL(sym, sec) \ ++ extern typeof(sym) sym; \ ++ __CRC_SYMBOL(sym, sec) \ ++ static const char __kstrtab_##sym[] \ ++- __attribute__((section("__ksymtab_strings"), aligned(1))) \ +++ __attribute__((section("__ksymtab_strings" \ +++ __EXPORT_SUFFIX(sym)), aligned(1))) \ ++ = VMLINUX_SYMBOL_STR(sym); \ ++ static const struct kernel_symbol __ksymtab_##sym \ ++ __used \ ++--- a/scripts/Makefile.build +++++ b/scripts/Makefile.build ++@@ -432,7 +432,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $( ++ # Linker scripts preprocessor (.lds.S -> .lds) ++ # --------------------------------------------------------------------------- ++ quiet_cmd_cpp_lds_S = LDS $@ ++- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \ +++ cmd_cpp_lds_S = $(CPP) $(EXTRA_LDSFLAGS) $(cpp_flags) -P -U$(ARCH) \ ++ -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $< ++ ++ $(obj)/%.lds: $(src)/%.lds.S FORCE +diff --git a/target/linux/generic/hack-4.14/230-openwrt_lzma_options.patch b/target/linux/generic/hack-4.14/230-openwrt_lzma_options.patch +new file mode 100644 +index 0000000000..3ae578c271 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/230-openwrt_lzma_options.patch +@@ -0,0 +1,71 @@ ++From b3d00b452467f621317953d9e4c6f9ae8dcfd271 Mon Sep 17 00:00:00 2001 ++From: Imre Kaloz ++Date: Fri, 7 Jul 2017 17:06:55 +0200 ++Subject: use the openwrt lzma options for now ++ ++lede-commit: 548de949f392049420a6a1feeef118b30ab8ea8c ++Signed-off-by: Imre Kaloz ++--- ++ lib/decompress.c | 1 + ++ scripts/Makefile.lib | 2 +- ++ scripts/gen_initramfs_list.sh | 10 +++++----- ++ 3 files changed, 7 insertions(+), 6 deletions(-) ++ ++--- a/lib/decompress.c +++++ b/lib/decompress.c ++@@ -49,6 +49,7 @@ static const struct compress_format comp ++ { {0x1f, 0x9e}, "gzip", gunzip }, ++ { {0x42, 0x5a}, "bzip2", bunzip2 }, ++ { {0x5d, 0x00}, "lzma", unlzma }, +++ { {0x6d, 0x00}, "lzma-openwrt", unlzma }, ++ { {0xfd, 0x37}, "xz", unxz }, ++ { {0x89, 0x4c}, "lzo", unlzo }, ++ { {0x02, 0x21}, "lz4", unlz4 }, ++--- a/scripts/Makefile.lib +++++ b/scripts/Makefile.lib ++@@ -348,7 +348,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) ++ ++ quiet_cmd_lzma = LZMA $@ ++ cmd_lzma = (cat $(filter-out FORCE,$^) | \ ++- lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ +++ lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ ++ (rm -f $@ ; false) ++ ++ quiet_cmd_lzo = LZO $@ ++--- a/scripts/gen_initramfs_list.sh +++++ b/scripts/gen_initramfs_list.sh ++@@ -229,7 +229,7 @@ cpio_list= ++ output="/dev/stdout" ++ output_file="" ++ is_cpio_compressed= ++-compr="gzip -n -9 -f" +++compr="gzip -n -9 -f -" ++ ++ arg="$1" ++ case "$arg" in ++@@ -245,13 +245,13 @@ case "$arg" in ++ output=${cpio_list} ++ echo "$output_file" | grep -q "\.gz$" \ ++ && [ -x "`which gzip 2> /dev/null`" ] \ ++- && compr="gzip -n -9 -f" +++ && compr="gzip -n -9 -f -" ++ echo "$output_file" | grep -q "\.bz2$" \ ++ && [ -x "`which bzip2 2> /dev/null`" ] \ ++- && compr="bzip2 -9 -f" +++ && compr="bzip2 -9 -f -" ++ echo "$output_file" | grep -q "\.lzma$" \ ++ && [ -x "`which lzma 2> /dev/null`" ] \ ++- && compr="lzma -9 -f" +++ && compr="lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so" ++ echo "$output_file" | grep -q "\.xz$" \ ++ && [ -x "`which xz 2> /dev/null`" ] \ ++ && compr="xz --check=crc32 --lzma2=dict=1MiB" ++@@ -320,7 +320,7 @@ if [ ! -z ${output_file} ]; then ++ if [ "${is_cpio_compressed}" = "compressed" ]; then ++ cat ${cpio_tfile} > ${output_file} ++ else ++- (cat ${cpio_tfile} | ${compr} - > ${output_file}) \ +++ (cat ${cpio_tfile} | ${compr} > ${output_file}) \ ++ || (rm -f ${output_file} ; false) ++ fi ++ [ -z ${cpio_file} ] && rm ${cpio_tfile} +diff --git a/target/linux/generic/hack-4.14/250-netfilter_depends.patch b/target/linux/generic/hack-4.14/250-netfilter_depends.patch +new file mode 100644 +index 0000000000..a8fe5d4175 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/250-netfilter_depends.patch +@@ -0,0 +1,27 @@ ++From: Felix Fietkau ++Subject: hack: net: remove bogus netfilter dependencies ++ ++lede-commit: 589d2a377dee27d206fc3725325309cf649e4df6 ++Signed-off-by: Felix Fietkau ++--- ++ net/netfilter/Kconfig | 2 -- ++ 1 file changed, 2 deletions(-) ++ ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -229,7 +229,6 @@ config NF_CONNTRACK_FTP ++ ++ config NF_CONNTRACK_H323 ++ tristate "H.323 protocol support" ++- depends on IPV6 || IPV6=n ++ depends on NETFILTER_ADVANCED ++ help ++ H.323 is a VoIP signalling protocol from ITU-T. As one of the most ++@@ -1052,7 +1051,6 @@ config NETFILTER_XT_TARGET_SECMARK ++ ++ config NETFILTER_XT_TARGET_TCPMSS ++ tristate '"TCPMSS" target support' ++- depends on IPV6 || IPV6=n ++ default m if NETFILTER_ADVANCED=n ++ ---help--- ++ This option adds a `TCPMSS' target, which allows you to alter the +diff --git a/target/linux/generic/hack-4.14/251-sound_kconfig.patch b/target/linux/generic/hack-4.14/251-sound_kconfig.patch +new file mode 100644 +index 0000000000..5bf5c01ad3 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/251-sound_kconfig.patch +@@ -0,0 +1,197 @@ ++From da3c50704f14132f4adf80d48e9a4cd5d46e54c9 Mon Sep 17 00:00:00 2001 ++From: John Crispin ++Date: Fri, 7 Jul 2017 17:09:21 +0200 ++Subject: kconfig: owrt specifc dependencies ++ ++Signed-off-by: John Crispin ++--- ++ crypto/Kconfig | 10 +++++----- ++ drivers/bcma/Kconfig | 1 + ++ drivers/ssb/Kconfig | 3 ++- ++ lib/Kconfig | 8 ++++---- ++ net/netfilter/Kconfig | 2 +- ++ net/wireless/Kconfig | 17 ++++++++++------- ++ sound/core/Kconfig | 4 ++-- ++ 7 files changed, 25 insertions(+), 20 deletions(-) ++ ++--- a/crypto/Kconfig +++++ b/crypto/Kconfig ++@@ -33,7 +33,7 @@ config CRYPTO_FIPS ++ this is. ++ ++ config CRYPTO_ALGAPI ++- tristate +++ tristate "ALGAPI" ++ select CRYPTO_ALGAPI2 ++ help ++ This option provides the API for cryptographic algorithms. ++@@ -42,7 +42,7 @@ config CRYPTO_ALGAPI2 ++ tristate ++ ++ config CRYPTO_AEAD ++- tristate +++ tristate "AEAD" ++ select CRYPTO_AEAD2 ++ select CRYPTO_ALGAPI ++ ++@@ -53,7 +53,7 @@ config CRYPTO_AEAD2 ++ select CRYPTO_RNG2 ++ ++ config CRYPTO_BLKCIPHER ++- tristate +++ tristate "BLKCIPHER" ++ select CRYPTO_BLKCIPHER2 ++ select CRYPTO_ALGAPI ++ ++@@ -64,7 +64,7 @@ config CRYPTO_BLKCIPHER2 ++ select CRYPTO_WORKQUEUE ++ ++ config CRYPTO_HASH ++- tristate +++ tristate "HASH" ++ select CRYPTO_HASH2 ++ select CRYPTO_ALGAPI ++ ++@@ -73,7 +73,7 @@ config CRYPTO_HASH2 ++ select CRYPTO_ALGAPI2 ++ ++ config CRYPTO_RNG ++- tristate +++ tristate "RNG" ++ select CRYPTO_RNG2 ++ select CRYPTO_ALGAPI ++ ++--- a/drivers/bcma/Kconfig +++++ b/drivers/bcma/Kconfig ++@@ -15,6 +15,7 @@ menuconfig BCMA ++ config BCMA_BLOCKIO ++ bool ++ depends on BCMA +++ default y ++ ++ config BCMA_HOST_PCI_POSSIBLE ++ bool ++--- a/drivers/ssb/Kconfig +++++ b/drivers/ssb/Kconfig ++@@ -29,6 +29,7 @@ config SSB_SPROM ++ config SSB_BLOCKIO ++ bool ++ depends on SSB +++ default y ++ ++ config SSB_PCIHOST_POSSIBLE ++ bool ++@@ -49,7 +50,7 @@ config SSB_PCIHOST ++ config SSB_B43_PCI_BRIDGE ++ bool ++ depends on SSB_PCIHOST ++- default n +++ default y ++ ++ config SSB_PCMCIAHOST_POSSIBLE ++ bool ++--- a/lib/Kconfig +++++ b/lib/Kconfig ++@@ -358,16 +358,16 @@ config BCH_CONST_T ++ # Textsearch support is select'ed if needed ++ # ++ config TEXTSEARCH ++- bool +++ boolean "Textsearch support" ++ ++ config TEXTSEARCH_KMP ++- tristate +++ tristate "Textsearch KMP" ++ ++ config TEXTSEARCH_BM ++- tristate +++ tristate "Textsearch BM" ++ ++ config TEXTSEARCH_FSM ++- tristate +++ tristate "Textsearch FSM" ++ ++ config BTREE ++ bool ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -10,7 +10,7 @@ config NETFILTER_INGRESS ++ infrastructure. ++ ++ config NETFILTER_NETLINK ++- tristate +++ tristate "Netfilter NFNETLINK interface" ++ ++ config NETFILTER_FAMILY_BRIDGE ++ bool ++--- a/net/wireless/Kconfig +++++ b/net/wireless/Kconfig ++@@ -1,5 +1,5 @@ ++ config WIRELESS_EXT ++- bool +++ bool "Wireless extensions" ++ ++ config WEXT_CORE ++ def_bool y ++@@ -11,10 +11,10 @@ config WEXT_PROC ++ depends on WEXT_CORE ++ ++ config WEXT_SPY ++- bool +++ bool "WEXT_SPY" ++ ++ config WEXT_PRIV ++- bool +++ bool "WEXT_PRIV" ++ ++ config CFG80211 ++ tristate "cfg80211 - wireless configuration API" ++@@ -188,7 +188,7 @@ config CFG80211_WEXT_EXPORT ++ wext compatibility symbols to be exported. ++ ++ config LIB80211 ++- tristate +++ tristate "LIB80211" ++ default n ++ help ++ This options enables a library of common routines used ++@@ -197,13 +197,16 @@ config LIB80211 ++ Drivers should select this themselves if needed. ++ ++ config LIB80211_CRYPT_WEP ++- tristate +++ tristate "LIB80211_CRYPT_WEP" +++ select LIB80211 ++ ++ config LIB80211_CRYPT_CCMP ++- tristate +++ tristate "LIB80211_CRYPT_CCMP" +++ select LIB80211 ++ ++ config LIB80211_CRYPT_TKIP ++- tristate +++ tristate "LIB80211_CRYPT_TKIP" +++ select LIB80211 ++ ++ config LIB80211_DEBUG ++ bool "lib80211 debugging messages" ++--- a/sound/core/Kconfig +++++ b/sound/core/Kconfig ++@@ -16,7 +16,7 @@ config SND_DMAENGINE_PCM ++ tristate ++ ++ config SND_HWDEP ++- tristate +++ tristate "Sound hardware support" ++ ++ config SND_SEQ_DEVICE ++ tristate ++@@ -26,7 +26,7 @@ config SND_RAWMIDI ++ select SND_SEQ_DEVICE if SND_SEQUENCER != n ++ ++ config SND_COMPRESS_OFFLOAD ++- tristate +++ tristate "Compression offloading support" ++ ++ config SND_JACK ++ bool +diff --git a/target/linux/generic/hack-4.14/259-regmap_dynamic.patch b/target/linux/generic/hack-4.14/259-regmap_dynamic.patch +new file mode 100644 +index 0000000000..2cbd791b28 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/259-regmap_dynamic.patch +@@ -0,0 +1,105 @@ ++From 811d9e2268a62b830cfe93cd8bc929afcb8b198b Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sat, 15 Jul 2017 21:12:38 +0200 ++Subject: kernel: move regmap bloat out of the kernel image if it is only being used in modules ++ ++lede-commit: 96f39119815028073583e4fca3a9c5fe9141e998 ++Signed-off-by: Felix Fietkau ++--- ++ drivers/base/regmap/Kconfig | 15 ++++++++++----- ++ drivers/base/regmap/Makefile | 12 ++++++++---- ++ drivers/base/regmap/regmap.c | 3 +++ ++ include/linux/regmap.h | 2 +- ++ 4 files changed, 22 insertions(+), 10 deletions(-) ++ ++--- a/drivers/base/regmap/Kconfig +++++ b/drivers/base/regmap/Kconfig ++@@ -4,9 +4,8 @@ ++ # subsystems should select the appropriate symbols. ++ ++ config REGMAP ++- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ) ++ select IRQ_DOMAIN if REGMAP_IRQ ++- bool +++ tristate ++ ++ config REGCACHE_COMPRESSED ++ select LZO_COMPRESS ++@@ -18,22 +17,29 @@ config REGMAP_AC97 ++ ++ config REGMAP_I2C ++ tristate +++ select REGMAP ++ depends on I2C ++ ++ config REGMAP_SPI ++ tristate +++ select REGMAP +++ depends on SPI_MASTER ++ depends on SPI ++ ++ config REGMAP_SPMI +++ select REGMAP ++ tristate ++ depends on SPMI ++ ++ config REGMAP_W1 +++ select REGMAP ++ tristate ++ depends on W1 ++ ++ config REGMAP_MMIO ++ tristate +++ select REGMAP ++ ++ config REGMAP_IRQ +++ select REGMAP ++ bool ++--- a/drivers/base/regmap/Makefile +++++ b/drivers/base/regmap/Makefile ++@@ -2,10 +2,14 @@ ++ # For include/trace/define_trace.h to include trace.h ++ CFLAGS_regmap.o := -I$(src) ++ ++-obj-$(CONFIG_REGMAP) += regmap.o regcache.o ++-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-flat.o ++-obj-$(CONFIG_REGCACHE_COMPRESSED) += regcache-lzo.o ++-obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o +++regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-flat.o +++ifdef CONFIG_DEBUG_FS +++regmap-core-objs += regmap-debugfs.o +++endif +++ifdef CONFIG_REGCACHE_COMPRESSED +++regmap-core-objs += regcache-lzo.o +++endif +++obj-$(CONFIG_REGMAP) += regmap-core.o ++ obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o ++ obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o ++ obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o ++--- a/drivers/base/regmap/regmap.c +++++ b/drivers/base/regmap/regmap.c ++@@ -13,6 +13,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -2928,3 +2929,5 @@ static int __init regmap_initcall(void) ++ return 0; ++ } ++ postcore_initcall(regmap_initcall); +++ +++MODULE_LICENSE("GPL"); ++--- a/include/linux/regmap.h +++++ b/include/linux/regmap.h ++@@ -139,7 +139,7 @@ struct reg_sequence { ++ pollret ?: ((cond) ? 0 : -ETIMEDOUT); \ ++ }) ++ ++-#ifdef CONFIG_REGMAP +++#if IS_REACHABLE(CONFIG_REGMAP) ++ ++ enum regmap_endian { ++ /* Unspecified -> 0 -> Backwards compatible default */ +diff --git a/target/linux/generic/hack-4.14/260-crypto_test_dependencies.patch b/target/linux/generic/hack-4.14/260-crypto_test_dependencies.patch +new file mode 100644 +index 0000000000..3cdc0973ec +--- /dev/null ++++ b/target/linux/generic/hack-4.14/260-crypto_test_dependencies.patch +@@ -0,0 +1,60 @@ ++From fd1799b0bf5efa46dd3e6dfbbf3955564807e508 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:12:51 +0200 ++Subject: kernel: prevent cryptomgr from pulling in useless extra dependencies for tests that are not run ++ ++Reduces kernel size after LZMA by about 5k on MIPS ++ ++lede-commit: 044c316167e076479a344c59905e5b435b84a77f ++Signed-off-by: Felix Fietkau ++--- ++ crypto/Kconfig | 13 ++++++------- ++ crypto/algboss.c | 4 ++++ ++ 2 files changed, 10 insertions(+), 7 deletions(-) ++ ++--- a/crypto/Kconfig +++++ b/crypto/Kconfig ++@@ -143,13 +143,13 @@ config CRYPTO_MANAGER ++ cbc(aes). ++ ++ config CRYPTO_MANAGER2 ++- def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y) ++- select CRYPTO_AEAD2 ++- select CRYPTO_HASH2 ++- select CRYPTO_BLKCIPHER2 ++- select CRYPTO_AKCIPHER2 ++- select CRYPTO_KPP2 ++- select CRYPTO_ACOMP2 +++ def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y && !CRYPTO_MANAGER_DISABLE_TESTS) +++ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS +++ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS +++ select CRYPTO_BLKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS +++ select CRYPTO_AKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS +++ select CRYPTO_KPP2 if !CRYPTO_MANAGER_DISABLE_TESTS +++ select CRYPTO_ACOMP2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ ++ config CRYPTO_USER ++ tristate "Userspace cryptographic algorithm configuration" ++@@ -162,7 +162,6 @@ config CRYPTO_USER ++ config CRYPTO_MANAGER_DISABLE_TESTS ++ bool "Disable run-time self tests" ++ default y ++- depends on CRYPTO_MANAGER2 ++ help ++ Disable run-time self tests that normally take place at ++ algorithm registration. ++--- a/crypto/algboss.c +++++ b/crypto/algboss.c ++@@ -246,8 +246,12 @@ static int cryptomgr_schedule_test(struc ++ type = alg->cra_flags; ++ ++ /* Do not test internal algorithms. */ +++#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS +++ type |= CRYPTO_ALG_TESTED; +++#else ++ if (type & CRYPTO_ALG_INTERNAL) ++ type |= CRYPTO_ALG_TESTED; +++#endif ++ ++ param->type = type; ++ +diff --git a/target/linux/generic/hack-4.14/280-rfkill-stubs.patch b/target/linux/generic/hack-4.14/280-rfkill-stubs.patch +new file mode 100644 +index 0000000000..85d01a6d10 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/280-rfkill-stubs.patch +@@ -0,0 +1,84 @@ ++From 236c1acdfef5958010ac9814a9872e0a46fd78ee Mon Sep 17 00:00:00 2001 ++From: John Crispin ++Date: Fri, 7 Jul 2017 17:13:44 +0200 ++Subject: rfkill: add fake rfkill support ++ ++allow building of modules depending on RFKILL even if RFKILL is not enabled. ++ ++Signed-off-by: John Crispin ++--- ++ include/linux/rfkill.h | 2 +- ++ net/Makefile | 2 +- ++ net/rfkill/Kconfig | 14 +++++++++----- ++ net/rfkill/Makefile | 2 +- ++ 4 files changed, 12 insertions(+), 8 deletions(-) ++ ++--- a/include/linux/rfkill.h +++++ b/include/linux/rfkill.h ++@@ -64,7 +64,7 @@ struct rfkill_ops { ++ int (*set_block)(void *data, bool blocked); ++ }; ++ ++-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) +++#if defined(CONFIG_RFKILL_FULL) || defined(CONFIG_RFKILL_FULL_MODULE) ++ /** ++ * rfkill_alloc - allocate rfkill structure ++ * @name: name of the struct -- the string is not copied internally ++--- a/net/Makefile +++++ b/net/Makefile ++@@ -53,7 +53,7 @@ obj-$(CONFIG_TIPC) += tipc/ ++ obj-$(CONFIG_NETLABEL) += netlabel/ ++ obj-$(CONFIG_IUCV) += iucv/ ++ obj-$(CONFIG_SMC) += smc/ ++-obj-$(CONFIG_RFKILL) += rfkill/ +++obj-$(CONFIG_RFKILL_FULL) += rfkill/ ++ obj-$(CONFIG_NET_9P) += 9p/ ++ obj-$(CONFIG_CAIF) += caif/ ++ ifneq ($(CONFIG_DCB),) ++--- a/net/rfkill/Kconfig +++++ b/net/rfkill/Kconfig ++@@ -1,7 +1,11 @@ ++ # ++ # RF switch subsystem configuration ++ # ++-menuconfig RFKILL +++config RFKILL +++ bool +++ default y +++ +++menuconfig RFKILL_FULL ++ tristate "RF switch subsystem support" ++ help ++ Say Y here if you want to have control over RF switches ++@@ -13,19 +17,19 @@ menuconfig RFKILL ++ # LED trigger support ++ config RFKILL_LEDS ++ bool ++- depends on RFKILL +++ depends on RFKILL_FULL ++ depends on LEDS_TRIGGERS = y || RFKILL = LEDS_TRIGGERS ++ default y ++ ++ config RFKILL_INPUT ++ bool "RF switch input support" if EXPERT ++- depends on RFKILL +++ depends on RFKILL_FULL ++ depends on INPUT = y || RFKILL = INPUT ++ default y if !EXPERT ++ ++ config RFKILL_GPIO ++ tristate "GPIO RFKILL driver" ++- depends on RFKILL +++ depends on RFKILL_FULL ++ depends on GPIOLIB || COMPILE_TEST ++ default n ++ help ++--- a/net/rfkill/Makefile +++++ b/net/rfkill/Makefile ++@@ -4,5 +4,5 @@ ++ ++ rfkill-y += core.o ++ rfkill-$(CONFIG_RFKILL_INPUT) += input.o ++-obj-$(CONFIG_RFKILL) += rfkill.o +++obj-$(CONFIG_RFKILL_FULL) += rfkill.o ++ obj-$(CONFIG_RFKILL_GPIO) += rfkill-gpio.o +diff --git a/target/linux/generic/hack-4.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch b/target/linux/generic/hack-4.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch +new file mode 100644 +index 0000000000..c07ccf9474 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch +@@ -0,0 +1,66 @@ ++From: Ben Menchaca ++Date: Fri, 7 Jun 2013 18:35:22 -0500 ++Subject: MIPS: r4k_cache: use more efficient cache blast ++ ++Optimize the compiler output for larger cache blast cases that are ++common for DMA-based networking. ++ ++Signed-off-by: Ben Menchaca ++Signed-off-by: Felix Fietkau ++--- ++--- a/arch/mips/include/asm/r4kcache.h +++++ b/arch/mips/include/asm/r4kcache.h ++@@ -683,16 +683,48 @@ static inline void prot##extra##blast_## ++ unsigned long end) \ ++ { \ ++ unsigned long lsize = cpu_##desc##_line_size(); \ +++ unsigned long lsize_2 = lsize * 2; \ +++ unsigned long lsize_3 = lsize * 3; \ +++ unsigned long lsize_4 = lsize * 4; \ +++ unsigned long lsize_5 = lsize * 5; \ +++ unsigned long lsize_6 = lsize * 6; \ +++ unsigned long lsize_7 = lsize * 7; \ +++ unsigned long lsize_8 = lsize * 8; \ ++ unsigned long addr = start & ~(lsize - 1); \ ++- unsigned long aend = (end - 1) & ~(lsize - 1); \ +++ unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \ +++ int lines = (aend - addr) / lsize; \ ++ \ ++ __##pfx##flush_prologue \ ++ \ ++- while (1) { \ +++ while (lines >= 8) { \ +++ prot##cache_op(hitop, addr); \ +++ prot##cache_op(hitop, addr + lsize); \ +++ prot##cache_op(hitop, addr + lsize_2); \ +++ prot##cache_op(hitop, addr + lsize_3); \ +++ prot##cache_op(hitop, addr + lsize_4); \ +++ prot##cache_op(hitop, addr + lsize_5); \ +++ prot##cache_op(hitop, addr + lsize_6); \ +++ prot##cache_op(hitop, addr + lsize_7); \ +++ addr += lsize_8; \ +++ lines -= 8; \ +++ } \ +++ \ +++ if (lines & 0x4) { \ +++ prot##cache_op(hitop, addr); \ +++ prot##cache_op(hitop, addr + lsize); \ +++ prot##cache_op(hitop, addr + lsize_2); \ +++ prot##cache_op(hitop, addr + lsize_3); \ +++ addr += lsize_4; \ +++ } \ +++ \ +++ if (lines & 0x2) { \ +++ prot##cache_op(hitop, addr); \ +++ prot##cache_op(hitop, addr + lsize); \ +++ addr += lsize_2; \ +++ } \ +++ \ +++ if (lines & 0x1) { \ ++ prot##cache_op(hitop, addr); \ ++- if (addr == aend) \ ++- break; \ ++- addr += lsize; \ ++ } \ ++ \ ++ __##pfx##flush_epilogue \ +diff --git a/target/linux/generic/hack-4.14/301-mips_image_cmdline_hack.patch b/target/linux/generic/hack-4.14/301-mips_image_cmdline_hack.patch +new file mode 100644 +index 0000000000..9bcd2a4401 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/301-mips_image_cmdline_hack.patch +@@ -0,0 +1,38 @@ ++From: John Crispin ++Subject: hack: kernel: add generic image_cmdline hack to MIPS targets ++ ++lede-commit: d59f5b3a987a48508257a0ddbaeadc7909f9f976 ++Signed-off-by: Gabor Juhos ++--- ++ arch/mips/Kconfig | 4 ++++ ++ arch/mips/kernel/head.S | 6 ++++++ ++ 2 files changed, 10 insertions(+) ++ ++--- a/arch/mips/Kconfig +++++ b/arch/mips/Kconfig ++@@ -1159,6 +1159,10 @@ config SYNC_R4K ++ config MIPS_MACHINE ++ def_bool n ++ +++config IMAGE_CMDLINE_HACK +++ bool "OpenWrt specific image command line hack" +++ default n +++ ++ config NO_IOPORT_MAP ++ def_bool n ++ ++--- a/arch/mips/kernel/head.S +++++ b/arch/mips/kernel/head.S ++@@ -79,6 +79,12 @@ FEXPORT(__kernel_entry) ++ j kernel_entry ++ #endif ++ +++#ifdef CONFIG_IMAGE_CMDLINE_HACK +++ .ascii "CMDLINE:" +++EXPORT(__image_cmdline) +++ .fill 0x400 +++#endif /* CONFIG_IMAGE_CMDLINE_HACK */ +++ ++ __REF ++ ++ NESTED(kernel_entry, 16, sp) # kernel entry point +diff --git a/target/linux/generic/hack-4.14/321-powerpc_crtsavres_prereq.patch b/target/linux/generic/hack-4.14/321-powerpc_crtsavres_prereq.patch +new file mode 100644 +index 0000000000..3f81b2e05f +--- /dev/null ++++ b/target/linux/generic/hack-4.14/321-powerpc_crtsavres_prereq.patch +@@ -0,0 +1,38 @@ ++From 107c0964cb8db7ca28ac5199426414fdab3c274d Mon Sep 17 00:00:00 2001 ++From: "Alexandros C. Couloumbis" ++Date: Fri, 7 Jul 2017 17:14:51 +0200 ++Subject: hack: arch: powerpc: drop register save/restore library from modules ++ ++Upstream GCC uses a libgcc function for saving/restoring registers. This ++makes the code bigger, and upstream kernels need to carry that function ++for every single kernel module. Our GCC is patched to avoid those ++references, so we can drop the extra bloat for modules. ++ ++lede-commit: e8e1084654f50904e6bf77b70b2de3f137d7b3ec ++Signed-off-by: Alexandros C. Couloumbis ++--- ++ arch/powerpc/Makefile | 1 - ++ 1 file changed, 1 deletion(-) ++ ++--- a/arch/powerpc/Makefile +++++ b/arch/powerpc/Makefile ++@@ -59,19 +59,6 @@ machine-$(CONFIG_PPC64) += 64 ++ machine-$(CONFIG_CPU_LITTLE_ENDIAN) += le ++ UTS_MACHINE := $(subst $(space),,$(machine-y)) ++ ++-# XXX This needs to be before we override LD below ++-ifdef CONFIG_PPC32 ++-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o ++-else ++-ifeq ($(call ld-ifversion, -ge, 225000000, y),y) ++-# Have the linker provide sfpr if possible. ++-# There is a corresponding test in arch/powerpc/lib/Makefile ++-KBUILD_LDFLAGS_MODULE += --save-restore-funcs ++-else ++-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o ++-endif ++-endif ++- ++ ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) ++ override LD += -EL ++ LDEMULATION := lppc +diff --git a/target/linux/generic/hack-4.14/400-mt29f_spinand-fix-memleak.patch b/target/linux/generic/hack-4.14/400-mt29f_spinand-fix-memleak.patch +new file mode 100644 +index 0000000000..d479aba01a +--- /dev/null ++++ b/target/linux/generic/hack-4.14/400-mt29f_spinand-fix-memleak.patch +@@ -0,0 +1,90 @@ ++--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c ++@@ -492,7 +492,7 @@ static int spinand_program_page(struct s ++ #ifdef CONFIG_MTD_SPINAND_ONDIEECC ++ unsigned int i, j; ++ ++- wbuf = devm_kzalloc(&spi_nand->dev, CACHE_BUF, GFP_KERNEL); +++ wbuf = kzalloc(CACHE_BUF, GFP_KERNEL); ++ if (!wbuf) ++ return -ENOMEM; ++ ++@@ -500,7 +500,7 @@ static int spinand_program_page(struct s ++ retval = spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf); ++ if (retval < 0) { ++ dev_err(&spi_nand->dev, "ecc error on read page!!!\n"); ++- return retval; +++ goto cleanup; ++ } ++ ++ for (i = offset, j = 0; i < len; i++, j++) ++@@ -510,7 +510,7 @@ static int spinand_program_page(struct s ++ retval = spinand_enable_ecc(spi_nand); ++ if (retval < 0) { ++ dev_err(&spi_nand->dev, "enable ecc failed!!\n"); ++- return retval; +++ goto cleanup; ++ } ++ } ++ #else ++@@ -519,7 +519,7 @@ static int spinand_program_page(struct s ++ retval = spinand_write_enable(spi_nand); ++ if (retval < 0) { ++ dev_err(&spi_nand->dev, "write enable failed!!\n"); ++- return retval; +++ goto cleanup; ++ } ++ if (wait_till_ready(spi_nand)) ++ dev_err(&spi_nand->dev, "wait timedout!!!\n"); ++@@ -527,23 +527,24 @@ static int spinand_program_page(struct s ++ retval = spinand_program_data_to_cache(spi_nand, page_id, ++ offset, len, wbuf); ++ if (retval < 0) ++- return retval; +++ goto cleanup; ++ retval = spinand_program_execute(spi_nand, page_id); ++ if (retval < 0) ++- return retval; +++ goto cleanup; ++ while (1) { ++ retval = spinand_read_status(spi_nand, &status); ++ if (retval < 0) { ++ dev_err(&spi_nand->dev, ++ "error %d reading status register\n", retval); ++- return retval; +++ goto cleanup; ++ } ++ ++ if ((status & STATUS_OIP_MASK) == STATUS_READY) { ++ if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) { ++ dev_err(&spi_nand->dev, ++ "program error, page %d\n", page_id); ++- return -1; +++ retval = -1; +++ goto cleanup; ++ } ++ break; ++ } ++@@ -553,13 +554,20 @@ static int spinand_program_page(struct s ++ retval = spinand_disable_ecc(spi_nand); ++ if (retval < 0) { ++ dev_err(&spi_nand->dev, "disable ecc failed!!\n"); ++- return retval; +++ goto cleanup; ++ } ++ enable_hw_ecc = 0; ++ } +++ kfree(wbuf); ++ #endif ++- ++ return 0; +++ +++cleanup: +++#ifdef CONFIG_MTD_SPINAND_ONDIEECC +++ kfree(wbuf); +++#endif +++ return retval; +++ ++ } ++ ++ /** +diff --git a/target/linux/generic/hack-4.14/531-debloat_lzma.patch b/target/linux/generic/hack-4.14/531-debloat_lzma.patch +new file mode 100644 +index 0000000000..2e453cc2f2 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/531-debloat_lzma.patch +@@ -0,0 +1,1040 @@ ++From 3fd297761ac246c54d7723c57fca95c112b99465 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sat, 15 Jul 2017 21:15:44 +0200 ++Subject: lzma: de-bloat the lzma library used by jffs2 ++ ++lede-commit: 3fd1dd08fbcbb78b34efefd32c3032e5c99108d6 ++Signed-off-by: Felix Fietkau ++--- ++ include/linux/lzma/LzFind.h | 17 --- ++ include/linux/lzma/LzmaDec.h | 101 --------------- ++ include/linux/lzma/LzmaEnc.h | 20 --- ++ lib/lzma/LzFind.c | 287 ++++--------------------------------------- ++ lib/lzma/LzmaDec.c | 86 +------------ ++ lib/lzma/LzmaEnc.c | 172 ++------------------------ ++ 6 files changed, 42 insertions(+), 641 deletions(-) ++ ++--- a/include/linux/lzma/LzFind.h +++++ b/include/linux/lzma/LzFind.h ++@@ -55,11 +55,6 @@ typedef struct _CMatchFinder ++ ++ #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) ++ ++-int MatchFinder_NeedMove(CMatchFinder *p); ++-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); ++-void MatchFinder_MoveBlock(CMatchFinder *p); ++-void MatchFinder_ReadIfRequired(CMatchFinder *p); ++- ++ void MatchFinder_Construct(CMatchFinder *p); ++ ++ /* Conditions: ++@@ -70,12 +65,6 @@ int MatchFinder_Create(CMatchFinder *p, ++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ++ ISzAlloc *alloc); ++ void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); ++-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); ++-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); ++- ++-UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, ++- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, ++- UInt32 *distances, UInt32 maxLen); ++ ++ /* ++ Conditions: ++@@ -102,12 +91,6 @@ typedef struct _IMatchFinder ++ ++ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); ++ ++-void MatchFinder_Init(CMatchFinder *p); ++-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); ++-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); ++-void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); ++-void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); ++- ++ #ifdef __cplusplus ++ } ++ #endif ++--- a/include/linux/lzma/LzmaDec.h +++++ b/include/linux/lzma/LzmaDec.h ++@@ -31,14 +31,6 @@ typedef struct _CLzmaProps ++ UInt32 dicSize; ++ } CLzmaProps; ++ ++-/* LzmaProps_Decode - decodes properties ++-Returns: ++- SZ_OK ++- SZ_ERROR_UNSUPPORTED - Unsupported properties ++-*/ ++- ++-SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); ++- ++ ++ /* ---------- LZMA Decoder state ---------- */ ++ ++@@ -70,8 +62,6 @@ typedef struct ++ ++ #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } ++ ++-void LzmaDec_Init(CLzmaDec *p); ++- ++ /* There are two types of LZMA streams: ++ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. ++ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ ++@@ -108,97 +98,6 @@ typedef enum ++ ++ /* ELzmaStatus is used only as output value for function call */ ++ ++- ++-/* ---------- Interfaces ---------- */ ++- ++-/* There are 3 levels of interfaces: ++- 1) Dictionary Interface ++- 2) Buffer Interface ++- 3) One Call Interface ++- You can select any of these interfaces, but don't mix functions from different ++- groups for same object. */ ++- ++- ++-/* There are two variants to allocate state for Dictionary Interface: ++- 1) LzmaDec_Allocate / LzmaDec_Free ++- 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs ++- You can use variant 2, if you set dictionary buffer manually. ++- For Buffer Interface you must always use variant 1. ++- ++-LzmaDec_Allocate* can return: ++- SZ_OK ++- SZ_ERROR_MEM - Memory allocation error ++- SZ_ERROR_UNSUPPORTED - Unsupported properties ++-*/ ++- ++-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); ++-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); ++- ++-SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); ++-void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); ++- ++-/* ---------- Dictionary Interface ---------- */ ++- ++-/* You can use it, if you want to eliminate the overhead for data copying from ++- dictionary to some other external buffer. ++- You must work with CLzmaDec variables directly in this interface. ++- ++- STEPS: ++- LzmaDec_Constr() ++- LzmaDec_Allocate() ++- for (each new stream) ++- { ++- LzmaDec_Init() ++- while (it needs more decompression) ++- { ++- LzmaDec_DecodeToDic() ++- use data from CLzmaDec::dic and update CLzmaDec::dicPos ++- } ++- } ++- LzmaDec_Free() ++-*/ ++- ++-/* LzmaDec_DecodeToDic ++- ++- The decoding to internal dictionary buffer (CLzmaDec::dic). ++- You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! ++- ++-finishMode: ++- It has meaning only if the decoding reaches output limit (dicLimit). ++- LZMA_FINISH_ANY - Decode just dicLimit bytes. ++- LZMA_FINISH_END - Stream must be finished after dicLimit. ++- ++-Returns: ++- SZ_OK ++- status: ++- LZMA_STATUS_FINISHED_WITH_MARK ++- LZMA_STATUS_NOT_FINISHED ++- LZMA_STATUS_NEEDS_MORE_INPUT ++- LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ++- SZ_ERROR_DATA - Data error ++-*/ ++- ++-SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, ++- const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); ++- ++- ++-/* ---------- Buffer Interface ---------- */ ++- ++-/* It's zlib-like interface. ++- See LzmaDec_DecodeToDic description for information about STEPS and return results, ++- but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need ++- to work with CLzmaDec variables manually. ++- ++-finishMode: ++- It has meaning only if the decoding reaches output limit (*destLen). ++- LZMA_FINISH_ANY - Decode just destLen bytes. ++- LZMA_FINISH_END - Stream must be finished after (*destLen). ++-*/ ++- ++-SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, ++- const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); ++- ++- ++ /* ---------- One Call Interface ---------- */ ++ ++ /* LzmaDecode ++--- a/include/linux/lzma/LzmaEnc.h +++++ b/include/linux/lzma/LzmaEnc.h ++@@ -31,9 +31,6 @@ typedef struct _CLzmaEncProps ++ } CLzmaEncProps; ++ ++ void LzmaEncProps_Init(CLzmaEncProps *p); ++-void LzmaEncProps_Normalize(CLzmaEncProps *p); ++-UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); ++- ++ ++ /* ---------- CLzmaEncHandle Interface ---------- */ ++ ++@@ -53,26 +50,9 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc * ++ void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); ++ SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); ++ SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); ++-SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ++- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ ++-/* ---------- One Call Interface ---------- */ ++- ++-/* LzmaEncode ++-Return code: ++- SZ_OK - OK ++- SZ_ERROR_MEM - Memory allocation error ++- SZ_ERROR_PARAM - Incorrect paramater ++- SZ_ERROR_OUTPUT_EOF - output buffer overflow ++- SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) ++-*/ ++- ++-SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++- const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ++- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++- ++ #ifdef __cplusplus ++ } ++ #endif ++--- a/lib/lzma/LzFind.c +++++ b/lib/lzma/LzFind.c ++@@ -14,9 +14,15 @@ ++ ++ #define kStartMaxLen 3 ++ +++#if 0 +++#define DIRECT_INPUT p->directInput +++#else +++#define DIRECT_INPUT 1 +++#endif +++ ++ static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) ++ { ++- if (!p->directInput) +++ if (!DIRECT_INPUT) ++ { ++ alloc->Free(alloc, p->bufferBase); ++ p->bufferBase = 0; ++@@ -28,7 +34,7 @@ static void LzInWindow_Free(CMatchFinder ++ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) ++ { ++ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; ++- if (p->directInput) +++ if (DIRECT_INPUT) ++ { ++ p->blockSize = blockSize; ++ return 1; ++@@ -42,12 +48,12 @@ static int LzInWindow_Create(CMatchFinde ++ return (p->bufferBase != 0); ++ } ++ ++-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } ++-Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } +++static Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +++static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } ++ ++-UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } +++static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } ++ ++-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +++static void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) ++ { ++ p->posLimit -= subValue; ++ p->pos -= subValue; ++@@ -58,7 +64,7 @@ static void MatchFinder_ReadBlock(CMatch ++ { ++ if (p->streamEndWasReached || p->result != SZ_OK) ++ return; ++- if (p->directInput) +++ if (DIRECT_INPUT) ++ { ++ UInt32 curSize = 0xFFFFFFFF - p->streamPos; ++ if (curSize > p->directInputRem) ++@@ -89,7 +95,7 @@ static void MatchFinder_ReadBlock(CMatch ++ } ++ } ++ ++-void MatchFinder_MoveBlock(CMatchFinder *p) +++static void MatchFinder_MoveBlock(CMatchFinder *p) ++ { ++ memmove(p->bufferBase, ++ p->buffer - p->keepSizeBefore, ++@@ -97,22 +103,14 @@ void MatchFinder_MoveBlock(CMatchFinder ++ p->buffer = p->bufferBase + p->keepSizeBefore; ++ } ++ ++-int MatchFinder_NeedMove(CMatchFinder *p) +++static int MatchFinder_NeedMove(CMatchFinder *p) ++ { ++- if (p->directInput) +++ if (DIRECT_INPUT) ++ return 0; ++ /* if (p->streamEndWasReached) return 0; */ ++ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); ++ } ++ ++-void MatchFinder_ReadIfRequired(CMatchFinder *p) ++-{ ++- if (p->streamEndWasReached) ++- return; ++- if (p->keepSizeAfter >= p->streamPos - p->pos) ++- MatchFinder_ReadBlock(p); ++-} ++- ++ static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) ++ { ++ if (MatchFinder_NeedMove(p)) ++@@ -268,7 +266,7 @@ static void MatchFinder_SetLimits(CMatch ++ p->posLimit = p->pos + limit; ++ } ++ ++-void MatchFinder_Init(CMatchFinder *p) +++static void MatchFinder_Init(CMatchFinder *p) ++ { ++ UInt32 i; ++ for (i = 0; i < p->hashSizeSum; i++) ++@@ -287,7 +285,7 @@ static UInt32 MatchFinder_GetSubValue(CM ++ return (p->pos - p->historySize - 1) & kNormalizeMask; ++ } ++ ++-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +++static void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) ++ { ++ UInt32 i; ++ for (i = 0; i < numItems; i++) ++@@ -319,38 +317,7 @@ static void MatchFinder_CheckLimits(CMat ++ MatchFinder_SetLimits(p); ++ } ++ ++-static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++- UInt32 *distances, UInt32 maxLen) ++-{ ++- son[_cyclicBufferPos] = curMatch; ++- for (;;) ++- { ++- UInt32 delta = pos - curMatch; ++- if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++- return distances; ++- { ++- const Byte *pb = cur - delta; ++- curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; ++- if (pb[maxLen] == cur[maxLen] && *pb == *cur) ++- { ++- UInt32 len = 0; ++- while (++len != lenLimit) ++- if (pb[len] != cur[len]) ++- break; ++- if (maxLen < len) ++- { ++- *distances++ = maxLen = len; ++- *distances++ = delta - 1; ++- if (len == lenLimit) ++- return distances; ++- } ++- } ++- } ++- } ++-} ++- ++-UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, +++static UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++ UInt32 *distances, UInt32 maxLen) ++ { ++@@ -460,10 +427,10 @@ static void SkipMatchesSpec(UInt32 lenLi ++ p->buffer++; \ ++ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); ++ ++-#define MOVE_POS_RET MOVE_POS return offset; ++- ++ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } ++ +++#define MOVE_POS_RET MatchFinder_MovePos(p); return offset; +++ ++ #define GET_MATCHES_HEADER2(minLen, ret_op) \ ++ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ ++ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ ++@@ -479,62 +446,7 @@ static void MatchFinder_MovePos(CMatchFi ++ distances + offset, maxLen) - distances); MOVE_POS_RET; ++ ++ #define SKIP_FOOTER \ ++- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; ++- ++-static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++-{ ++- UInt32 offset; ++- GET_MATCHES_HEADER(2) ++- HASH2_CALC; ++- curMatch = p->hash[hashValue]; ++- p->hash[hashValue] = p->pos; ++- offset = 0; ++- GET_MATCHES_FOOTER(offset, 1) ++-} ++- ++-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++-{ ++- UInt32 offset; ++- GET_MATCHES_HEADER(3) ++- HASH_ZIP_CALC; ++- curMatch = p->hash[hashValue]; ++- p->hash[hashValue] = p->pos; ++- offset = 0; ++- GET_MATCHES_FOOTER(offset, 2) ++-} ++- ++-static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++-{ ++- UInt32 hash2Value, delta2, maxLen, offset; ++- GET_MATCHES_HEADER(3) ++- ++- HASH3_CALC; ++- ++- delta2 = p->pos - p->hash[hash2Value]; ++- curMatch = p->hash[kFix3HashSize + hashValue]; ++- ++- p->hash[hash2Value] = ++- p->hash[kFix3HashSize + hashValue] = p->pos; ++- ++- ++- maxLen = 2; ++- offset = 0; ++- if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++- { ++- for (; maxLen != lenLimit; maxLen++) ++- if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++- break; ++- distances[0] = maxLen; ++- distances[1] = delta2 - 1; ++- offset = 2; ++- if (maxLen == lenLimit) ++- { ++- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); ++- MOVE_POS_RET; ++- } ++- } ++- GET_MATCHES_FOOTER(offset, maxLen) ++-} +++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MatchFinder_MovePos(p); ++ ++ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++ { ++@@ -583,108 +495,6 @@ static UInt32 Bt4_MatchFinder_GetMatches ++ GET_MATCHES_FOOTER(offset, maxLen) ++ } ++ ++-static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++-{ ++- UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; ++- GET_MATCHES_HEADER(4) ++- ++- HASH4_CALC; ++- ++- delta2 = p->pos - p->hash[ hash2Value]; ++- delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; ++- curMatch = p->hash[kFix4HashSize + hashValue]; ++- ++- p->hash[ hash2Value] = ++- p->hash[kFix3HashSize + hash3Value] = ++- p->hash[kFix4HashSize + hashValue] = p->pos; ++- ++- maxLen = 1; ++- offset = 0; ++- if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++- { ++- distances[0] = maxLen = 2; ++- distances[1] = delta2 - 1; ++- offset = 2; ++- } ++- if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) ++- { ++- maxLen = 3; ++- distances[offset + 1] = delta3 - 1; ++- offset += 2; ++- delta2 = delta3; ++- } ++- if (offset != 0) ++- { ++- for (; maxLen != lenLimit; maxLen++) ++- if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++- break; ++- distances[offset - 2] = maxLen; ++- if (maxLen == lenLimit) ++- { ++- p->son[p->cyclicBufferPos] = curMatch; ++- MOVE_POS_RET; ++- } ++- } ++- if (maxLen < 3) ++- maxLen = 3; ++- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), ++- distances + offset, maxLen) - (distances)); ++- MOVE_POS_RET ++-} ++- ++-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++-{ ++- UInt32 offset; ++- GET_MATCHES_HEADER(3) ++- HASH_ZIP_CALC; ++- curMatch = p->hash[hashValue]; ++- p->hash[hashValue] = p->pos; ++- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), ++- distances, 2) - (distances)); ++- MOVE_POS_RET ++-} ++- ++-static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++-{ ++- do ++- { ++- SKIP_HEADER(2) ++- HASH2_CALC; ++- curMatch = p->hash[hashValue]; ++- p->hash[hashValue] = p->pos; ++- SKIP_FOOTER ++- } ++- while (--num != 0); ++-} ++- ++-void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++-{ ++- do ++- { ++- SKIP_HEADER(3) ++- HASH_ZIP_CALC; ++- curMatch = p->hash[hashValue]; ++- p->hash[hashValue] = p->pos; ++- SKIP_FOOTER ++- } ++- while (--num != 0); ++-} ++- ++-static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++-{ ++- do ++- { ++- UInt32 hash2Value; ++- SKIP_HEADER(3) ++- HASH3_CALC; ++- curMatch = p->hash[kFix3HashSize + hashValue]; ++- p->hash[hash2Value] = ++- p->hash[kFix3HashSize + hashValue] = p->pos; ++- SKIP_FOOTER ++- } ++- while (--num != 0); ++-} ++- ++ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++ { ++ do ++@@ -701,61 +511,12 @@ static void Bt4_MatchFinder_Skip(CMatchF ++ while (--num != 0); ++ } ++ ++-static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++-{ ++- do ++- { ++- UInt32 hash2Value, hash3Value; ++- SKIP_HEADER(4) ++- HASH4_CALC; ++- curMatch = p->hash[kFix4HashSize + hashValue]; ++- p->hash[ hash2Value] = ++- p->hash[kFix3HashSize + hash3Value] = ++- p->hash[kFix4HashSize + hashValue] = p->pos; ++- p->son[p->cyclicBufferPos] = curMatch; ++- MOVE_POS ++- } ++- while (--num != 0); ++-} ++- ++-void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++-{ ++- do ++- { ++- SKIP_HEADER(3) ++- HASH_ZIP_CALC; ++- curMatch = p->hash[hashValue]; ++- p->hash[hashValue] = p->pos; ++- p->son[p->cyclicBufferPos] = curMatch; ++- MOVE_POS ++- } ++- while (--num != 0); ++-} ++- ++ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) ++ { ++ vTable->Init = (Mf_Init_Func)MatchFinder_Init; ++ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; ++ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; ++ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; ++- if (!p->btMode) ++- { ++- vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; ++- vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; ++- } ++- else if (p->numHashBytes == 2) ++- { ++- vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; ++- vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; ++- } ++- else if (p->numHashBytes == 3) ++- { ++- vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; ++- vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; ++- } ++- else ++- { ++- vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; ++- vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; ++- } +++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; +++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; ++ } ++--- a/lib/lzma/LzmaDec.c +++++ b/lib/lzma/LzmaDec.c ++@@ -682,7 +682,7 @@ static void LzmaDec_InitRc(CLzmaDec *p, ++ p->needFlush = 0; ++ } ++ ++-void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +++static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) ++ { ++ p->needFlush = 1; ++ p->remainLen = 0; ++@@ -698,7 +698,7 @@ void LzmaDec_InitDicAndState(CLzmaDec *p ++ p->needInitState = 1; ++ } ++ ++-void LzmaDec_Init(CLzmaDec *p) +++static void LzmaDec_Init(CLzmaDec *p) ++ { ++ p->dicPos = 0; ++ LzmaDec_InitDicAndState(p, True, True); ++@@ -716,7 +716,7 @@ static void LzmaDec_InitStateReal(CLzmaD ++ p->needInitState = 0; ++ } ++ ++-SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, +++static SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ++ ELzmaFinishMode finishMode, ELzmaStatus *status) ++ { ++ SizeT inSize = *srcLen; ++@@ -837,65 +837,13 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, Si ++ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; ++ } ++ ++-SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) ++-{ ++- SizeT outSize = *destLen; ++- SizeT inSize = *srcLen; ++- *srcLen = *destLen = 0; ++- for (;;) ++- { ++- SizeT inSizeCur = inSize, outSizeCur, dicPos; ++- ELzmaFinishMode curFinishMode; ++- SRes res; ++- if (p->dicPos == p->dicBufSize) ++- p->dicPos = 0; ++- dicPos = p->dicPos; ++- if (outSize > p->dicBufSize - dicPos) ++- { ++- outSizeCur = p->dicBufSize; ++- curFinishMode = LZMA_FINISH_ANY; ++- } ++- else ++- { ++- outSizeCur = dicPos + outSize; ++- curFinishMode = finishMode; ++- } ++- ++- res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); ++- src += inSizeCur; ++- inSize -= inSizeCur; ++- *srcLen += inSizeCur; ++- outSizeCur = p->dicPos - dicPos; ++- memcpy(dest, p->dic + dicPos, outSizeCur); ++- dest += outSizeCur; ++- outSize -= outSizeCur; ++- *destLen += outSizeCur; ++- if (res != 0) ++- return res; ++- if (outSizeCur == 0 || outSize == 0) ++- return SZ_OK; ++- } ++-} ++- ++-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +++static void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) ++ { ++ alloc->Free(alloc, p->probs); ++ p->probs = 0; ++ } ++ ++-static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) ++-{ ++- alloc->Free(alloc, p->dic); ++- p->dic = 0; ++-} ++- ++-void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) ++-{ ++- LzmaDec_FreeProbs(p, alloc); ++- LzmaDec_FreeDict(p, alloc); ++-} ++- ++-SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +++static SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) ++ { ++ UInt32 dicSize; ++ Byte d; ++@@ -935,7 +883,7 @@ static SRes LzmaDec_AllocateProbs2(CLzma ++ return SZ_OK; ++ } ++ ++-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +++static SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++ { ++ CLzmaProps propNew; ++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++@@ -943,28 +891,6 @@ SRes LzmaDec_AllocateProbs(CLzmaDec *p, ++ p->prop = propNew; ++ return SZ_OK; ++ } ++- ++-SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++-{ ++- CLzmaProps propNew; ++- SizeT dicBufSize; ++- RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++- RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); ++- dicBufSize = propNew.dicSize; ++- if (p->dic == 0 || dicBufSize != p->dicBufSize) ++- { ++- LzmaDec_FreeDict(p, alloc); ++- p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); ++- if (p->dic == 0) ++- { ++- LzmaDec_FreeProbs(p, alloc); ++- return SZ_ERROR_MEM; ++- } ++- } ++- p->dicBufSize = dicBufSize; ++- p->prop = propNew; ++- return SZ_OK; ++-} ++ ++ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ++--- a/lib/lzma/LzmaEnc.c +++++ b/lib/lzma/LzmaEnc.c ++@@ -53,7 +53,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) ++ p->writeEndMark = 0; ++ } ++ ++-void LzmaEncProps_Normalize(CLzmaEncProps *p) +++static void LzmaEncProps_Normalize(CLzmaEncProps *p) ++ { ++ int level = p->level; ++ if (level < 0) level = 5; ++@@ -76,7 +76,7 @@ void LzmaEncProps_Normalize(CLzmaEncProp ++ #endif ++ } ++ ++-UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +++static UInt32 __maybe_unused LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) ++ { ++ CLzmaEncProps props = *props2; ++ LzmaEncProps_Normalize(&props); ++@@ -93,7 +93,7 @@ UInt32 LzmaEncProps_GetDictSize(const CL ++ ++ #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } ++ ++-UInt32 GetPosSlot1(UInt32 pos) +++static UInt32 GetPosSlot1(UInt32 pos) ++ { ++ UInt32 res; ++ BSR2_RET(pos, res); ++@@ -107,7 +107,7 @@ UInt32 GetPosSlot1(UInt32 pos) ++ #define kNumLogBits (9 + (int)sizeof(size_t) / 2) ++ #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) ++ ++-void LzmaEnc_FastPosInit(Byte *g_FastPos) +++static void LzmaEnc_FastPosInit(Byte *g_FastPos) ++ { ++ int c = 2, slotFast; ++ g_FastPos[0] = 0; ++@@ -339,58 +339,6 @@ typedef struct ++ CSaveState saveState; ++ } CLzmaEnc; ++ ++-void LzmaEnc_SaveState(CLzmaEncHandle pp) ++-{ ++- CLzmaEnc *p = (CLzmaEnc *)pp; ++- CSaveState *dest = &p->saveState; ++- int i; ++- dest->lenEnc = p->lenEnc; ++- dest->repLenEnc = p->repLenEnc; ++- dest->state = p->state; ++- ++- for (i = 0; i < kNumStates; i++) ++- { ++- memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); ++- memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); ++- } ++- for (i = 0; i < kNumLenToPosStates; i++) ++- memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); ++- memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); ++- memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); ++- memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); ++- memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); ++- memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); ++- memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); ++- memcpy(dest->reps, p->reps, sizeof(p->reps)); ++- memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); ++-} ++- ++-void LzmaEnc_RestoreState(CLzmaEncHandle pp) ++-{ ++- CLzmaEnc *dest = (CLzmaEnc *)pp; ++- const CSaveState *p = &dest->saveState; ++- int i; ++- dest->lenEnc = p->lenEnc; ++- dest->repLenEnc = p->repLenEnc; ++- dest->state = p->state; ++- ++- for (i = 0; i < kNumStates; i++) ++- { ++- memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); ++- memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); ++- } ++- for (i = 0; i < kNumLenToPosStates; i++) ++- memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); ++- memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); ++- memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); ++- memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); ++- memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); ++- memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); ++- memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); ++- memcpy(dest->reps, p->reps, sizeof(p->reps)); ++- memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); ++-} ++- ++ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) ++ { ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++@@ -600,7 +548,7 @@ static void LitEnc_EncodeMatched(CRangeE ++ while (symbol < 0x10000); ++ } ++ ++-void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +++static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) ++ { ++ UInt32 i; ++ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) ++@@ -1676,7 +1624,7 @@ static void FillDistancesPrices(CLzmaEnc ++ p->matchPriceCount = 0; ++ } ++ ++-void LzmaEnc_Construct(CLzmaEnc *p) +++static void LzmaEnc_Construct(CLzmaEnc *p) ++ { ++ RangeEnc_Construct(&p->rc); ++ MatchFinder_Construct(&p->matchFinderBase); ++@@ -1709,7 +1657,7 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc * ++ return p; ++ } ++ ++-void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +++static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) ++ { ++ alloc->Free(alloc, p->litProbs); ++ alloc->Free(alloc, p->saveState.litProbs); ++@@ -1717,7 +1665,7 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAl ++ p->saveState.litProbs = 0; ++ } ++ ++-void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +++static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) ++ { ++ #ifndef _7ZIP_ST ++ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); ++@@ -1947,7 +1895,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, U ++ return SZ_OK; ++ } ++ ++-void LzmaEnc_Init(CLzmaEnc *p) +++static void LzmaEnc_Init(CLzmaEnc *p) ++ { ++ UInt32 i; ++ p->state = 0; ++@@ -2005,7 +1953,7 @@ void LzmaEnc_Init(CLzmaEnc *p) ++ p->lpMask = (1 << p->lp) - 1; ++ } ++ ++-void LzmaEnc_InitPrices(CLzmaEnc *p) +++static void LzmaEnc_InitPrices(CLzmaEnc *p) ++ { ++ if (!p->fastMode) ++ { ++@@ -2037,26 +1985,6 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEn ++ return SZ_OK; ++ } ++ ++-static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ++- ISzAlloc *alloc, ISzAlloc *allocBig) ++-{ ++- CLzmaEnc *p = (CLzmaEnc *)pp; ++- p->matchFinderBase.stream = inStream; ++- p->needInit = 1; ++- p->rc.outStream = outStream; ++- return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); ++-} ++- ++-SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ++- ISeqInStream *inStream, UInt32 keepWindowSize, ++- ISzAlloc *alloc, ISzAlloc *allocBig) ++-{ ++- CLzmaEnc *p = (CLzmaEnc *)pp; ++- p->matchFinderBase.stream = inStream; ++- p->needInit = 1; ++- return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++-} ++- ++ static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) ++ { ++ p->matchFinderBase.directInput = 1; ++@@ -2064,7 +1992,7 @@ static void LzmaEnc_SetInputBuf(CLzmaEnc ++ p->matchFinderBase.directInputRem = srcLen; ++ } ++ ++-SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, +++static SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, ++ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++ { ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++@@ -2074,7 +2002,7 @@ SRes LzmaEnc_MemPrepare(CLzmaEncHandle p ++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++ } ++ ++-void LzmaEnc_Finish(CLzmaEncHandle pp) +++static void LzmaEnc_Finish(CLzmaEncHandle pp) ++ { ++ #ifndef _7ZIP_ST ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++@@ -2107,53 +2035,6 @@ static size_t MyWrite(void *pp, const vo ++ return size; ++ } ++ ++- ++-UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) ++-{ ++- const CLzmaEnc *p = (CLzmaEnc *)pp; ++- return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++-} ++- ++-const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) ++-{ ++- const CLzmaEnc *p = (CLzmaEnc *)pp; ++- return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; ++-} ++- ++-SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, ++- Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) ++-{ ++- CLzmaEnc *p = (CLzmaEnc *)pp; ++- UInt64 nowPos64; ++- SRes res; ++- CSeqOutStreamBuf outStream; ++- ++- outStream.funcTable.Write = MyWrite; ++- outStream.data = dest; ++- outStream.rem = *destLen; ++- outStream.overflow = False; ++- ++- p->writeEndMark = False; ++- p->finished = False; ++- p->result = SZ_OK; ++- ++- if (reInit) ++- LzmaEnc_Init(p); ++- LzmaEnc_InitPrices(p); ++- nowPos64 = p->nowPos64; ++- RangeEnc_Init(&p->rc); ++- p->rc.outStream = &outStream.funcTable; ++- ++- res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); ++- ++- *unpackSize = (UInt32)(p->nowPos64 - nowPos64); ++- *destLen -= outStream.rem; ++- if (outStream.overflow) ++- return SZ_ERROR_OUTPUT_EOF; ++- ++- return res; ++-} ++- ++ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) ++ { ++ SRes res = SZ_OK; ++@@ -2184,13 +2065,6 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ++ return res; ++ } ++ ++-SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ++- ISzAlloc *alloc, ISzAlloc *allocBig) ++-{ ++- RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); ++- return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); ++-} ++- ++ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) ++ { ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++@@ -2247,25 +2121,3 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp ++ return SZ_ERROR_OUTPUT_EOF; ++ return res; ++ } ++- ++-SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++- const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ++- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ++-{ ++- CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); ++- SRes res; ++- if (p == 0) ++- return SZ_ERROR_MEM; ++- ++- res = LzmaEnc_SetProps(p, props); ++- if (res == SZ_OK) ++- { ++- res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); ++- if (res == SZ_OK) ++- res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, ++- writeEndMark, progress, alloc, allocBig); ++- } ++- ++- LzmaEnc_Destroy(p, alloc, allocBig); ++- return res; ++-} +diff --git a/target/linux/generic/hack-4.14/640-bridge-only-accept-EAP-locally.patch b/target/linux/generic/hack-4.14/640-bridge-only-accept-EAP-locally.patch +new file mode 100644 +index 0000000000..fbe9ab0876 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/640-bridge-only-accept-EAP-locally.patch +@@ -0,0 +1,82 @@ ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:18:54 +0200 ++Subject: bridge: only accept EAP locally ++ ++When bridging, do not forward EAP frames to other ports, only deliver ++them locally, regardless of the state. ++ ++Signed-off-by: Felix Fietkau ++[add disable_eap_hack sysfs attribute] ++Signed-off-by: Etienne Champetier ++--- ++ ++--- a/net/bridge/br_input.c +++++ b/net/bridge/br_input.c ++@@ -166,10 +166,14 @@ int br_handle_frame_finish(struct net *n ++ } ++ } ++ +++ BR_INPUT_SKB_CB(skb)->brdev = br->dev; +++ +++ if (skb->protocol == htons(ETH_P_PAE) && !br->disable_eap_hack) +++ return br_pass_frame_up(skb); +++ ++ if (p->state == BR_STATE_LEARNING) ++ goto drop; ++ ++- BR_INPUT_SKB_CB(skb)->brdev = br->dev; ++ BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED); ++ ++ if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP)) ++--- a/net/bridge/br_private.h +++++ b/net/bridge/br_private.h ++@@ -320,6 +320,8 @@ struct net_bridge { ++ u16 group_fwd_mask; ++ u16 group_fwd_mask_required; ++ +++ bool disable_eap_hack; +++ ++ /* STP */ ++ bridge_id designated_root; ++ bridge_id bridge_id; ++--- a/net/bridge/br_sysfs_br.c +++++ b/net/bridge/br_sysfs_br.c ++@@ -170,6 +170,30 @@ static ssize_t group_fwd_mask_store(stru ++ } ++ static DEVICE_ATTR_RW(group_fwd_mask); ++ +++static ssize_t disable_eap_hack_show(struct device *d, +++ struct device_attribute *attr, +++ char *buf) +++{ +++ struct net_bridge *br = to_bridge(d); +++ return sprintf(buf, "%u\n", br->disable_eap_hack); +++} +++ +++static int set_disable_eap_hack(struct net_bridge *br, unsigned long val) +++{ +++ br->disable_eap_hack = !!val; +++ +++ return 0; +++} +++ +++static ssize_t disable_eap_hack_store(struct device *d, +++ struct device_attribute *attr, +++ const char *buf, +++ size_t len) +++{ +++ return store_bridge_parm(d, buf, len, set_disable_eap_hack); +++} +++static DEVICE_ATTR_RW(disable_eap_hack); +++ ++ static ssize_t priority_show(struct device *d, struct device_attribute *attr, ++ char *buf) ++ { ++@@ -817,6 +841,7 @@ static struct attribute *bridge_attrs[] ++ &dev_attr_ageing_time.attr, ++ &dev_attr_stp_state.attr, ++ &dev_attr_group_fwd_mask.attr, +++ &dev_attr_disable_eap_hack.attr, ++ &dev_attr_priority.attr, ++ &dev_attr_bridge_id.attr, ++ &dev_attr_root_id.attr, +diff --git a/target/linux/generic/hack-4.14/645-netfilter-connmark-introduce-set-dscpmark.patch b/target/linux/generic/hack-4.14/645-netfilter-connmark-introduce-set-dscpmark.patch +new file mode 100644 +index 0000000000..1ecc95bf22 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/645-netfilter-connmark-introduce-set-dscpmark.patch +@@ -0,0 +1,124 @@ ++From f1627abea333781d3e2a61bac4c7fd4502395741 Mon Sep 17 00:00:00 2001 ++From: Kevin Darbyshire-Bryant ++Date: Sat, 23 Mar 2019 09:29:49 +0000 ++Subject: [PATCH] netfilter: connmark: introduce set-dscpmark ++ ++set-dscpmark is a method of storing the DSCP of an ip packet into ++conntrack mark. In combination with a suitable tc filter action ++(act_ctinfo) DSCP values are able to be stored in the mark on egress and ++restored on ingress across links that otherwise alter or bleach DSCP. ++ ++This is useful for qdiscs such as CAKE which are able to shape according ++to policies based on DSCP. ++ ++Ingress classification is traditionally a challenging task since ++iptables rules haven't yet run and tc filter/eBPF programs are pre-NAT ++lookups, hence are unable to see internal IPv4 addresses as used on the ++typical home masquerading gateway. ++ ++x_tables CONNMARK set-dscpmark target solves the problem of storing the ++DSCP to the conntrack mark in a way suitable for the new act_ctinfo tc ++action to restore. ++ ++The set-dscpmark option accepts 2 parameters, a 32bit 'dscpmask' and a ++32bit 'statemask'. The dscp mask must be 6 contiguous bits and ++represents the area where the DSCP will be stored in the connmark. The ++state mask is a minimum 1 bit length mask that must not overlap with the ++dscpmask. It represents a flag which is set when the DSCP has been ++stored in the conntrack mark. This is useful to implement a 'one shot' ++iptables based classification where the 'complicated' iptables rules are ++only run once to classify the connection on initial (egress) packet and ++subsequent packets are all marked/restored with the same DSCP. A state ++mask of zero disables the setting of a status bit/s. ++ ++example syntax with a suitably modified iptables user space application: ++ ++iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --set-dscpmark 0xfc000000/0x01000000 ++ ++Would store the DSCP in the top 6 bits of the 32bit mark field, and use ++the LSB of the top byte as the 'DSCP has been stored' marker. ++ ++|----0xFC----conntrack mark----000000---| ++| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| ++| DSCP | unused | flag |unused | ++|-----------------------0x01---000000---| ++ ^ ^ ++ | | ++ ---| Conditional flag ++ | set this when dscp ++|-ip diffserv-| stored in mark ++| 6 bits | ++|-------------| ++ ++an identically configured tc action to restore looks like: ++ ++tc filter show dev eth0 ingress ++filter parent ffff: protocol all pref 10 u32 chain 0 ++filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1 ++filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1: not_in_hw ++ match 00000000/00000000 at 0 ++ action order 1: ctinfo zone 0 pipe ++ index 2 ref 1 bind 1 dscp 0xfc000000/0x1000000 ++ ++ action order 2: mirred (Egress Redirect to device ifb4eth0) stolen ++ index 1 ref 1 bind 1 ++ ++|----0xFC----conntrack mark----000000---| ++| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| ++| DSCP | unused | flag |unused | ++|-----------------------0x01---000000---| ++ | | ++ | | ++ ---| Conditional flag ++ v only restore if set ++|-ip diffserv-| ++| 6 bits | ++|-------------| ++ ++Signed-off-by: Kevin Darbyshire-Bryant ++--- ++ net/netfilter/xt_connmark.c | 19 +++++++++++++++++-- ++ 1 file changed, 17 insertions(+), 2 deletions(-) ++ ++--- a/net/netfilter/xt_connmark.c +++++ b/net/netfilter/xt_connmark.c ++@@ -42,6 +42,7 @@ connmark_tg(struct sk_buff *skb, const s ++ enum ip_conntrack_info ctinfo; ++ struct nf_conn *ct; ++ u_int32_t newmark; +++ u_int8_t dscp, maskshift; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (ct == NULL) ++@@ -49,7 +50,21 @@ connmark_tg(struct sk_buff *skb, const s ++ ++ switch (info->mode) { ++ case XT_CONNMARK_SET: ++- newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; +++ if (info->nfmask & 0x80000000) { +++ newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; +++ } else { +++ if (skb->protocol == htons(ETH_P_IP)) +++ dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2; +++ else if (skb->protocol == htons(ETH_P_IPV6)) +++ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2; +++ else /* protocol doesn't have diffserv */ +++ break; +++ +++ /* nfmask contains the mask shift value */ +++ maskshift = info->nfmask & 0x1f; +++ newmark = (ct->mark & ~info->ctmark) | +++ (info->ctmask | (dscp << maskshift)); +++ } ++ if (ct->mark != newmark) { ++ ct->mark = newmark; ++ nf_conntrack_event_cache(IPCT_MARK, ct); ++@@ -57,7 +72,7 @@ connmark_tg(struct sk_buff *skb, const s ++ break; ++ case XT_CONNMARK_SAVE: ++ newmark = (ct->mark & ~info->ctmask) ^ ++- (skb->mark & info->nfmask); +++ (skb->mark & info->nfmask); ++ if (ct->mark != newmark) { ++ ct->mark = newmark; ++ nf_conntrack_event_cache(IPCT_MARK, ct); +diff --git a/target/linux/generic/hack-4.14/647-netfilter-flow-acct.patch b/target/linux/generic/hack-4.14/647-netfilter-flow-acct.patch +new file mode 100644 +index 0000000000..f58b8bc716 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/647-netfilter-flow-acct.patch +@@ -0,0 +1,70 @@ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -163,6 +163,8 @@ struct nf_flow_table_hw { ++ int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload); ++ void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload); ++ +++void nf_flow_table_acct(struct flow_offload *flow, struct sk_buff *skb, int dir); +++ ++ extern struct work_struct nf_flow_offload_hw_work; ++ ++ #define MODULE_ALIAS_NF_FLOWTABLE(family) \ ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -11,6 +11,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ struct flow_offload_entry { ++ struct flow_offload flow; ++@@ -152,6 +153,22 @@ void flow_offload_free(struct flow_offlo ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_free); ++ +++void nf_flow_table_acct(struct flow_offload *flow, struct sk_buff *skb, int dir) +++{ +++ struct flow_offload_entry *entry; +++ struct nf_conn_acct *acct; +++ +++ entry = container_of(flow, struct flow_offload_entry, flow); +++ acct = nf_conn_acct_find(entry->ct); +++ if (acct) { +++ struct nf_conn_counter *counter = acct->counter; +++ +++ atomic64_inc(&counter[dir].packets); +++ atomic64_add(skb->len, &counter[dir].bytes); +++ } +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_acct); +++ ++ static u32 flow_offload_hash(const void *data, u32 len, u32 seed) ++ { ++ const struct flow_offload_tuple *tuple = data; ++--- a/net/netfilter/nf_flow_table_ip.c +++++ b/net/netfilter/nf_flow_table_ip.c ++@@ -11,6 +11,7 @@ ++ #include ++ #include ++ #include +++ ++ /* For layer 4 checksum field offset. */ ++ #include ++ #include ++@@ -265,6 +266,7 @@ nf_flow_offload_ip_hook(void *priv, stru ++ skb->dev = outdev; ++ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); ++ skb_dst_set_noref(skb, &rt->dst); +++ nf_flow_table_acct(flow, skb, dir); ++ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); ++ ++ return NF_STOLEN; ++@@ -482,6 +484,7 @@ nf_flow_offload_ipv6_hook(void *priv, st ++ skb->dev = outdev; ++ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); ++ skb_dst_set_noref(skb, &rt->dst); +++ nf_flow_table_acct(flow, skb, dir); ++ neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); ++ ++ return NF_STOLEN; +diff --git a/target/linux/generic/hack-4.14/650-netfilter-add-xt_OFFLOAD-target.patch b/target/linux/generic/hack-4.14/650-netfilter-add-xt_OFFLOAD-target.patch +new file mode 100644 +index 0000000000..7c93feccdc +--- /dev/null ++++ b/target/linux/generic/hack-4.14/650-netfilter-add-xt_OFFLOAD-target.patch +@@ -0,0 +1,553 @@ ++From: Felix Fietkau ++Date: Tue, 20 Feb 2018 15:56:02 +0100 ++Subject: [PATCH] netfilter: add xt_OFFLOAD target ++ ++Signed-off-by: Felix Fietkau ++--- ++ create mode 100644 net/netfilter/xt_OFFLOAD.c ++ ++--- a/net/ipv4/netfilter/Kconfig +++++ b/net/ipv4/netfilter/Kconfig ++@@ -76,8 +76,6 @@ config NF_TABLES_ARP ++ help ++ This option enables the ARP support for nf_tables. ++ ++-endif # NF_TABLES ++- ++ config NF_FLOW_TABLE_IPV4 ++ tristate "Netfilter flow table IPv4 module" ++ depends on NF_FLOW_TABLE ++@@ -86,6 +84,8 @@ config NF_FLOW_TABLE_IPV4 ++ ++ To compile it as a module, choose M here. ++ +++endif # NF_TABLES +++ ++ config NF_DUP_IPV4 ++ tristate "Netfilter IPv4 packet duplication to alternate destination" ++ depends on !NF_CONNTRACK || NF_CONNTRACK ++--- a/net/ipv6/netfilter/Kconfig +++++ b/net/ipv6/netfilter/Kconfig ++@@ -97,7 +97,6 @@ config NFT_FIB_IPV6 ++ multicast or blackhole. ++ ++ endif # NF_TABLES_IPV6 ++-endif # NF_TABLES ++ ++ config NF_FLOW_TABLE_IPV6 ++ tristate "Netfilter flow table IPv6 module" ++@@ -107,6 +106,8 @@ config NF_FLOW_TABLE_IPV6 ++ ++ To compile it as a module, choose M here. ++ +++endif # NF_TABLES +++ ++ config NF_DUP_IPV6 ++ tristate "Netfilter IPv6 packet duplication to alternate destination" ++ depends on !NF_CONNTRACK || NF_CONNTRACK ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -671,8 +671,6 @@ config NFT_FIB_NETDEV ++ ++ endif # NF_TABLES_NETDEV ++ ++-endif # NF_TABLES ++- ++ config NF_FLOW_TABLE_INET ++ tristate "Netfilter flow table mixed IPv4/IPv6 module" ++ depends on NF_FLOW_TABLE ++@@ -681,11 +679,12 @@ config NF_FLOW_TABLE_INET ++ ++ To compile it as a module, choose M here. ++ +++endif # NF_TABLES +++ ++ config NF_FLOW_TABLE ++ tristate "Netfilter flow table module" ++ depends on NETFILTER_INGRESS ++ depends on NF_CONNTRACK ++- depends on NF_TABLES ++ help ++ This option adds the flow table core infrastructure. ++ ++@@ -974,6 +973,15 @@ config NETFILTER_XT_TARGET_NOTRACK ++ depends on NETFILTER_ADVANCED ++ select NETFILTER_XT_TARGET_CT ++ +++config NETFILTER_XT_TARGET_FLOWOFFLOAD +++ tristate '"FLOWOFFLOAD" target support' +++ depends on NF_FLOW_TABLE +++ depends on NETFILTER_INGRESS +++ help +++ This option adds a `FLOWOFFLOAD' target, which uses the nf_flow_offload +++ module to speed up processing of packets by bypassing the usual +++ netfilter chains +++ ++ config NETFILTER_XT_TARGET_RATEEST ++ tristate '"RATEEST" target support' ++ depends on NETFILTER_ADVANCED ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -134,6 +134,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF ++ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o ++ obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o ++ obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o +++obj-$(CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD) += xt_FLOWOFFLOAD.o ++ obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o ++ obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o ++ obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o ++--- /dev/null +++++ b/net/netfilter/xt_FLOWOFFLOAD.c ++@@ -0,0 +1,422 @@ +++/* +++ * Copyright (C) 2018 Felix Fietkau +++ * +++ * 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 +++#include +++#include +++ +++static struct nf_flowtable nf_flowtable; +++static HLIST_HEAD(hooks); +++static DEFINE_SPINLOCK(hooks_lock); +++static struct delayed_work hook_work; +++ +++struct xt_flowoffload_hook { +++ struct hlist_node list; +++ struct nf_hook_ops ops; +++ struct net *net; +++ bool registered; +++ bool used; +++}; +++ +++static unsigned int +++xt_flowoffload_net_hook(void *priv, struct sk_buff *skb, +++ const struct nf_hook_state *state) +++{ +++ switch (skb->protocol) { +++ case htons(ETH_P_IP): +++ return nf_flow_offload_ip_hook(priv, skb, state); +++ case htons(ETH_P_IPV6): +++ return nf_flow_offload_ipv6_hook(priv, skb, state); +++ } +++ +++ return NF_ACCEPT; +++} +++ +++static int +++xt_flowoffload_create_hook(struct net_device *dev) +++{ +++ struct xt_flowoffload_hook *hook; +++ struct nf_hook_ops *ops; +++ +++ hook = kzalloc(sizeof(*hook), GFP_ATOMIC); +++ if (!hook) +++ return -ENOMEM; +++ +++ ops = &hook->ops; +++ ops->pf = NFPROTO_NETDEV; +++ ops->hooknum = NF_NETDEV_INGRESS; +++ ops->priority = 10; +++ ops->priv = &nf_flowtable; +++ ops->hook = xt_flowoffload_net_hook; +++ ops->dev = dev; +++ +++ hlist_add_head(&hook->list, &hooks); +++ mod_delayed_work(system_power_efficient_wq, &hook_work, 0); +++ +++ return 0; +++} +++ +++static struct xt_flowoffload_hook * +++flow_offload_lookup_hook(struct net_device *dev) +++{ +++ struct xt_flowoffload_hook *hook; +++ +++ hlist_for_each_entry(hook, &hooks, list) { +++ if (hook->ops.dev == dev) +++ return hook; +++ } +++ +++ return NULL; +++} +++ +++static void +++xt_flowoffload_check_device(struct net_device *dev) +++{ +++ struct xt_flowoffload_hook *hook; +++ +++ spin_lock_bh(&hooks_lock); +++ hook = flow_offload_lookup_hook(dev); +++ if (hook) +++ hook->used = true; +++ else +++ xt_flowoffload_create_hook(dev); +++ spin_unlock_bh(&hooks_lock); +++} +++ +++static void +++xt_flowoffload_register_hooks(void) +++{ +++ struct xt_flowoffload_hook *hook; +++ +++restart: +++ hlist_for_each_entry(hook, &hooks, list) { +++ if (hook->registered) +++ continue; +++ +++ hook->registered = true; +++ hook->net = dev_net(hook->ops.dev); +++ spin_unlock_bh(&hooks_lock); +++ nf_register_net_hook(hook->net, &hook->ops); +++ spin_lock_bh(&hooks_lock); +++ goto restart; +++ } +++ +++} +++ +++static void +++xt_flowoffload_cleanup_hooks(void) +++{ +++ struct xt_flowoffload_hook *hook; +++ +++restart: +++ hlist_for_each_entry(hook, &hooks, list) { +++ if (hook->used || !hook->registered) +++ continue; +++ +++ hlist_del(&hook->list); +++ spin_unlock_bh(&hooks_lock); +++ nf_unregister_net_hook(hook->net, &hook->ops); +++ kfree(hook); +++ spin_lock_bh(&hooks_lock); +++ goto restart; +++ } +++ +++} +++ +++static void +++xt_flowoffload_check_hook(struct flow_offload *flow, void *data) +++{ +++ struct flow_offload_tuple *tuple = &flow->tuplehash[0].tuple; +++ struct xt_flowoffload_hook *hook; +++ bool *found = data; +++ +++ spin_lock_bh(&hooks_lock); +++ hlist_for_each_entry(hook, &hooks, list) { +++ if (hook->ops.dev->ifindex != tuple->iifidx && +++ hook->ops.dev->ifindex != tuple->oifidx) +++ continue; +++ +++ hook->used = true; +++ *found = true; +++ } +++ spin_unlock_bh(&hooks_lock); +++} +++ +++static void +++xt_flowoffload_hook_work(struct work_struct *work) +++{ +++ struct xt_flowoffload_hook *hook; +++ bool found = false; +++ int err; +++ +++ spin_lock_bh(&hooks_lock); +++ xt_flowoffload_register_hooks(); +++ hlist_for_each_entry(hook, &hooks, list) +++ hook->used = false; +++ spin_unlock_bh(&hooks_lock); +++ +++ err = nf_flow_table_iterate(&nf_flowtable, xt_flowoffload_check_hook, +++ &found); +++ if (err && err != -EAGAIN) +++ goto out; +++ +++ spin_lock_bh(&hooks_lock); +++ xt_flowoffload_cleanup_hooks(); +++ spin_unlock_bh(&hooks_lock); +++ +++out: +++ if (found) +++ queue_delayed_work(system_power_efficient_wq, &hook_work, HZ); +++} +++ +++static bool +++xt_flowoffload_skip(struct sk_buff *skb, int family) +++{ +++ if (skb_sec_path(skb)) +++ return true; +++ +++ if (family == NFPROTO_IPV4) { +++ const struct ip_options *opt = &(IPCB(skb)->opt); +++ +++ if (unlikely(opt->optlen)) +++ return true; +++ } +++ +++ return false; +++} +++ +++static struct dst_entry * +++xt_flowoffload_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir, +++ const struct xt_action_param *par, int ifindex) +++{ +++ struct dst_entry *dst = NULL; +++ struct flowi fl; +++ +++ memset(&fl, 0, sizeof(fl)); +++ switch (xt_family(par)) { +++ case NFPROTO_IPV4: +++ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; +++ fl.u.ip4.flowi4_oif = ifindex; +++ break; +++ case NFPROTO_IPV6: +++ fl.u.ip6.saddr = ct->tuplehash[dir].tuple.dst.u3.in6; +++ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; +++ fl.u.ip6.flowi6_oif = ifindex; +++ break; +++ } +++ +++ nf_route(xt_net(par), &dst, &fl, false, xt_family(par)); +++ +++ return dst; +++} +++ +++static int +++xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct, +++ const struct xt_action_param *par, +++ struct nf_flow_route *route, enum ip_conntrack_dir dir) +++{ +++ struct dst_entry *this_dst, *other_dst; +++ +++ this_dst = xt_flowoffload_dst(ct, !dir, par, xt_out(par)->ifindex); +++ other_dst = xt_flowoffload_dst(ct, dir, par, xt_in(par)->ifindex); +++ +++ route->tuple[dir].dst = this_dst; +++ route->tuple[!dir].dst = other_dst; +++ +++ if (!this_dst || !other_dst) +++ return -ENOENT; +++ +++ if (dst_xfrm(this_dst) || dst_xfrm(other_dst)) +++ return -EINVAL; +++ +++ return 0; +++} +++ +++static unsigned int +++flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par) +++{ +++ const struct xt_flowoffload_target_info *info = par->targinfo; +++ struct tcphdr _tcph, *tcph = NULL; +++ enum ip_conntrack_info ctinfo; +++ enum ip_conntrack_dir dir; +++ struct nf_flow_route route; +++ struct flow_offload *flow = NULL; +++ struct nf_conn *ct; +++ struct net *net; +++ +++ if (xt_flowoffload_skip(skb, xt_family(par))) +++ return XT_CONTINUE; +++ +++ ct = nf_ct_get(skb, &ctinfo); +++ if (ct == NULL) +++ return XT_CONTINUE; +++ +++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { +++ case IPPROTO_TCP: +++ if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) +++ return XT_CONTINUE; +++ +++ tcph = skb_header_pointer(skb, par->thoff, +++ sizeof(_tcph), &_tcph); +++ if (unlikely(!tcph || tcph->fin || tcph->rst)) +++ return XT_CONTINUE; +++ break; +++ case IPPROTO_UDP: +++ break; +++ default: +++ return XT_CONTINUE; +++ } +++ +++ if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) || +++ ct->status & IPS_SEQ_ADJUST) +++ return XT_CONTINUE; +++ +++ if (!nf_ct_is_confirmed(ct)) +++ return XT_CONTINUE; +++ +++ if (!xt_in(par) || !xt_out(par)) +++ return XT_CONTINUE; +++ +++ if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status)) +++ return XT_CONTINUE; +++ +++ dir = CTINFO2DIR(ctinfo); +++ +++ if (xt_flowoffload_route(skb, ct, par, &route, dir) == 0) +++ flow = flow_offload_alloc(ct, &route); +++ +++ dst_release(route.tuple[dir].dst); +++ dst_release(route.tuple[!dir].dst); +++ +++ if (!flow) +++ goto err_flow_route; +++ +++ if (tcph) { +++ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; +++ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; +++ } +++ +++ if (flow_offload_add(&nf_flowtable, flow) < 0) +++ goto err_flow_add; +++ +++ xt_flowoffload_check_device(xt_in(par)); +++ xt_flowoffload_check_device(xt_out(par)); +++ +++ net = read_pnet(&nf_flowtable.ft_net); +++ if (!net) +++ write_pnet(&nf_flowtable.ft_net, xt_net(par)); +++ +++ if (info->flags & XT_FLOWOFFLOAD_HW) +++ nf_flow_offload_hw_add(xt_net(par), flow, ct); +++ +++ return XT_CONTINUE; +++ +++err_flow_add: +++ flow_offload_free(flow); +++err_flow_route: +++ clear_bit(IPS_OFFLOAD_BIT, &ct->status); +++ return XT_CONTINUE; +++} +++ +++ +++static int flowoffload_chk(const struct xt_tgchk_param *par) +++{ +++ struct xt_flowoffload_target_info *info = par->targinfo; +++ +++ if (info->flags & ~XT_FLOWOFFLOAD_MASK) +++ return -EINVAL; +++ +++ return 0; +++} +++ +++static struct xt_target offload_tg_reg __read_mostly = { +++ .family = NFPROTO_UNSPEC, +++ .name = "FLOWOFFLOAD", +++ .revision = 0, +++ .targetsize = sizeof(struct xt_flowoffload_target_info), +++ .usersize = sizeof(struct xt_flowoffload_target_info), +++ .checkentry = flowoffload_chk, +++ .target = flowoffload_tg, +++ .me = THIS_MODULE, +++}; +++ +++static int xt_flowoffload_table_init(struct nf_flowtable *table) +++{ +++ table->flags = NF_FLOWTABLE_F_HW; +++ nf_flow_table_init(table); +++ return 0; +++} +++ +++static void xt_flowoffload_table_cleanup(struct nf_flowtable *table) +++{ +++ nf_flow_table_free(table); +++} +++ +++static int flow_offload_netdev_event(struct notifier_block *this, +++ unsigned long event, void *ptr) +++{ +++ struct xt_flowoffload_hook *hook = NULL; +++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); +++ +++ if (event != NETDEV_UNREGISTER) +++ return NOTIFY_DONE; +++ +++ spin_lock_bh(&hooks_lock); +++ hook = flow_offload_lookup_hook(dev); +++ if (hook) { +++ hlist_del(&hook->list); +++ } +++ spin_unlock_bh(&hooks_lock); +++ if (hook) { +++ nf_unregister_net_hook(hook->net, &hook->ops); +++ kfree(hook); +++ } +++ +++ nf_flow_table_cleanup(dev_net(dev), dev); +++ +++ return NOTIFY_DONE; +++} +++ +++static struct notifier_block flow_offload_netdev_notifier = { +++ .notifier_call = flow_offload_netdev_event, +++}; +++ +++static int __init xt_flowoffload_tg_init(void) +++{ +++ int ret; +++ +++ register_netdevice_notifier(&flow_offload_netdev_notifier); +++ +++ INIT_DELAYED_WORK(&hook_work, xt_flowoffload_hook_work); +++ +++ ret = xt_flowoffload_table_init(&nf_flowtable); +++ if (ret) +++ return ret; +++ +++ ret = xt_register_target(&offload_tg_reg); +++ if (ret) +++ xt_flowoffload_table_cleanup(&nf_flowtable); +++ +++ return ret; +++} +++ +++static void __exit xt_flowoffload_tg_exit(void) +++{ +++ xt_unregister_target(&offload_tg_reg); +++ xt_flowoffload_table_cleanup(&nf_flowtable); +++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); +++} +++ +++MODULE_LICENSE("GPL"); +++module_init(xt_flowoffload_tg_init); +++module_exit(xt_flowoffload_tg_exit); ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -6,7 +6,6 @@ ++ #include ++ #include ++ #include ++-#include ++ #include ++ #include ++ #include ++--- /dev/null +++++ b/include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h ++@@ -0,0 +1,17 @@ +++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +++#ifndef _XT_FLOWOFFLOAD_H +++#define _XT_FLOWOFFLOAD_H +++ +++#include +++ +++enum { +++ XT_FLOWOFFLOAD_HW = 1 << 0, +++ +++ XT_FLOWOFFLOAD_MASK = XT_FLOWOFFLOAD_HW +++}; +++ +++struct xt_flowoffload_target_info { +++ __u32 flags; +++}; +++ +++#endif /* _XT_FLOWOFFLOAD_H */ +diff --git a/target/linux/generic/hack-4.14/651-wireless_mesh_header.patch b/target/linux/generic/hack-4.14/651-wireless_mesh_header.patch +new file mode 100644 +index 0000000000..f545d8ebbc +--- /dev/null ++++ b/target/linux/generic/hack-4.14/651-wireless_mesh_header.patch +@@ -0,0 +1,24 @@ ++From 6d3bc769657b0ee7c7506dad9911111c4226a7ea Mon Sep 17 00:00:00 2001 ++From: Imre Kaloz ++Date: Fri, 7 Jul 2017 17:21:05 +0200 ++Subject: mac80211: increase wireless mesh header size ++ ++lede-commit 3d4466cfd8f75f717efdb1f96fdde3c70d865fc1 ++Signed-off-by: Imre Kaloz ++--- ++ include/linux/netdevice.h | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++--- a/include/linux/netdevice.h +++++ b/include/linux/netdevice.h ++@@ -138,8 +138,8 @@ static inline bool dev_xmit_complete(int ++ ++ #if defined(CONFIG_HYPERV_NET) ++ # define LL_MAX_HEADER 128 ++-#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) ++-# if defined(CONFIG_MAC80211_MESH) +++#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) || 1 +++# if defined(CONFIG_MAC80211_MESH) || 1 ++ # define LL_MAX_HEADER 128 ++ # else ++ # define LL_MAX_HEADER 96 +diff --git a/target/linux/generic/hack-4.14/660-fq_codel_defaults.patch b/target/linux/generic/hack-4.14/660-fq_codel_defaults.patch +new file mode 100644 +index 0000000000..b923a2d206 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/660-fq_codel_defaults.patch +@@ -0,0 +1,27 @@ ++From a6ccb238939b25851474a279b20367fd24a0e816 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:21:53 +0200 ++Subject: hack: net: fq_codel: tune defaults for small devices ++ ++Assume that x86_64 devices always have a big memory and do not need this ++optimization compared to devices with only 32 MB or 64 MB RAM. ++ ++Signed-off-by: Felix Fietkau ++--- ++ net/sched/sch_fq_codel.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/net/sched/sch_fq_codel.c +++++ b/net/sched/sch_fq_codel.c ++@@ -471,7 +471,11 @@ static int fq_codel_init(struct Qdisc *s ++ ++ sch->limit = 10*1024; ++ q->flows_cnt = 1024; +++#ifdef CONFIG_X86_64 ++ q->memory_limit = 32 << 20; /* 32 MBytes */ +++#else +++ q->memory_limit = 4 << 20; /* 4 MBytes */ +++#endif ++ q->drop_batch_size = 64; ++ q->quantum = psched_mtu(qdisc_dev(sch)); ++ INIT_LIST_HEAD(&q->new_flows); +diff --git a/target/linux/generic/hack-4.14/661-use_fq_codel_by_default.patch b/target/linux/generic/hack-4.14/661-use_fq_codel_by_default.patch +new file mode 100644 +index 0000000000..6a7d554c20 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/661-use_fq_codel_by_default.patch +@@ -0,0 +1,94 @@ ++From 1d418f7e88035ed7a94073f6354246c66e9193e9 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:22:58 +0200 ++Subject: fq_codel: switch default qdisc from pfifo_fast to fq_codel and remove pfifo_fast ++ ++Signed-off-by: Felix Fietkau ++--- ++ include/net/sch_generic.h | 3 ++- ++ net/sched/Kconfig | 3 ++- ++ net/sched/sch_api.c | 2 +- ++ net/sched/sch_fq_codel.c | 3 ++- ++ net/sched/sch_generic.c | 4 ++-- ++ 5 files changed, 9 insertions(+), 6 deletions(-) ++ ++--- a/include/net/sch_generic.h +++++ b/include/net/sch_generic.h ++@@ -373,12 +373,13 @@ extern struct Qdisc_ops noop_qdisc_ops; ++ extern struct Qdisc_ops pfifo_fast_ops; ++ extern struct Qdisc_ops mq_qdisc_ops; ++ extern struct Qdisc_ops noqueue_qdisc_ops; +++extern struct Qdisc_ops fq_codel_qdisc_ops; ++ extern const struct Qdisc_ops *default_qdisc_ops; ++ static inline const struct Qdisc_ops * ++ get_default_qdisc_ops(const struct net_device *dev, int ntx) ++ { ++ return ntx < dev->real_num_tx_queues ? ++- default_qdisc_ops : &pfifo_fast_ops; +++ default_qdisc_ops : &fq_codel_qdisc_ops; ++ } ++ ++ struct Qdisc_class_common { ++--- a/net/sched/Kconfig +++++ b/net/sched/Kconfig ++@@ -3,8 +3,9 @@ ++ # ++ ++ menuconfig NET_SCHED ++- bool "QoS and/or fair queueing" +++ def_bool y ++ select NET_SCH_FIFO +++ select NET_SCH_FQ_CODEL ++ ---help--- ++ When the kernel has several packets to send out over a network ++ device, it has to decide which ones to send first, which ones to ++--- a/net/sched/sch_api.c +++++ b/net/sched/sch_api.c ++@@ -2031,7 +2031,7 @@ static int __init pktsched_init(void) ++ return err; ++ } ++ ++- register_qdisc(&pfifo_fast_ops); +++ register_qdisc(&fq_codel_qdisc_ops); ++ register_qdisc(&pfifo_qdisc_ops); ++ register_qdisc(&bfifo_qdisc_ops); ++ register_qdisc(&pfifo_head_drop_qdisc_ops); ++--- a/net/sched/sch_fq_codel.c +++++ b/net/sched/sch_fq_codel.c ++@@ -700,7 +700,7 @@ static const struct Qdisc_class_ops fq_c ++ .walk = fq_codel_walk, ++ }; ++ ++-static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = { +++struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = { ++ .cl_ops = &fq_codel_class_ops, ++ .id = "fq_codel", ++ .priv_size = sizeof(struct fq_codel_sched_data), ++@@ -715,6 +715,7 @@ static struct Qdisc_ops fq_codel_qdisc_o ++ .dump_stats = fq_codel_dump_stats, ++ .owner = THIS_MODULE, ++ }; +++EXPORT_SYMBOL(fq_codel_qdisc_ops); ++ ++ static int __init fq_codel_module_init(void) ++ { ++--- a/net/sched/sch_generic.c +++++ b/net/sched/sch_generic.c ++@@ -32,7 +32,7 @@ ++ #include ++ ++ /* Qdisc to use by default */ ++-const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops; +++const struct Qdisc_ops *default_qdisc_ops = &fq_codel_qdisc_ops; ++ EXPORT_SYMBOL(default_qdisc_ops); ++ ++ /* Main transmission queue. */ ++@@ -765,7 +765,7 @@ static void attach_one_default_qdisc(str ++ void *_unused) ++ { ++ struct Qdisc *qdisc; ++- const struct Qdisc_ops *ops = default_qdisc_ops; +++ const struct Qdisc_ops *ops = &fq_codel_qdisc_ops; ++ ++ if (dev->priv_flags & IFF_NO_QUEUE) ++ ops = &noqueue_qdisc_ops; +diff --git a/target/linux/generic/hack-4.14/662-remove_pfifo_fast.patch b/target/linux/generic/hack-4.14/662-remove_pfifo_fast.patch +new file mode 100644 +index 0000000000..d1a17a4bac +--- /dev/null ++++ b/target/linux/generic/hack-4.14/662-remove_pfifo_fast.patch +@@ -0,0 +1,159 @@ ++From b531d492d5ef1cf9dba0f4888eb5fd8624a6d762 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:23:42 +0200 ++Subject: net: sched: switch default qdisc from pfifo_fast to fq_codel and remove pfifo_fast ++ ++Signed-off-by: Felix Fietkau ++--- ++ net/sched/sch_generic.c | 140 ------------------------------------------------ ++ 1 file changed, 140 deletions(-) ++ ++--- a/net/sched/sch_generic.c +++++ b/net/sched/sch_generic.c ++@@ -454,146 +454,6 @@ struct Qdisc_ops noqueue_qdisc_ops __rea ++ .owner = THIS_MODULE, ++ }; ++ ++-static const u8 prio2band[TC_PRIO_MAX + 1] = { ++- 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 ++-}; ++- ++-/* 3-band FIFO queue: old style, but should be a bit faster than ++- generic prio+fifo combination. ++- */ ++- ++-#define PFIFO_FAST_BANDS 3 ++- ++-/* ++- * Private data for a pfifo_fast scheduler containing: ++- * - queues for the three band ++- * - bitmap indicating which of the bands contain skbs ++- */ ++-struct pfifo_fast_priv { ++- u32 bitmap; ++- struct qdisc_skb_head q[PFIFO_FAST_BANDS]; ++-}; ++- ++-/* ++- * Convert a bitmap to the first band number where an skb is queued, where: ++- * bitmap=0 means there are no skbs on any band. ++- * bitmap=1 means there is an skb on band 0. ++- * bitmap=7 means there are skbs on all 3 bands, etc. ++- */ ++-static const int bitmap2band[] = {-1, 0, 1, 0, 2, 0, 1, 0}; ++- ++-static inline struct qdisc_skb_head *band2list(struct pfifo_fast_priv *priv, ++- int band) ++-{ ++- return priv->q + band; ++-} ++- ++-static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc, ++- struct sk_buff **to_free) ++-{ ++- if (qdisc->q.qlen < qdisc_dev(qdisc)->tx_queue_len) { ++- int band = prio2band[skb->priority & TC_PRIO_MAX]; ++- struct pfifo_fast_priv *priv = qdisc_priv(qdisc); ++- struct qdisc_skb_head *list = band2list(priv, band); ++- ++- priv->bitmap |= (1 << band); ++- qdisc->q.qlen++; ++- return __qdisc_enqueue_tail(skb, qdisc, list); ++- } ++- ++- return qdisc_drop(skb, qdisc, to_free); ++-} ++- ++-static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *qdisc) ++-{ ++- struct pfifo_fast_priv *priv = qdisc_priv(qdisc); ++- int band = bitmap2band[priv->bitmap]; ++- ++- if (likely(band >= 0)) { ++- struct qdisc_skb_head *qh = band2list(priv, band); ++- struct sk_buff *skb = __qdisc_dequeue_head(qh); ++- ++- if (likely(skb != NULL)) { ++- qdisc_qstats_backlog_dec(qdisc, skb); ++- qdisc_bstats_update(qdisc, skb); ++- } ++- ++- qdisc->q.qlen--; ++- if (qh->qlen == 0) ++- priv->bitmap &= ~(1 << band); ++- ++- return skb; ++- } ++- ++- return NULL; ++-} ++- ++-static struct sk_buff *pfifo_fast_peek(struct Qdisc *qdisc) ++-{ ++- struct pfifo_fast_priv *priv = qdisc_priv(qdisc); ++- int band = bitmap2band[priv->bitmap]; ++- ++- if (band >= 0) { ++- struct qdisc_skb_head *qh = band2list(priv, band); ++- ++- return qh->head; ++- } ++- ++- return NULL; ++-} ++- ++-static void pfifo_fast_reset(struct Qdisc *qdisc) ++-{ ++- int prio; ++- struct pfifo_fast_priv *priv = qdisc_priv(qdisc); ++- ++- for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) ++- __qdisc_reset_queue(band2list(priv, prio)); ++- ++- priv->bitmap = 0; ++- qdisc->qstats.backlog = 0; ++- qdisc->q.qlen = 0; ++-} ++- ++-static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb) ++-{ ++- struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS }; ++- ++- memcpy(&opt.priomap, prio2band, TC_PRIO_MAX + 1); ++- if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt)) ++- goto nla_put_failure; ++- return skb->len; ++- ++-nla_put_failure: ++- return -1; ++-} ++- ++-static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt) ++-{ ++- int prio; ++- struct pfifo_fast_priv *priv = qdisc_priv(qdisc); ++- ++- for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) ++- qdisc_skb_head_init(band2list(priv, prio)); ++- ++- /* Can by-pass the queue discipline */ ++- qdisc->flags |= TCQ_F_CAN_BYPASS; ++- return 0; ++-} ++- ++-struct Qdisc_ops pfifo_fast_ops __read_mostly = { ++- .id = "pfifo_fast", ++- .priv_size = sizeof(struct pfifo_fast_priv), ++- .enqueue = pfifo_fast_enqueue, ++- .dequeue = pfifo_fast_dequeue, ++- .peek = pfifo_fast_peek, ++- .init = pfifo_fast_init, ++- .reset = pfifo_fast_reset, ++- .dump = pfifo_fast_dump, ++- .owner = THIS_MODULE, ++-}; ++-EXPORT_SYMBOL(pfifo_fast_ops); ++- ++ static struct lock_class_key qdisc_tx_busylock; ++ static struct lock_class_key qdisc_running_key; ++ +diff --git a/target/linux/generic/hack-4.14/700-swconfig_switch_drivers.patch b/target/linux/generic/hack-4.14/700-swconfig_switch_drivers.patch +new file mode 100644 +index 0000000000..f9df475500 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/700-swconfig_switch_drivers.patch +@@ -0,0 +1,140 @@ ++From 36e516290611e613aa92996cb4339561452695b4 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:24:23 +0200 ++Subject: net: swconfig: adds openwrt switch layer ++ ++Signed-off-by: Felix Fietkau ++--- ++ drivers/net/phy/Kconfig | 83 +++++++++++++++++++++++++++++++++++++++++++++++ ++ drivers/net/phy/Makefile | 15 +++++++++ ++ include/uapi/linux/Kbuild | 1 + ++ 3 files changed, 99 insertions(+) ++ ++--- a/drivers/net/phy/Kconfig +++++ b/drivers/net/phy/Kconfig ++@@ -198,6 +198,89 @@ config LED_TRIGGER_PHY ++ Mbps or Gbps ++ ++ +++comment "Switch configuration API + drivers" +++ +++config SWCONFIG +++ tristate "Switch configuration API" +++ ---help--- +++ Switch configuration API using netlink. This allows +++ you to configure the VLAN features of certain switches. +++ +++config SWCONFIG_LEDS +++ bool "Switch LED trigger support" +++ depends on (SWCONFIG && LEDS_TRIGGERS) +++ +++config ADM6996_PHY +++ tristate "Driver for ADM6996 switches" +++ select SWCONFIG +++ ---help--- +++ Currently supports the ADM6996FC and ADM6996M switches. +++ Support for FC is very limited. +++ +++config AR8216_PHY +++ tristate "Driver for Atheros AR8216 switches" +++ select ETHERNET_PACKET_MANGLE +++ select SWCONFIG +++ +++config AR8216_PHY_LEDS +++ bool "Atheros AR8216 switch LED support" +++ depends on (AR8216_PHY && LEDS_CLASS) +++ +++source "drivers/net/phy/b53/Kconfig" +++ +++config IP17XX_PHY +++ tristate "Driver for IC+ IP17xx switches" +++ select SWCONFIG +++ +++config MVSWITCH_PHY +++ tristate "Driver for Marvell 88E6060 switches" +++ select ETHERNET_PACKET_MANGLE +++ +++config MVSW61XX_PHY +++ tristate "Driver for Marvell 88E6171/6172 switches" +++ select SWCONFIG +++ +++config PSB6970_PHY +++ tristate "Lantiq XWAY Tantos (PSB6970) Ethernet switch" +++ select SWCONFIG +++ select ETHERNET_PACKET_MANGLE +++ +++config RTL8306_PHY +++ tristate "Driver for Realtek RTL8306S switches" +++ select SWCONFIG +++ +++config RTL8366_SMI +++ tristate "Driver for the RTL8366 SMI interface" +++ depends on GPIOLIB +++ ---help--- +++ This module implements the SMI interface protocol which is used +++ by some RTL8366 ethernet switch devices via the generic GPIO API. +++ +++if RTL8366_SMI +++ +++config RTL8366_SMI_DEBUG_FS +++ bool "RTL8366 SMI interface debugfs support" +++ depends on DEBUG_FS +++ default n +++ +++config RTL8366S_PHY +++ tristate "Driver for the Realtek RTL8366S switch" +++ select SWCONFIG +++ +++config RTL8366RB_PHY +++ tristate "Driver for the Realtek RTL8366RB switch" +++ select SWCONFIG +++ +++config RTL8367_PHY +++ tristate "Driver for the Realtek RTL8367R/M switches" +++ select SWCONFIG +++ +++config RTL8367B_PHY +++ tristate "Driver fot the Realtek RTL8367R-VB switch" +++ select SWCONFIG +++ +++endif # RTL8366_SMI +++ ++ comment "MII PHY device drivers" ++ ++ config SFP ++--- a/drivers/net/phy/Makefile +++++ b/drivers/net/phy/Makefile ++@@ -22,6 +22,21 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_ ++ obj-$(CONFIG_PHYLINK) += phylink.o ++ obj-$(CONFIG_PHYLIB) += libphy.o ++ +++obj-$(CONFIG_SWCONFIG) += swconfig.o +++obj-$(CONFIG_ADM6996_PHY) += adm6996.o +++obj-$(CONFIG_AR8216_PHY) += ar8216.o ar8327.o +++obj-$(CONFIG_SWCONFIG_B53) += b53/ +++obj-$(CONFIG_IP17XX_PHY) += ip17xx.o +++obj-$(CONFIG_MVSWITCH_PHY) += mvswitch.o +++obj-$(CONFIG_MVSW61XX_PHY) += mvsw61xx.o +++obj-$(CONFIG_PSB6970_PHY) += psb6970.o +++obj-$(CONFIG_RTL8306_PHY) += rtl8306.o +++obj-$(CONFIG_RTL8366_SMI) += rtl8366_smi.o +++obj-$(CONFIG_RTL8366S_PHY) += rtl8366s.o +++obj-$(CONFIG_RTL8366RB_PHY) += rtl8366rb.o +++obj-$(CONFIG_RTL8367_PHY) += rtl8367.o +++obj-$(CONFIG_RTL8367B_PHY) += rtl8367b.o +++ ++ obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o ++ obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o ++ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o ++--- a/include/linux/platform_data/b53.h +++++ b/include/linux/platform_data/b53.h ++@@ -25,6 +25,9 @@ struct b53_platform_data { ++ u32 chip_id; ++ u16 enabled_ports; ++ +++ /* allow to specify an ethX alias */ +++ const char *alias; +++ ++ /* only used by MMAP'd driver */ ++ unsigned big_endian:1; ++ void __iomem *regs; +diff --git a/target/linux/generic/hack-4.14/702-phy_add_aneg_done_function.patch b/target/linux/generic/hack-4.14/702-phy_add_aneg_done_function.patch +new file mode 100644 +index 0000000000..5885c8fae6 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/702-phy_add_aneg_done_function.patch +@@ -0,0 +1,27 @@ ++--- a/include/linux/phy.h +++++ b/include/linux/phy.h ++@@ -549,6 +549,12 @@ struct phy_driver { ++ /* Determines the negotiated speed and duplex */ ++ int (*read_status)(struct phy_device *phydev); ++ +++ /* +++ * Update the value in phydev->link to reflect the +++ * current link value +++ */ +++ int (*update_link)(struct phy_device *phydev); +++ ++ /* Clears any pending interrupts */ ++ int (*ack_interrupt)(struct phy_device *phydev); ++ ++--- a/drivers/net/phy/phy_device.c +++++ b/drivers/net/phy/phy_device.c ++@@ -1466,6 +1466,9 @@ int genphy_update_link(struct phy_device ++ { ++ int status; ++ +++ if (phydev->drv && phydev->drv->update_link) +++ return phydev->drv->update_link(phydev); +++ ++ /* Do a fake read */ ++ status = phy_read(phydev, MII_BMSR); ++ if (status < 0) +diff --git a/target/linux/generic/hack-4.14/721-phy_packets.patch b/target/linux/generic/hack-4.14/721-phy_packets.patch +new file mode 100644 +index 0000000000..d67171054d +--- /dev/null ++++ b/target/linux/generic/hack-4.14/721-phy_packets.patch +@@ -0,0 +1,176 @@ ++From ffe387740bbe88dd88bbe04d6375902708003d6e Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Fri, 7 Jul 2017 17:25:00 +0200 ++Subject: net: add packet mangeling patch ++ ++Signed-off-by: Felix Fietkau ++--- ++ include/linux/netdevice.h | 11 +++++++++++ ++ include/linux/skbuff.h | 14 ++++---------- ++ net/Kconfig | 6 ++++++ ++ net/core/dev.c | 18 ++++++++++++++---- ++ net/core/skbuff.c | 17 +++++++++++++++++ ++ net/ethernet/eth.c | 6 ++++++ ++ 6 files changed, 58 insertions(+), 14 deletions(-) ++ ++--- a/include/linux/netdevice.h +++++ b/include/linux/netdevice.h ++@@ -1415,6 +1415,7 @@ enum netdev_priv_flags { ++ IFF_PHONY_HEADROOM = 1<<26, ++ IFF_MACSEC = 1<<27, ++ IFF_L3MDEV_RX_HANDLER = 1<<28, +++ IFF_NO_IP_ALIGN = 1<<29, ++ }; ++ ++ #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN ++@@ -1445,6 +1446,7 @@ enum netdev_priv_flags { ++ #define IFF_RXFH_CONFIGURED IFF_RXFH_CONFIGURED ++ #define IFF_MACSEC IFF_MACSEC ++ #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER +++#define IFF_NO_IP_ALIGN IFF_NO_IP_ALIGN ++ ++ /** ++ * struct net_device - The DEVICE structure. ++@@ -1731,6 +1733,11 @@ struct net_device { ++ const struct xfrmdev_ops *xfrmdev_ops; ++ #endif ++ +++#ifdef CONFIG_ETHERNET_PACKET_MANGLE +++ void (*eth_mangle_rx)(struct net_device *dev, struct sk_buff *skb); +++ struct sk_buff *(*eth_mangle_tx)(struct net_device *dev, struct sk_buff *skb); +++#endif +++ ++ const struct header_ops *header_ops; ++ ++ unsigned int flags; ++@@ -1805,6 +1812,10 @@ struct net_device { ++ struct mpls_dev __rcu *mpls_ptr; ++ #endif ++ +++#ifdef CONFIG_ETHERNET_PACKET_MANGLE +++ void *phy_ptr; /* PHY device specific data */ +++#endif +++ ++ /* ++ * Cache lines mostly used on receive path (including eth_type_trans()) ++ */ ++--- a/include/linux/skbuff.h +++++ b/include/linux/skbuff.h ++@@ -2532,6 +2532,10 @@ static inline int pskb_trim(struct sk_bu ++ return (len < skb->len) ? __pskb_trim(skb, len) : 0; ++ } ++ +++extern struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, +++ unsigned int length, gfp_t gfp); +++ +++ ++ /** ++ * pskb_trim_unique - remove end from a paged unique (not cloned) buffer ++ * @skb: buffer to alter ++@@ -2663,16 +2667,6 @@ static inline struct sk_buff *dev_alloc_ ++ } ++ ++ ++-static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, ++- unsigned int length, gfp_t gfp) ++-{ ++- struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); ++- ++- if (NET_IP_ALIGN && skb) ++- skb_reserve(skb, NET_IP_ALIGN); ++- return skb; ++-} ++- ++ static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev, ++ unsigned int length) ++ { ++--- a/net/Kconfig +++++ b/net/Kconfig ++@@ -25,6 +25,12 @@ menuconfig NET ++ ++ if NET ++ +++config ETHERNET_PACKET_MANGLE +++ bool +++ help +++ This option can be selected by phy drivers that need to mangle +++ packets going in or out of an ethernet device. +++ ++ config WANT_COMPAT_NETLINK_MESSAGES ++ bool ++ help ++--- a/net/core/dev.c +++++ b/net/core/dev.c ++@@ -3001,10 +3001,20 @@ static int xmit_one(struct sk_buff *skb, ++ if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all)) ++ dev_queue_xmit_nit(skb, dev); ++ ++- len = skb->len; ++- trace_net_dev_start_xmit(skb, dev); ++- rc = netdev_start_xmit(skb, dev, txq, more); ++- trace_net_dev_xmit(skb, rc, dev, len); +++#ifdef CONFIG_ETHERNET_PACKET_MANGLE +++ if (!dev->eth_mangle_tx || +++ (skb = dev->eth_mangle_tx(dev, skb)) != NULL) +++#else +++ if (1) +++#endif +++ { +++ len = skb->len; +++ trace_net_dev_start_xmit(skb, dev); +++ rc = netdev_start_xmit(skb, dev, txq, more); +++ trace_net_dev_xmit(skb, rc, dev, len); +++ } else { +++ rc = NETDEV_TX_OK; +++ } ++ ++ return rc; ++ } ++--- a/net/core/skbuff.c +++++ b/net/core/skbuff.c ++@@ -63,6 +63,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include ++ #include ++@@ -503,6 +504,22 @@ skb_fail: ++ } ++ EXPORT_SYMBOL(__napi_alloc_skb); ++ +++struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, +++ unsigned int length, gfp_t gfp) +++{ +++ struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); +++ +++#ifdef CONFIG_ETHERNET_PACKET_MANGLE +++ if (dev && (dev->priv_flags & IFF_NO_IP_ALIGN)) +++ return skb; +++#endif +++ +++ if (NET_IP_ALIGN && skb) +++ skb_reserve(skb, NET_IP_ALIGN); +++ return skb; +++} +++EXPORT_SYMBOL(__netdev_alloc_skb_ip_align); +++ ++ void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, ++ int size, unsigned int truesize) ++ { ++--- a/net/ethernet/eth.c +++++ b/net/ethernet/eth.c ++@@ -172,6 +172,12 @@ __be16 eth_type_trans(struct sk_buff *sk ++ const struct ethhdr *eth; ++ ++ skb->dev = dev; +++ +++#ifdef CONFIG_ETHERNET_PACKET_MANGLE +++ if (dev->eth_mangle_rx) +++ dev->eth_mangle_rx(dev, skb); +++#endif +++ ++ skb_reset_mac_header(skb); ++ ++ eth = (struct ethhdr *)skb->data; +diff --git a/target/linux/generic/hack-4.14/773-bgmac-add-srab-switch.patch b/target/linux/generic/hack-4.14/773-bgmac-add-srab-switch.patch +new file mode 100644 +index 0000000000..33a18a8352 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/773-bgmac-add-srab-switch.patch +@@ -0,0 +1,98 @@ ++From 3cb240533ab787899dc7f17aa7d6c5b4810e2e58 Mon Sep 17 00:00:00 2001 ++From: Hauke Mehrtens ++Date: Fri, 7 Jul 2017 17:26:01 +0200 ++Subject: bcm53xx: bgmac: use srab switch driver ++ ++use the srab switch driver on these SoCs. ++ ++Signed-off-by: Hauke Mehrtens ++--- ++ drivers/net/ethernet/broadcom/bgmac-bcma.c | 1 + ++ drivers/net/ethernet/broadcom/bgmac.c | 24 ++++++++++++++++++++++++ ++ drivers/net/ethernet/broadcom/bgmac.h | 4 ++++ ++ 3 files changed, 29 insertions(+) ++ ++--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c +++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c ++@@ -268,6 +268,7 @@ static int bgmac_probe(struct bcma_devic ++ bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; ++ bgmac->feature_flags |= BGMAC_FEAT_NO_RESET; ++ bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500; +++ bgmac->feature_flags |= BGMAC_FEAT_SRAB; ++ break; ++ default: ++ bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; ++--- a/drivers/net/ethernet/broadcom/bgmac.c +++++ b/drivers/net/ethernet/broadcom/bgmac.c ++@@ -12,6 +12,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -1410,6 +1411,17 @@ static const struct ethtool_ops bgmac_et ++ .set_link_ksettings = phy_ethtool_set_link_ksettings, ++ }; ++ +++static struct b53_platform_data bgmac_b53_pdata = { +++}; +++ +++static struct platform_device bgmac_b53_dev = { +++ .name = "b53-srab-switch", +++ .id = -1, +++ .dev = { +++ .platform_data = &bgmac_b53_pdata, +++ }, +++}; +++ ++ /************************************************** ++ * MII ++ **************************************************/ ++@@ -1539,6 +1551,14 @@ int bgmac_enet_probe(struct bgmac *bgmac ++ net_dev->hw_features = net_dev->features; ++ net_dev->vlan_features = net_dev->features; ++ +++ if ((bgmac->feature_flags & BGMAC_FEAT_SRAB) && !bgmac_b53_pdata.regs) { +++ bgmac_b53_pdata.regs = ioremap_nocache(0x18007000, 0x1000); +++ +++ err = platform_device_register(&bgmac_b53_dev); +++ if (!err) +++ bgmac->b53_device = &bgmac_b53_dev; +++ } +++ ++ err = register_netdev(bgmac->net_dev); ++ if (err) { ++ dev_err(bgmac->dev, "Cannot register net device\n"); ++@@ -1561,6 +1581,10 @@ EXPORT_SYMBOL_GPL(bgmac_enet_probe); ++ ++ void bgmac_enet_remove(struct bgmac *bgmac) ++ { +++ if (bgmac->b53_device) +++ platform_device_unregister(&bgmac_b53_dev); +++ bgmac->b53_device = NULL; +++ ++ unregister_netdev(bgmac->net_dev); ++ phy_disconnect(bgmac->net_dev->phydev); ++ netif_napi_del(&bgmac->napi); ++--- a/drivers/net/ethernet/broadcom/bgmac.h +++++ b/drivers/net/ethernet/broadcom/bgmac.h ++@@ -427,6 +427,7 @@ ++ #define BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII BIT(18) ++ #define BGMAC_FEAT_CC7_IF_TYPE_RGMII BIT(19) ++ #define BGMAC_FEAT_IDM_MASK BIT(20) +++#define BGMAC_FEAT_SRAB BIT(21) ++ ++ struct bgmac_slot_info { ++ union { ++@@ -532,6 +533,9 @@ struct bgmac { ++ void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask, ++ u32 set); ++ int (*phy_connect)(struct bgmac *bgmac); +++ +++ /* platform device for associated switch */ +++ struct platform_device *b53_device; ++ }; ++ ++ struct bgmac *bgmac_alloc(struct device *dev); +diff --git a/target/linux/generic/hack-4.14/901-debloat_sock_diag.patch b/target/linux/generic/hack-4.14/901-debloat_sock_diag.patch +new file mode 100644 +index 0000000000..2f2b8eb705 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/901-debloat_sock_diag.patch +@@ -0,0 +1,136 @@ ++From 3b6115d6b57a263bdc8c9b1df273bd4a7955eead Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sat, 8 Jul 2017 08:16:31 +0200 ++Subject: debloat: add some debloat patches, strip down procfs and make O_DIRECT support optional, saves ~15K after lzma on MIPS ++ ++Signed-off-by: Felix Fietkau ++--- ++ net/Kconfig | 3 +++ ++ net/core/Makefile | 3 ++- ++ net/core/sock.c | 2 ++ ++ net/ipv4/Kconfig | 1 + ++ net/netlink/Kconfig | 1 + ++ net/packet/Kconfig | 1 + ++ net/unix/Kconfig | 1 + ++ 7 files changed, 11 insertions(+), 1 deletion(-) ++ ++--- a/net/Kconfig +++++ b/net/Kconfig ++@@ -97,6 +97,9 @@ source "net/netlabel/Kconfig" ++ ++ endif # if INET ++ +++config SOCK_DIAG +++ bool +++ ++ config NETWORK_SECMARK ++ bool "Security Marking" ++ help ++--- a/net/core/Makefile +++++ b/net/core/Makefile ++@@ -10,9 +10,10 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core. ++ ++ obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ ++ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ ++- sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ +++ dev_ioctl.o tso.o sock_reuseport.o \ ++ fib_notifier.o ++ +++obj-$(CONFIG_SOCK_DIAG) += sock_diag.o ++ obj-y += net-sysfs.o ++ obj-$(CONFIG_PROC_FS) += net-procfs.o ++ obj-$(CONFIG_NET_PKTGEN) += pktgen.o ++--- a/net/core/sock.c +++++ b/net/core/sock.c ++@@ -528,6 +528,18 @@ discard_and_relse: ++ } ++ EXPORT_SYMBOL(__sk_receive_skb); ++ +++u64 sock_gen_cookie(struct sock *sk) +++{ +++ while (1) { +++ u64 res = atomic64_read(&sk->sk_cookie); +++ +++ if (res) +++ return res; +++ res = atomic64_inc_return(&sock_net(sk)->cookie_gen); +++ atomic64_cmpxchg(&sk->sk_cookie, 0, res); +++ } +++} +++ ++ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) ++ { ++ struct dst_entry *dst = __sk_dst_get(sk); ++@@ -1599,9 +1611,11 @@ void sk_destruct(struct sock *sk) ++ ++ static void __sk_free(struct sock *sk) ++ { +++#ifdef CONFIG_SOCK_DIAG ++ if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk))) ++ sock_diag_broadcast_destroy(sk); ++ else +++#endif ++ sk_destruct(sk); ++ } ++ ++--- a/net/core/sock_diag.c +++++ b/net/core/sock_diag.c ++@@ -19,18 +19,6 @@ static int (*inet_rcv_compat)(struct sk_ ++ static DEFINE_MUTEX(sock_diag_table_mutex); ++ static struct workqueue_struct *broadcast_wq; ++ ++-u64 sock_gen_cookie(struct sock *sk) ++-{ ++- while (1) { ++- u64 res = atomic64_read(&sk->sk_cookie); ++- ++- if (res) ++- return res; ++- res = atomic64_inc_return(&sock_net(sk)->cookie_gen); ++- atomic64_cmpxchg(&sk->sk_cookie, 0, res); ++- } ++-} ++- ++ int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie) ++ { ++ u64 res; ++--- a/net/ipv4/Kconfig +++++ b/net/ipv4/Kconfig ++@@ -421,6 +421,7 @@ config INET_XFRM_MODE_BEET ++ ++ config INET_DIAG ++ tristate "INET: socket monitoring interface" +++ select SOCK_DIAG ++ default y ++ ---help--- ++ Support for INET (TCP, DCCP, etc) socket monitoring interface used by ++--- a/net/netlink/Kconfig +++++ b/net/netlink/Kconfig ++@@ -4,6 +4,7 @@ ++ ++ config NETLINK_DIAG ++ tristate "NETLINK: socket monitoring interface" +++ select SOCK_DIAG ++ default n ++ ---help--- ++ Support for NETLINK socket monitoring interface used by the ss tool. ++--- a/net/packet/Kconfig +++++ b/net/packet/Kconfig ++@@ -18,6 +18,7 @@ config PACKET ++ config PACKET_DIAG ++ tristate "Packet: sockets monitoring interface" ++ depends on PACKET +++ select SOCK_DIAG ++ default n ++ ---help--- ++ Support for PF_PACKET sockets monitoring interface used by the ss tool. ++--- a/net/unix/Kconfig +++++ b/net/unix/Kconfig ++@@ -22,6 +22,7 @@ config UNIX ++ config UNIX_DIAG ++ tristate "UNIX: socket monitoring interface" ++ depends on UNIX +++ select SOCK_DIAG ++ default n ++ ---help--- ++ Support for UNIX socket monitoring interface used by the ss tool. +diff --git a/target/linux/generic/hack-4.14/902-debloat_proc.patch b/target/linux/generic/hack-4.14/902-debloat_proc.patch +new file mode 100644 +index 0000000000..3cf89b7421 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/902-debloat_proc.patch +@@ -0,0 +1,405 @@ ++From 9e3f1d0805b2d919904dd9a4ff0d956314cc3cba Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sat, 8 Jul 2017 08:20:09 +0200 ++Subject: debloat: procfs ++ ++Signed-off-by: Felix Fietkau ++--- ++ fs/locks.c | 2 ++ ++ fs/proc/Kconfig | 5 +++++ ++ fs/proc/consoles.c | 3 +++ ++ fs/proc/proc_tty.c | 11 ++++++++++- ++ include/net/snmp.h | 18 +++++++++++++++++- ++ ipc/msg.c | 3 +++ ++ ipc/sem.c | 2 ++ ++ ipc/shm.c | 2 ++ ++ ipc/util.c | 3 +++ ++ kernel/exec_domain.c | 2 ++ ++ kernel/irq/proc.c | 9 +++++++++ ++ kernel/time/timer_list.c | 2 ++ ++ mm/vmalloc.c | 2 ++ ++ mm/vmstat.c | 8 +++++--- ++ net/8021q/vlanproc.c | 6 ++++++ ++ net/core/net-procfs.c | 18 ++++++++++++------ ++ net/core/sock.c | 2 ++ ++ net/ipv4/fib_trie.c | 18 ++++++++++++------ ++ net/ipv4/proc.c | 3 +++ ++ net/ipv4/route.c | 3 +++ ++ 20 files changed, 105 insertions(+), 17 deletions(-) ++ ++--- a/fs/locks.c +++++ b/fs/locks.c ++@@ -2812,6 +2812,8 @@ static const struct file_operations proc ++ ++ static int __init proc_locks_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; ++ proc_create("locks", 0, NULL, &proc_locks_operations); ++ return 0; ++ } ++--- a/fs/proc/Kconfig +++++ b/fs/proc/Kconfig ++@@ -81,3 +81,8 @@ config PROC_CHILDREN ++ ++ Say Y if you are running any user-space software which takes benefit from ++ this interface. For example, rkt is such a piece of software. +++ +++config PROC_STRIPPED +++ default n +++ depends on EXPERT +++ bool "Strip non-essential /proc functionality to reduce code size" ++--- a/fs/proc/consoles.c +++++ b/fs/proc/consoles.c ++@@ -106,6 +106,9 @@ static const struct file_operations proc ++ ++ static int __init proc_consoles_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; +++ ++ proc_create("consoles", 0, NULL, &proc_consoles_operations); ++ return 0; ++ } ++--- a/fs/proc/proc_tty.c +++++ b/fs/proc/proc_tty.c ++@@ -145,7 +145,10 @@ static const struct file_operations proc ++ void proc_tty_register_driver(struct tty_driver *driver) ++ { ++ struct proc_dir_entry *ent; ++- +++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return; +++ ++ if (!driver->driver_name || driver->proc_entry || ++ !driver->ops->proc_fops) ++ return; ++@@ -162,6 +165,9 @@ void proc_tty_unregister_driver(struct t ++ { ++ struct proc_dir_entry *ent; ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return; +++ ++ ent = driver->proc_entry; ++ if (!ent) ++ return; ++@@ -176,6 +182,9 @@ void proc_tty_unregister_driver(struct t ++ */ ++ void __init proc_tty_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return; +++ ++ if (!proc_mkdir("tty", NULL)) ++ return; ++ proc_mkdir("tty/ldisc", NULL); /* Preserved: it's userspace visible */ ++--- a/include/net/snmp.h +++++ b/include/net/snmp.h ++@@ -123,6 +123,21 @@ struct linux_xfrm_mib { ++ #define DECLARE_SNMP_STAT(type, name) \ ++ extern __typeof__(type) __percpu *name ++ +++#ifdef CONFIG_PROC_STRIPPED +++#define __SNMP_STATS_DUMMY(mib) \ +++ do { (void) mib->mibs[0]; } while(0) +++ +++#define __SNMP_INC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) +++#define SNMP_INC_STATS_ATOMIC_LONG(mib, field) __SNMP_STATS_DUMMY(mib) +++#define SNMP_INC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) +++#define SNMP_DEC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) +++#define __SNMP_ADD_STATS(mib, field, addend) __SNMP_STATS_DUMMY(mib) +++#define SNMP_ADD_STATS(mib, field, addend) __SNMP_STATS_DUMMY(mib) +++#define SNMP_UPD_PO_STATS(mib, basefield, addend) __SNMP_STATS_DUMMY(mib) +++#define __SNMP_UPD_PO_STATS(mib, basefield, addend) __SNMP_STATS_DUMMY(mib) +++ +++#else +++ ++ #define __SNMP_INC_STATS(mib, field) \ ++ __this_cpu_inc(mib->mibs[field]) ++ ++@@ -153,8 +168,9 @@ struct linux_xfrm_mib { ++ __this_cpu_add(ptr[basefield##OCTETS], addend); \ ++ } while (0) ++ +++#endif ++ ++-#if BITS_PER_LONG==32 +++#if (BITS_PER_LONG==32) && !defined(CONFIG_PROC_STRIPPED) ++ ++ #define __SNMP_ADD_STATS64(mib, field, addend) \ ++ do { \ ++--- a/ipc/msg.c +++++ b/ipc/msg.c ++@@ -1208,6 +1208,9 @@ int __init msg_init(void) ++ { ++ const int err = msg_init_ns(&init_ipc_ns); ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return err; +++ ++ ipc_init_proc_interface("sysvipc/msg", ++ " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", ++ IPC_MSG_IDS, sysvipc_msg_proc_show); ++--- a/ipc/sem.c +++++ b/ipc/sem.c ++@@ -207,6 +207,8 @@ int __init sem_init(void) ++ { ++ const int err = sem_init_ns(&init_ipc_ns); ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return err; ++ ipc_init_proc_interface("sysvipc/sem", ++ " key semid perms nsems uid gid cuid cgid otime ctime\n", ++ IPC_SEM_IDS, sysvipc_sem_proc_show); ++--- a/ipc/shm.c +++++ b/ipc/shm.c ++@@ -122,6 +122,8 @@ pure_initcall(ipc_ns_init); ++ ++ void __init shm_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return; ++ ipc_init_proc_interface("sysvipc/shm", ++ #if BITS_PER_LONG <= 32 ++ " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap\n", ++--- a/ipc/util.c +++++ b/ipc/util.c ++@@ -141,6 +141,9 @@ void __init ipc_init_proc_interface(cons ++ struct proc_dir_entry *pde; ++ struct ipc_proc_iface *iface; ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return; +++ ++ iface = kmalloc(sizeof(*iface), GFP_KERNEL); ++ if (!iface) ++ return; ++--- a/kernel/exec_domain.c +++++ b/kernel/exec_domain.c ++@@ -42,6 +42,8 @@ static const struct file_operations exec ++ ++ static int __init proc_execdomains_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; ++ proc_create("execdomains", 0, NULL, &execdomains_proc_fops); ++ return 0; ++ } ++--- a/kernel/irq/proc.c +++++ b/kernel/irq/proc.c ++@@ -418,6 +418,9 @@ void register_irq_proc(unsigned int irq, ++ void __maybe_unused *irqp = (void *)(unsigned long) irq; ++ char name [MAX_NAMELEN]; ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) +++ return; +++ ++ if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip)) ++ return; ++ ++@@ -471,6 +474,9 @@ void unregister_irq_proc(unsigned int ir ++ { ++ char name [MAX_NAMELEN]; ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) +++ return; +++ ++ if (!root_irq_dir || !desc->dir) ++ return; ++ #ifdef CONFIG_SMP ++@@ -509,6 +515,9 @@ void init_irq_proc(void) ++ unsigned int irq; ++ struct irq_desc *desc; ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) +++ return; +++ ++ /* create /proc/irq */ ++ root_irq_dir = proc_mkdir("irq", NULL); ++ if (!root_irq_dir) ++--- a/kernel/time/timer_list.c +++++ b/kernel/time/timer_list.c ++@@ -390,6 +390,8 @@ static int __init init_timer_list_procfs ++ { ++ struct proc_dir_entry *pe; ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; ++ pe = proc_create("timer_list", 0400, NULL, &timer_list_fops); ++ if (!pe) ++ return -ENOMEM; ++--- a/mm/vmalloc.c +++++ b/mm/vmalloc.c ++@@ -2798,6 +2798,8 @@ static const struct file_operations proc ++ ++ static int __init proc_vmalloc_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; ++ proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations); ++ return 0; ++ } ++--- a/mm/vmstat.c +++++ b/mm/vmstat.c ++@@ -1951,10 +1951,12 @@ void __init init_mm_internals(void) ++ start_shepherd_timer(); ++ #endif ++ #ifdef CONFIG_PROC_FS ++- proc_create("buddyinfo", 0444, NULL, &buddyinfo_file_operations); ++- proc_create("pagetypeinfo", 0400, NULL, &pagetypeinfo_file_operations); +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { +++ proc_create("buddyinfo", 0444, NULL, &buddyinfo_file_operations); +++ proc_create("pagetypeinfo", 0400, NULL, &pagetypeinfo_file_operations); +++ proc_create("zoneinfo", 0444, NULL, &zoneinfo_file_operations); +++ } ++ proc_create("vmstat", 0444, NULL, &vmstat_file_operations); ++- proc_create("zoneinfo", 0444, NULL, &zoneinfo_file_operations); ++ #endif ++ } ++ ++--- a/net/8021q/vlanproc.c +++++ b/net/8021q/vlanproc.c ++@@ -127,6 +127,9 @@ void vlan_proc_cleanup(struct net *net) ++ { ++ struct vlan_net *vn = net_generic(net, vlan_net_id); ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return; +++ ++ if (vn->proc_vlan_conf) ++ remove_proc_entry(name_conf, vn->proc_vlan_dir); ++ ++@@ -146,6 +149,9 @@ int __net_init vlan_proc_init(struct net ++ { ++ struct vlan_net *vn = net_generic(net, vlan_net_id); ++ +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; +++ ++ vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net); ++ if (!vn->proc_vlan_dir) ++ goto err; ++--- a/net/core/net-procfs.c +++++ b/net/core/net-procfs.c ++@@ -320,10 +320,12 @@ static int __net_init dev_proc_net_init( ++ ++ if (!proc_create("dev", S_IRUGO, net->proc_net, &dev_seq_fops)) ++ goto out; ++- if (!proc_create("softnet_stat", S_IRUGO, net->proc_net, +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && +++ !proc_create("softnet_stat", S_IRUGO, net->proc_net, ++ &softnet_seq_fops)) ++ goto out_dev; ++- if (!proc_create("ptype", S_IRUGO, net->proc_net, &ptype_seq_fops)) +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && +++ !proc_create("ptype", S_IRUGO, net->proc_net, &ptype_seq_fops)) ++ goto out_softnet; ++ ++ if (wext_proc_init(net)) ++@@ -332,9 +334,11 @@ static int __net_init dev_proc_net_init( ++ out: ++ return rc; ++ out_ptype: ++- remove_proc_entry("ptype", net->proc_net); +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ remove_proc_entry("ptype", net->proc_net); ++ out_softnet: ++- remove_proc_entry("softnet_stat", net->proc_net); +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ remove_proc_entry("softnet_stat", net->proc_net); ++ out_dev: ++ remove_proc_entry("dev", net->proc_net); ++ goto out; ++@@ -344,8 +348,10 @@ static void __net_exit dev_proc_net_exit ++ { ++ wext_proc_exit(net); ++ ++- remove_proc_entry("ptype", net->proc_net); ++- remove_proc_entry("softnet_stat", net->proc_net); +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { +++ remove_proc_entry("ptype", net->proc_net); +++ remove_proc_entry("softnet_stat", net->proc_net); +++ } ++ remove_proc_entry("dev", net->proc_net); ++ } ++ ++--- a/net/core/sock.c +++++ b/net/core/sock.c ++@@ -3389,6 +3389,8 @@ static __net_initdata struct pernet_oper ++ ++ static int __init proto_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; ++ return register_pernet_subsys(&proto_net_ops); ++ } ++ ++--- a/net/ipv4/fib_trie.c +++++ b/net/ipv4/fib_trie.c ++@@ -2743,10 +2743,12 @@ static const struct file_operations fib_ ++ ++ int __net_init fib_proc_init(struct net *net) ++ { ++- if (!proc_create("fib_trie", S_IRUGO, net->proc_net, &fib_trie_fops)) +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && +++ !proc_create("fib_trie", S_IRUGO, net->proc_net, &fib_trie_fops)) ++ goto out1; ++ ++- if (!proc_create("fib_triestat", S_IRUGO, net->proc_net, +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && +++ !proc_create("fib_triestat", S_IRUGO, net->proc_net, ++ &fib_triestat_fops)) ++ goto out2; ++ ++@@ -2756,17 +2758,21 @@ int __net_init fib_proc_init(struct net ++ return 0; ++ ++ out3: ++- remove_proc_entry("fib_triestat", net->proc_net); +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ remove_proc_entry("fib_triestat", net->proc_net); ++ out2: ++- remove_proc_entry("fib_trie", net->proc_net); +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ remove_proc_entry("fib_trie", net->proc_net); ++ out1: ++ return -ENOMEM; ++ } ++ ++ void __net_exit fib_proc_exit(struct net *net) ++ { ++- remove_proc_entry("fib_trie", net->proc_net); ++- remove_proc_entry("fib_triestat", net->proc_net); +++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { +++ remove_proc_entry("fib_trie", net->proc_net); +++ remove_proc_entry("fib_triestat", net->proc_net); +++ } ++ remove_proc_entry("route", net->proc_net); ++ } ++ ++--- a/net/ipv4/proc.c +++++ b/net/ipv4/proc.c ++@@ -559,6 +559,9 @@ static __net_initdata struct pernet_oper ++ ++ int __init ip_misc_proc_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; +++ ++ return register_pernet_subsys(&ip_proc_ops); ++ } ++ ++--- a/net/ipv4/route.c +++++ b/net/ipv4/route.c ++@@ -426,6 +426,9 @@ static struct pernet_operations ip_rt_pr ++ ++ static int __init ip_rt_proc_init(void) ++ { +++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) +++ return 0; +++ ++ return register_pernet_subsys(&ip_rt_proc_ops); ++ } ++ +diff --git a/target/linux/generic/hack-4.14/904-debloat_dma_buf.patch b/target/linux/generic/hack-4.14/904-debloat_dma_buf.patch +new file mode 100644 +index 0000000000..9fd8894225 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/904-debloat_dma_buf.patch +@@ -0,0 +1,64 @@ ++From e3692cb2fcd5ba1244512a0f43b8118f65f1c375 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sat, 8 Jul 2017 08:20:43 +0200 ++Subject: debloat: dmabuf ++ ++Signed-off-by: Felix Fietkau ++--- ++ drivers/base/Kconfig | 2 +- ++ drivers/dma-buf/Makefile | 10 +++++++--- ++ drivers/dma-buf/dma-buf.c | 4 +++- ++ kernel/sched/core.c | 1 + ++ 4 files changed, 12 insertions(+), 5 deletions(-) ++ ++--- a/drivers/base/Kconfig +++++ b/drivers/base/Kconfig ++@@ -246,7 +246,7 @@ config SOC_BUS ++ source "drivers/base/regmap/Kconfig" ++ ++ config DMA_SHARED_BUFFER ++- bool +++ tristate ++ default n ++ select ANON_INODES ++ select IRQ_WORK ++--- a/drivers/dma-buf/Makefile +++++ b/drivers/dma-buf/Makefile ++@@ -1,3 +1,7 @@ ++-obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o ++-obj-$(CONFIG_SYNC_FILE) += sync_file.o ++-obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o +++obj-$(CONFIG_DMA_SHARED_BUFFER) := dma-shared-buffer.o +++ +++dma-buf-objs-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o +++dma-buf-objs-$(CONFIG_SYNC_FILE) += sync_file.o +++dma-buf-objs-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o +++ +++dma-shared-buffer-objs := $(dma-buf-objs-y) ++--- a/drivers/dma-buf/dma-buf.c +++++ b/drivers/dma-buf/dma-buf.c ++@@ -34,6 +34,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include ++ ++@@ -1206,4 +1207,5 @@ static void __exit dma_buf_deinit(void) ++ { ++ dma_buf_uninit_debugfs(); ++ } ++-__exitcall(dma_buf_deinit); +++module_exit(dma_buf_deinit); +++MODULE_LICENSE("GPL"); ++--- a/kernel/sched/core.c +++++ b/kernel/sched/core.c ++@@ -2165,6 +2165,7 @@ int wake_up_state(struct task_struct *p, ++ { ++ return try_to_wake_up(p, state, 0); ++ } +++EXPORT_SYMBOL_GPL(wake_up_state); ++ ++ /* ++ * Perform scheduler related setup for a newly forked process p. +diff --git a/target/linux/generic/hack-4.14/910-kobject_uevent.patch b/target/linux/generic/hack-4.14/910-kobject_uevent.patch +new file mode 100644 +index 0000000000..113fbb54b3 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/910-kobject_uevent.patch +@@ -0,0 +1,32 @@ ++From 0d37e6edc09c99e683dd91ca0e83bbc0df8477b3 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sun, 16 Jul 2017 16:56:10 +0200 ++Subject: lib: add uevent_next_seqnum() ++ ++Signed-off-by: Felix Fietkau ++--- ++ include/linux/kobject.h | 5 +++++ ++ lib/kobject_uevent.c | 37 +++++++++++++++++++++++++++++++++++++ ++ 2 files changed, 42 insertions(+) ++ ++--- a/lib/kobject_uevent.c +++++ b/lib/kobject_uevent.c ++@@ -176,6 +176,18 @@ out: ++ return r; ++ } ++ +++u64 uevent_next_seqnum(void) +++{ +++ u64 seq; +++ +++ mutex_lock(&uevent_sock_mutex); +++ seq = ++uevent_seqnum; +++ mutex_unlock(&uevent_sock_mutex); +++ +++ return seq; +++} +++EXPORT_SYMBOL_GPL(uevent_next_seqnum); +++ ++ /** ++ * kobject_synth_uevent - send synthetic uevent with arguments ++ * +diff --git a/target/linux/generic/hack-4.14/911-kobject_add_broadcast_uevent.patch b/target/linux/generic/hack-4.14/911-kobject_add_broadcast_uevent.patch +new file mode 100644 +index 0000000000..bf46428854 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/911-kobject_add_broadcast_uevent.patch +@@ -0,0 +1,76 @@ ++From 0d37e6edc09c99e683dd91ca0e83bbc0df8477b3 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sun, 16 Jul 2017 16:56:10 +0200 ++Subject: lib: add uevent_next_seqnum() ++ ++Signed-off-by: Felix Fietkau ++--- ++ include/linux/kobject.h | 5 +++++ ++ lib/kobject_uevent.c | 37 +++++++++++++++++++++++++++++++++++++ ++ 2 files changed, 42 insertions(+) ++ ++--- a/include/linux/kobject.h +++++ b/include/linux/kobject.h ++@@ -32,6 +32,8 @@ ++ #define UEVENT_NUM_ENVP 32 /* number of env pointers */ ++ #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ ++ +++struct sk_buff; +++ ++ #ifdef CONFIG_UEVENT_HELPER ++ /* path to the userspace helper executed on an event */ ++ extern char uevent_helper[]; ++@@ -241,4 +243,7 @@ int kobject_synth_uevent(struct kobject ++ __printf(2, 3) ++ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...); ++ +++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, +++ gfp_t allocation); +++ ++ #endif /* _KOBJECT_H_ */ ++--- a/lib/kobject_uevent.c +++++ b/lib/kobject_uevent.c ++@@ -602,6 +602,43 @@ int add_uevent_var(struct kobj_uevent_en ++ EXPORT_SYMBOL_GPL(add_uevent_var); ++ ++ #if defined(CONFIG_NET) +++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, +++ gfp_t allocation) +++{ +++ struct uevent_sock *ue_sk; +++ int err = 0; +++ +++ /* send netlink message */ +++ mutex_lock(&uevent_sock_mutex); +++ list_for_each_entry(ue_sk, &uevent_sock_list, list) { +++ struct sock *uevent_sock = ue_sk->sk; +++ struct sk_buff *skb2; +++ +++ skb2 = skb_clone(skb, allocation); +++ if (!skb2) +++ break; +++ +++ err = netlink_broadcast(uevent_sock, skb2, pid, group, +++ allocation); +++ if (err) +++ break; +++ } +++ mutex_unlock(&uevent_sock_mutex); +++ +++ kfree_skb(skb); +++ return err; +++} +++#else +++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, +++ gfp_t allocation) +++{ +++ kfree_skb(skb); +++ return 0; +++} +++#endif +++EXPORT_SYMBOL_GPL(broadcast_uevent); +++ +++#if defined(CONFIG_NET) ++ static int uevent_net_init(struct net *net) ++ { ++ struct uevent_sock *ue_sk; +diff --git a/target/linux/generic/hack-4.14/921-always-create-console-node-in-initramfs.patch b/target/linux/generic/hack-4.14/921-always-create-console-node-in-initramfs.patch +new file mode 100644 +index 0000000000..6eeddcc3c6 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/921-always-create-console-node-in-initramfs.patch +@@ -0,0 +1,40 @@ ++From 5d301596fdc72f6cb672f72eb3c66e7cddefb103 Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sat, 8 Jul 2017 08:26:02 +0200 ++Subject: initramfs: always create console node ++ ++Signed-off-by: Felix Fietkau ++--- ++ scripts/gen_initramfs_list.sh | 14 ++++++++++++++ ++ 1 file changed, 14 insertions(+) ++ ++--- a/scripts/gen_initramfs_list.sh +++++ b/scripts/gen_initramfs_list.sh ++@@ -59,6 +59,18 @@ default_initramfs() { ++ EOF ++ } ++ +++list_openwrt_initramfs() { +++ : +++} +++ +++openwrt_initramfs() { +++ # make sure that /dev/console exists +++ cat <<-EOF >> ${output} +++ dir /dev 0755 0 0 +++ nod /dev/console 0600 0 0 c 5 1 +++ EOF +++} +++ ++ filetype() { ++ local argv1="$1" ++ ++@@ -180,6 +192,8 @@ dir_filelist() { ++ if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then ++ ${dep_list}print_mtime "$1" ++ +++ ${dep_list}openwrt_initramfs +++ ++ echo "${dirlist}" | \ ++ while read x; do ++ ${dep_list}parse ${x} +diff --git a/target/linux/generic/hack-4.14/930-crashlog.patch b/target/linux/generic/hack-4.14/930-crashlog.patch +new file mode 100644 +index 0000000000..9d09dbd760 +--- /dev/null ++++ b/target/linux/generic/hack-4.14/930-crashlog.patch +@@ -0,0 +1,338 @@ ++From 6b1ab74a9917012d0c559edc4ed299d9228ac89f Mon Sep 17 00:00:00 2001 ++From: Felix Fietkau ++Date: Sat, 8 Jul 2017 08:26:47 +0200 ++Subject: kernel: add the new 'crashlog' feature ++ ++this tries to store kernel oops/panic logs in a fixed location in RAM to ++recover them available to user space using debugfs ++ ++Signed-off-by: Felix Fietkau ++--- ++ include/linux/crashlog.h | 17 ++++ ++ init/Kconfig | 4 + ++ kernel/Makefile | 1 + ++ kernel/crashlog.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++ ++ kernel/module.c | 3 + ++ mm/bootmem.c | 2 + ++ mm/memblock.c | 5 ++ ++ 7 files changed, 245 insertions(+) ++ create mode 100644 include/linux/crashlog.h ++ create mode 100644 kernel/crashlog.c ++ ++--- /dev/null +++++ b/include/linux/crashlog.h ++@@ -0,0 +1,17 @@ +++#ifndef __CRASHLOG_H +++#define __CRASHLOG_H +++ +++#ifdef CONFIG_CRASHLOG +++void crashlog_init_bootmem(struct bootmem_data *bdata); +++void crashlog_init_memblock(phys_addr_t addr, phys_addr_t size); +++#else +++static inline void crashlog_init_bootmem(struct bootmem_data *bdata) +++{ +++} +++ +++static inline void crashlog_init_memblock(phys_addr_t addr, phys_addr_t size) +++{ +++} +++#endif +++ +++#endif ++--- a/init/Kconfig +++++ b/init/Kconfig ++@@ -1009,6 +1009,10 @@ config RELAY ++ ++ If unsure, say N. ++ +++config CRASHLOG +++ bool "Crash logging" +++ depends on (!NO_BOOTMEM || HAVE_MEMBLOCK) +++ ++ config BLK_DEV_INITRD ++ bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" ++ depends on BROKEN || !FRV ++--- a/kernel/Makefile +++++ b/kernel/Makefile ++@@ -110,6 +110,7 @@ obj-$(CONFIG_CONTEXT_TRACKING) += contex ++ obj-$(CONFIG_TORTURE_TEST) += torture.o ++ ++ obj-$(CONFIG_HAS_IOMEM) += memremap.o +++obj-$(CONFIG_CRASHLOG) += crashlog.o ++ ++ $(obj)/configs.o: $(obj)/config_data.h ++ ++--- /dev/null +++++ b/kernel/crashlog.c ++@@ -0,0 +1,213 @@ +++/* +++ * Crash information logger +++ * Copyright (C) 2010 Felix Fietkau +++ * +++ * Based on ramoops.c +++ * Copyright (C) 2010 Marco Stornelli +++ * +++ * 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. +++ * +++ * 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., 51 Franklin St, Fifth Floor, Boston, MA +++ * 02110-1301 USA +++ * +++ */ +++ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++#define CRASHLOG_PAGES 4 +++#define CRASHLOG_SIZE (CRASHLOG_PAGES * PAGE_SIZE) +++#define CRASHLOG_MAGIC 0xa1eedead +++ +++/* +++ * Start the log at 1M before the end of RAM, as some boot loaders like +++ * to use the end of the RAM for stack usage and other things +++ * If this fails, fall back to using the last part. +++ */ +++#define CRASHLOG_OFFSET (1024 * 1024) +++ +++struct crashlog_data { +++ u32 magic; +++ u32 len; +++ u8 data[]; +++}; +++ +++static struct debugfs_blob_wrapper crashlog_blob; +++static unsigned long crashlog_addr = 0; +++static struct crashlog_data *crashlog_buf; +++static struct kmsg_dumper dump; +++static bool first = true; +++ +++extern struct list_head *crashlog_modules; +++ +++static bool crashlog_set_addr(phys_addr_t addr, phys_addr_t size) +++{ +++ /* Limit to lower 64 MB to avoid highmem */ +++ phys_addr_t limit = 64 * 1024 * 1024; +++ +++ if (crashlog_addr) +++ return false; +++ +++ if (addr > limit) +++ return false; +++ +++ if (addr + size > limit) +++ size = limit - addr; +++ +++ crashlog_addr = addr; +++ +++ if (addr + size > CRASHLOG_OFFSET) +++ crashlog_addr += size - CRASHLOG_OFFSET; +++ +++ return true; +++} +++ +++#ifndef CONFIG_NO_BOOTMEM +++void __init crashlog_init_bootmem(bootmem_data_t *bdata) +++{ +++ phys_addr_t start, end; +++ +++ start = PFN_PHYS(bdata->node_low_pfn); +++ end = PFN_PHYS(bdata->node_min_pfn); +++ if (!crashlog_set_addr(start, end - start)) +++ return; +++ +++ if (reserve_bootmem(crashlog_addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) { +++ printk("Crashlog failed to allocate RAM at address 0x%lx\n", +++ crashlog_addr); +++ crashlog_addr = 0; +++ } +++} +++#endif +++ +++#ifdef CONFIG_HAVE_MEMBLOCK +++void __init_memblock crashlog_init_memblock(phys_addr_t addr, phys_addr_t size) +++{ +++ if (!crashlog_set_addr(addr, size)) +++ return; +++ +++ if (memblock_reserve(crashlog_addr, CRASHLOG_SIZE)) { +++ printk("Crashlog failed to allocate RAM at address 0x%lx\n", +++ crashlog_addr); +++ crashlog_addr = 0; +++ } +++} +++#endif +++ +++static void __init crashlog_copy(void) +++{ +++ if (crashlog_buf->magic != CRASHLOG_MAGIC) +++ return; +++ +++ if (!crashlog_buf->len || crashlog_buf->len > +++ CRASHLOG_SIZE - sizeof(*crashlog_buf)) +++ return; +++ +++ crashlog_blob.size = crashlog_buf->len; +++ crashlog_blob.data = kmemdup(crashlog_buf->data, +++ crashlog_buf->len, GFP_KERNEL); +++ +++ debugfs_create_blob("crashlog", 0700, NULL, &crashlog_blob); +++} +++ +++static int get_maxlen(void) +++{ +++ return CRASHLOG_SIZE - sizeof(*crashlog_buf) - crashlog_buf->len; +++} +++ +++static void crashlog_printf(const char *fmt, ...) +++{ +++ va_list args; +++ int len = get_maxlen(); +++ +++ if (!len) +++ return; +++ +++ va_start(args, fmt); +++ crashlog_buf->len += vscnprintf( +++ &crashlog_buf->data[crashlog_buf->len], +++ len, fmt, args); +++ va_end(args); +++} +++ +++static void crashlog_do_dump(struct kmsg_dumper *dumper, +++ enum kmsg_dump_reason reason) +++{ +++ struct timeval tv; +++ struct module *m; +++ char *buf; +++ size_t len; +++ +++ if (!first) +++ crashlog_printf("\n===================================\n"); +++ +++ do_gettimeofday(&tv); +++ crashlog_printf("Time: %lu.%lu\n", +++ (long)tv.tv_sec, (long)tv.tv_usec); +++ +++ if (first) { +++ crashlog_printf("Modules:"); +++ list_for_each_entry(m, crashlog_modules, list) { +++ crashlog_printf("\t%s@%p+%x", m->name, +++ m->core_layout.base, m->core_layout.size, +++ m->init_layout.base, m->init_layout.size); +++ } +++ crashlog_printf("\n"); +++ first = false; +++ } +++ +++ buf = (char *)&crashlog_buf->data[crashlog_buf->len]; +++ +++ kmsg_dump_get_buffer(dumper, true, buf, get_maxlen(), &len); +++ +++ crashlog_buf->len += len; +++} +++ +++ +++int __init crashlog_init_fs(void) +++{ +++ struct page *pages[CRASHLOG_PAGES]; +++ pgprot_t prot; +++ int i; +++ +++ if (!crashlog_addr) { +++ printk("No memory allocated for crashlog\n"); +++ return -ENOMEM; +++ } +++ +++ printk("Crashlog allocated RAM at address 0x%lx\n", (unsigned long) crashlog_addr); +++ for (i = 0; i < CRASHLOG_PAGES; i++) +++ pages[i] = pfn_to_page((crashlog_addr >> PAGE_SHIFT) + i); +++ +++ prot = pgprot_writecombine(PAGE_KERNEL); +++ crashlog_buf = vmap(pages, CRASHLOG_PAGES, VM_MAP, prot); +++ +++ crashlog_copy(); +++ +++ crashlog_buf->magic = CRASHLOG_MAGIC; +++ crashlog_buf->len = 0; +++ +++ dump.max_reason = KMSG_DUMP_OOPS; +++ dump.dump = crashlog_do_dump; +++ kmsg_dump_register(&dump); +++ +++ return 0; +++} +++module_init(crashlog_init_fs); ++--- a/kernel/module.c +++++ b/kernel/module.c ++@@ -256,6 +256,9 @@ static void mod_update_bounds(struct mod ++ #ifdef CONFIG_KGDB_KDB ++ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ ++ #endif /* CONFIG_KGDB_KDB */ +++#ifdef CONFIG_CRASHLOG +++struct list_head *crashlog_modules = &modules; +++#endif ++ ++ static void module_assert_mutex(void) ++ { ++--- a/mm/bootmem.c +++++ b/mm/bootmem.c ++@@ -15,6 +15,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -175,6 +176,7 @@ static unsigned long __init free_all_boo ++ if (!bdata->node_bootmem_map) ++ return 0; ++ +++ crashlog_init_bootmem(bdata); ++ map = bdata->node_bootmem_map; ++ start = bdata->node_min_pfn; ++ end = bdata->node_low_pfn; ++--- a/mm/memblock.c +++++ b/mm/memblock.c ++@@ -19,6 +19,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include ++ #include ++@@ -483,6 +484,8 @@ static void __init_memblock memblock_ins ++ memblock_set_region_node(rgn, nid); ++ type->cnt++; ++ type->total_size += size; +++ if (type == &memblock.memory) +++ crashlog_init_memblock(base, size); ++ } ++ ++ /** ++@@ -522,6 +525,8 @@ int __init_memblock memblock_add_range(s ++ type->regions[0].flags = flags; ++ memblock_set_region_node(&type->regions[0], nid); ++ type->total_size = size; +++ if (type == &memblock.memory) +++ crashlog_init_memblock(base, size); ++ return 0; ++ } ++ repeat: +diff --git a/target/linux/generic/pending-4.14/0931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/target/linux/generic/pending-4.14/0931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch +new file mode 100644 +index 0000000000..0c4a13f9df +--- /dev/null ++++ b/target/linux/generic/pending-4.14/0931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch +@@ -0,0 +1,38 @@ ++From d9c8bc8c1408f3e8529db6e4e04017b4c579c342 Mon Sep 17 00:00:00 2001 ++From: Pawel Dembicki ++Date: Sun, 18 Feb 2018 17:08:04 +0100 ++Subject: [PATCH] w1: gpio: fix problem with platfom data in w1-gpio ++ ++In devices, where fdt is used, is impossible to apply platform data ++without proper fdt node. ++ ++This patch allow to use platform data in devices with fdt. ++ ++Signed-off-by: Pawel Dembicki ++--- ++ drivers/w1/masters/w1-gpio.c | 7 +++---- ++ 1 file changed, 3 insertions(+), 4 deletions(-) ++ ++--- a/drivers/w1/masters/w1-gpio.c +++++ b/drivers/w1/masters/w1-gpio.c ++@@ -112,17 +112,16 @@ static int w1_gpio_probe_dt(struct platf ++ static int w1_gpio_probe(struct platform_device *pdev) ++ { ++ struct w1_bus_master *master; ++- struct w1_gpio_platform_data *pdata; +++ struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); ++ int err; ++ ++- if (of_have_populated_dt()) { +++ if (of_have_populated_dt() && !pdata) { ++ err = w1_gpio_probe_dt(pdev); ++ if (err < 0) ++ return err; +++ pdata = dev_get_platdata(&pdev->dev); ++ } ++ ++- pdata = dev_get_platdata(&pdev->dev); ++- ++ if (!pdata) { ++ dev_err(&pdev->dev, "No configuration data\n"); ++ return -ENXIO; +diff --git a/target/linux/generic/pending-4.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch b/target/linux/generic/pending-4.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch +new file mode 100644 +index 0000000000..92e86b24e7 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch +@@ -0,0 +1,57 @@ ++From: Felix Fietkau ++Date: Wed, 18 Apr 2018 10:50:05 +0200 ++Subject: [PATCH] MIPS: only process negative stack offsets on stack traces ++ ++Fixes endless back traces in cases where the compiler emits a stack ++pointer increase in a branch delay slot (probably for some form of ++function return). ++ ++[ 3.475442] BUG: MAX_STACK_TRACE_ENTRIES too low! ++[ 3.480070] turning off the locking correctness validator. ++[ 3.485521] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.14.34 #0 ++[ 3.491475] Stack : 00000000 00000000 00000000 00000000 80e0fce2 00000034 00000000 00000000 ++[ 3.499764] 87c3838c 80696377 8061047c 00000000 00000001 00000001 87c2d850 6534689f ++[ 3.508059] 00000000 00000000 80e10000 00000000 00000000 000000cf 0000000f 00000000 ++[ 3.516353] 00000000 806a0000 00076891 00000000 00000000 00000000 ffffffff 00000000 ++[ 3.524648] 806c0000 00000004 80e10000 806a0000 00000003 80690000 00000000 80700000 ++[ 3.532942] ... ++[ 3.535362] Call Trace: ++[ 3.537818] [<80010a48>] show_stack+0x58/0x100 ++[ 3.542207] [<804c2f78>] dump_stack+0xe8/0x170 ++[ 3.546613] [<80079f90>] save_trace+0xf0/0x110 ++[ 3.551010] [<8007b1ec>] mark_lock+0x33c/0x78c ++[ 3.555413] [<8007bf48>] __lock_acquire+0x2ac/0x1a08 ++[ 3.560337] [<8007de60>] lock_acquire+0x64/0x8c ++[ 3.564846] [<804e1570>] _raw_spin_lock_irqsave+0x54/0x78 ++[ 3.570186] [<801b618c>] kernfs_notify+0x94/0xac ++[ 3.574770] [<801b7b10>] sysfs_notify+0x74/0xa0 ++[ 3.579257] [<801b618c>] kernfs_notify+0x94/0xac ++[ 3.583839] [<801b7b10>] sysfs_notify+0x74/0xa0 ++[ 3.588329] [<801b618c>] kernfs_notify+0x94/0xac ++[ 3.592911] [<801b7b10>] sysfs_notify+0x74/0xa0 ++[ 3.597401] [<801b618c>] kernfs_notify+0x94/0xac ++[ 3.601983] [<801b7b10>] sysfs_notify+0x74/0xa0 ++[ 3.606473] [<801b618c>] kernfs_notify+0x94/0xac ++[ 3.611055] [<801b7b10>] sysfs_notify+0x74/0xa0 ++[ 3.615545] [<801b618c>] kernfs_notify+0x94/0xac ++[ 3.620125] [<801b7b10>] sysfs_notify+0x74/0xa0 ++[ 3.624619] [<801b618c>] kernfs_notify+0x94/0xac ++[ 3.629197] [<801b7b10>] sysfs_notify+0x74/0xa0 ++[ 3.633691] [<801b618c>] kernfs_notify+0x94/0xac ++[ 3.638269] [<801b7b10>] sysfs_notify+0x74/0xa0 ++[ 3.642763] [<801b618c>] kernfs_notify+0x94/0xac ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/arch/mips/kernel/process.c +++++ b/arch/mips/kernel/process.c ++@@ -360,6 +360,8 @@ static inline int is_sp_move_ins(union m ++ ++ if (ip->i_format.opcode == addiu_op || ++ ip->i_format.opcode == daddiu_op) { +++ if (ip->i_format.simmediate > 0) +++ return 0; ++ *frame_size = -ip->i_format.simmediate; ++ return 1; ++ } +diff --git a/target/linux/generic/pending-4.14/103-MIPS-perf-ath79-Fix-perfcount-IRQ-assignment.patch b/target/linux/generic/pending-4.14/103-MIPS-perf-ath79-Fix-perfcount-IRQ-assignment.patch +new file mode 100644 +index 0000000000..1990e87055 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/103-MIPS-perf-ath79-Fix-perfcount-IRQ-assignment.patch +@@ -0,0 +1,110 @@ ++From 852a88f35f4b7e5ebb717fed3c3a3330d5ad4336 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Petr=20=C5=A0tetiar?= ++Date: Wed, 10 Apr 2019 16:43:27 +0200 ++Subject: [PATCH v2] MIPS: perf: ath79: Fix perfcount IRQ assignment ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Currently it's not possible to use perf on ath79 due to genirq flags ++mismatch happening on static virtual IRQ 13 which is used for ++performance counters hardware IRQ 5. ++ ++On TP-Link Archer C7v5: ++ ++ CPU0 ++ 2: 0 MIPS 2 ath9k ++ 4: 318 MIPS 4 19000000.eth ++ 7: 55034 MIPS 7 timer ++ 8: 1236 MISC 3 ttyS0 ++ 12: 0 INTC 1 ehci_hcd:usb1 ++ 13: 0 gpio-ath79 2 keys ++ 14: 0 gpio-ath79 5 keys ++ 15: 31 AR724X PCI 1 ath10k_pci ++ ++ $ perf top ++ genirq: Flags mismatch irq 13. 00014c83 (mips_perf_pmu) vs. 00002003 (keys) ++ ++On TP-Link Archer C7v4: ++ ++ CPU0 ++ 4: 0 MIPS 4 19000000.eth ++ 5: 7135 MIPS 5 1a000000.eth ++ 7: 98379 MIPS 7 timer ++ 8: 30 MISC 3 ttyS0 ++ 12: 90028 INTC 0 ath9k ++ 13: 5520 INTC 1 ehci_hcd:usb1 ++ 14: 4623 INTC 2 ehci_hcd:usb2 ++ 15: 32844 AR724X PCI 1 ath10k_pci ++ 16: 0 gpio-ath79 16 keys ++ 23: 0 gpio-ath79 23 keys ++ ++ $ perf top ++ genirq: Flags mismatch irq 13. 00014c80 (mips_perf_pmu) vs. 00000080 (ehci_hcd:usb1) ++ ++This problem is happening, because currently statically assigned virtual ++IRQ 13 for performance counters is not claimed during the initialization ++of MIPS PMU during the bootup, so the IRQ subsystem doesn't know, that ++this interrupt isn't available for further use. ++ ++So this patch fixes the issue by simply booking hardware IRQ 5 for MIPS PMU. ++ ++Tested-by: Kevin 'ldir' Darbyshire-Bryant ++Signed-off-by: Petr Štetiar ++--- ++ ++Changes since v1: ++ ++ I've incorporated two comments which I've received on IRC from blogic and ++ I've also reworded the commit message to match the changes in v2 of this ++ patch. ++ ++ * use actual hardware perfcount IRQ 5 instead of the virtual IRQ 13 ++ * dropped the CONFIG_PERF_EVENTS ifdef around irq_create_mapping ++ ++ arch/mips/ath79/setup.c | 6 ------ ++ drivers/irqchip/irq-ath79-misc.c | 11 +++++++++++ ++ 2 files changed, 11 insertions(+), 6 deletions(-) ++ ++--- a/arch/mips/ath79/setup.c +++++ b/arch/mips/ath79/setup.c ++@@ -183,12 +183,6 @@ const char *get_system_type(void) ++ return ath79_sys_type; ++ } ++ ++-int get_c0_perfcount_int(void) ++-{ ++- return ATH79_MISC_IRQ(5); ++-} ++-EXPORT_SYMBOL_GPL(get_c0_perfcount_int); ++- ++ unsigned int get_c0_compare_int(void) ++ { ++ return CP0_LEGACY_COMPARE_IRQ; ++--- a/drivers/irqchip/irq-ath79-misc.c +++++ b/drivers/irqchip/irq-ath79-misc.c ++@@ -22,6 +22,15 @@ ++ #define AR71XX_RESET_REG_MISC_INT_ENABLE 4 ++ ++ #define ATH79_MISC_IRQ_COUNT 32 +++#define ATH79_MISC_PERF_IRQ 5 +++ +++static int ath79_perfcount_irq; +++ +++int get_c0_perfcount_int(void) +++{ +++ return ath79_perfcount_irq; +++} +++EXPORT_SYMBOL_GPL(get_c0_perfcount_int); ++ ++ static void ath79_misc_irq_handler(struct irq_desc *desc) ++ { ++@@ -113,6 +122,8 @@ static void __init ath79_misc_intc_domai ++ { ++ void __iomem *base = domain->host_data; ++ +++ ath79_perfcount_irq = irq_create_mapping(domain, ATH79_MISC_PERF_IRQ); +++ ++ /* Disable and clear all interrupts */ ++ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); ++ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); +diff --git a/target/linux/generic/pending-4.14/110-ehci_hcd_ignore_oc.patch b/target/linux/generic/pending-4.14/110-ehci_hcd_ignore_oc.patch +new file mode 100644 +index 0000000000..b45b1c079c +--- /dev/null ++++ b/target/linux/generic/pending-4.14/110-ehci_hcd_ignore_oc.patch +@@ -0,0 +1,79 @@ ++From: Florian Fainelli ++Subject: USB: EHCI: add ignore_oc flag to disable overcurrent checking ++ ++This patch adds an ignore_oc flag which can be set by EHCI controller ++not supporting or wanting to disable overcurrent checking. The EHCI ++platform data in include/linux/usb/ehci_pdriver.h is also augmented to ++take advantage of this new flag. ++ ++Signed-off-by: Florian Fainelli ++--- ++ drivers/usb/host/ehci-hcd.c | 2 +- ++ drivers/usb/host/ehci-hub.c | 4 ++-- ++ drivers/usb/host/ehci-platform.c | 1 + ++ drivers/usb/host/ehci.h | 1 + ++ include/linux/usb/ehci_pdriver.h | 1 + ++ 5 files changed, 6 insertions(+), 3 deletions(-) ++ ++--- a/drivers/usb/host/ehci-hcd.c +++++ b/drivers/usb/host/ehci-hcd.c ++@@ -651,7 +651,7 @@ static int ehci_run (struct usb_hcd *hcd ++ "USB %x.%x started, EHCI %x.%02x%s\n", ++ ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), ++ temp >> 8, temp & 0xff, ++- ignore_oc ? ", overcurrent ignored" : ""); +++ (ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : ""); ++ ++ ehci_writel(ehci, INTR_MASK, ++ &ehci->regs->intr_enable); /* Turn On Interrupts */ ++--- a/drivers/usb/host/ehci-hub.c +++++ b/drivers/usb/host/ehci-hub.c ++@@ -646,7 +646,7 @@ ehci_hub_status_data (struct usb_hcd *hc ++ * always set, seem to clear PORT_OCC and PORT_CSC when writing to ++ * PORT_POWER; that's surprising, but maybe within-spec. ++ */ ++- if (!ignore_oc) +++ if (!ignore_oc && !ehci->ignore_oc) ++ mask = PORT_CSC | PORT_PEC | PORT_OCC; ++ else ++ mask = PORT_CSC | PORT_PEC; ++@@ -1016,7 +1016,7 @@ int ehci_hub_control( ++ if (temp & PORT_PEC) ++ status |= USB_PORT_STAT_C_ENABLE << 16; ++ ++- if ((temp & PORT_OCC) && !ignore_oc){ +++ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){ ++ status |= USB_PORT_STAT_C_OVERCURRENT << 16; ++ ++ /* ++--- a/drivers/usb/host/ehci-platform.c +++++ b/drivers/usb/host/ehci-platform.c ++@@ -263,6 +263,8 @@ static int ehci_platform_probe(struct pl ++ hcd->has_tt = 1; ++ if (pdata->reset_on_resume) ++ priv->reset_on_resume = true; +++ if (pdata->ignore_oc) +++ ehci->ignore_oc = 1; ++ ++ #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO ++ if (ehci->big_endian_mmio) { ++--- a/drivers/usb/host/ehci.h +++++ b/drivers/usb/host/ehci.h ++@@ -231,6 +231,7 @@ struct ehci_hcd { /* one per controlle ++ unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ ++ unsigned need_oc_pp_cycle:1; /* MPC834X port power */ ++ unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ +++ unsigned ignore_oc:1; ++ ++ /* required for usb32 quirk */ ++ #define OHCI_CTRL_HCFS (3 << 6) ++--- a/include/linux/usb/ehci_pdriver.h +++++ b/include/linux/usb/ehci_pdriver.h ++@@ -49,6 +49,7 @@ struct usb_ehci_pdata { ++ unsigned no_io_watchdog:1; ++ unsigned reset_on_resume:1; ++ unsigned dma_mask_64:1; +++ unsigned ignore_oc:1; ++ ++ /* Turn on all power and clocks */ ++ int (*power_on)(struct platform_device *pdev); +diff --git a/target/linux/generic/pending-4.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/target/linux/generic/pending-4.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch +new file mode 100644 +index 0000000000..44e7fa70a3 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch +@@ -0,0 +1,82 @@ ++From: Tobias Wolf ++Subject: mm: Fix alloc_node_mem_map with ARCH_PFN_OFFSET calculation ++ ++An rt288x (ralink) based router (Belkin F5D8235 v1) does not boot with any ++kernel beyond version 4.3 resulting in: ++ ++BUG: Bad page state in process swapper pfn:086ac ++ ++bisect resulted in: ++ ++a1c34a3bf00af2cede839879502e12dc68491ad5 is the first bad commit ++commit a1c34a3bf00af2cede839879502e12dc68491ad5 ++Author: Laura Abbott ++Date: Thu Nov 5 18:48:46 2015 -0800 ++ ++ mm: Don't offset memmap for flatmem ++ ++ Srinivas Kandagatla reported bad page messages when trying to remove the ++ bottom 2MB on an ARM based IFC6410 board ++ ++ BUG: Bad page state in process swapper pfn:fffa8 ++ page:ef7fb500 count:0 mapcount:0 mapping: (null) index:0x0 ++ flags: 0x96640253(locked|error|dirty|active|arch_1|reclaim|mlocked) ++ page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set ++ bad because of flags: ++ flags: 0x200041(locked|active|mlocked) ++ Modules linked in: ++ CPU: 0 PID: 0 Comm: swapper Not tainted 3.19.0-rc3-00007-g412f9ba-dirty ++#816 ++ Hardware name: Qualcomm (Flattened Device Tree) ++ unwind_backtrace ++ show_stack ++ dump_stack ++ bad_page ++ free_pages_prepare ++ free_hot_cold_page ++ __free_pages ++ free_highmem_page ++ mem_init ++ start_kernel ++ Disabling lock debugging due to kernel taint ++ [...] ++:040000 040000 2de013c372345fd471cd58f0553c9b38b0ef1cc4 ++0a8156f848733dfa21e16c196dfb6c0a76290709 M mm ++ ++This fix for ARM does not account ARCH_PFN_OFFSET for mem_map as later used by ++page_to_pfn anymore. ++ ++The following output was generated with two hacked in printk statements: ++ ++printk("before %p vs. %p or %p\n", mem_map, mem_map - offset, mem_map - ++(pgdat->node_start_pfn - ARCH_PFN_OFFSET)); ++ if (page_to_pfn(mem_map) != pgdat->node_start_pfn) ++ mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET); ++printk("after %p\n", mem_map); ++ ++Output: ++ ++[ 0.000000] before 8861b280 vs. 8861b280 or 8851b280 ++[ 0.000000] after 8851b280 ++ ++As seen in the first line mem_map with subtraction of offset does not equal the ++mem_map after subtraction of ARCH_PFN_OFFSET. ++ ++After adding the offset of ARCH_PFN_OFFSET as well to mem_map as the ++previously calculated offset is zero for the named platform it is able to boot ++4.4 and 4.9-rc7 again. ++ ++Signed-off-by: Tobias Wolf ++--- ++ ++--- a/mm/page_alloc.c +++++ b/mm/page_alloc.c ++@@ -6146,7 +6146,7 @@ static void __ref alloc_node_mem_map(str ++ mem_map = NODE_DATA(0)->node_mem_map; ++ #if defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) || defined(CONFIG_FLATMEM) ++ if (page_to_pfn(mem_map) != pgdat->node_start_pfn) ++- mem_map -= offset; +++ mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET); ++ #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ ++ } ++ #endif +diff --git a/target/linux/generic/pending-4.14/130-add-linux-spidev-compatible-si3210.patch b/target/linux/generic/pending-4.14/130-add-linux-spidev-compatible-si3210.patch +new file mode 100644 +index 0000000000..3a42182c97 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/130-add-linux-spidev-compatible-si3210.patch +@@ -0,0 +1,18 @@ ++From: Giuseppe Lippolis ++Subject: Add the linux,spidev compatible in spidev Several device in ramips have this binding in the dts ++ ++Signed-off-by: Giuseppe Lippolis ++--- ++ drivers/spi/spidev.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/spi/spidev.c +++++ b/drivers/spi/spidev.c ++@@ -672,6 +672,7 @@ static const struct of_device_id spidev_ ++ { .compatible = "lineartechnology,ltc2488" }, ++ { .compatible = "ge,achc" }, ++ { .compatible = "semtech,sx1301" }, +++ { .compatible = "siliconlabs,si3210" }, ++ {}, ++ }; ++ MODULE_DEVICE_TABLE(of, spidev_dt_ids); +diff --git a/target/linux/generic/pending-4.14/131-spi-use-gpio_set_value_cansleep-for-setting-chipsele.patch b/target/linux/generic/pending-4.14/131-spi-use-gpio_set_value_cansleep-for-setting-chipsele.patch +new file mode 100644 +index 0000000000..9603385aed +--- /dev/null ++++ b/target/linux/generic/pending-4.14/131-spi-use-gpio_set_value_cansleep-for-setting-chipsele.patch +@@ -0,0 +1,20 @@ ++From: Felix Fietkau ++Subject: spi: use gpio_set_value_cansleep for setting chipselect GPIO ++ ++Sleeping is safe inside spi_transfer_one_message, and some GPIO chips ++need to sleep for setting values ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/spi/spi.c +++++ b/drivers/spi/spi.c ++@@ -729,7 +729,7 @@ static void spi_set_cs(struct spi_device ++ enable = !enable; ++ ++ if (gpio_is_valid(spi->cs_gpio)) { ++- gpio_set_value(spi->cs_gpio, !enable); +++ gpio_set_value_cansleep(spi->cs_gpio, !enable); ++ /* Some SPI masters need both GPIO CS & slave_select */ ++ if ((spi->controller->flags & SPI_MASTER_GPIO_SS) && ++ spi->controller->set_cs) +diff --git a/target/linux/generic/pending-4.14/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch b/target/linux/generic/pending-4.14/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch +new file mode 100644 +index 0000000000..c97e93250b +--- /dev/null ++++ b/target/linux/generic/pending-4.14/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch +@@ -0,0 +1,62 @@ ++From: Felix Fietkau ++Subject: jffs2: use .rename2 and add RENAME_WHITEOUT support ++ ++It is required for renames on overlayfs ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/fs/jffs2/dir.c +++++ b/fs/jffs2/dir.c ++@@ -752,6 +752,24 @@ static int jffs2_mknod (struct inode *di ++ return ret; ++ } ++ +++static int jffs2_whiteout (struct inode *old_dir, struct dentry *old_dentry) +++{ +++ struct dentry *wh; +++ int err; +++ +++ wh = d_alloc(old_dentry->d_parent, &old_dentry->d_name); +++ if (!wh) +++ return -ENOMEM; +++ +++ err = jffs2_mknod(old_dir, wh, S_IFCHR | WHITEOUT_MODE, +++ WHITEOUT_DEV); +++ if (err) +++ return err; +++ +++ d_rehash(wh); +++ return 0; +++} +++ ++ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, ++ struct inode *new_dir_i, struct dentry *new_dentry, ++ unsigned int flags) ++@@ -762,7 +780,7 @@ static int jffs2_rename (struct inode *o ++ uint8_t type; ++ uint32_t now; ++ ++- if (flags & ~RENAME_NOREPLACE) +++ if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT)) ++ return -EINVAL; ++ ++ /* The VFS will check for us and prevent trying to rename a ++@@ -828,9 +846,14 @@ static int jffs2_rename (struct inode *o ++ if (d_is_dir(old_dentry) && !victim_f) ++ inc_nlink(new_dir_i); ++ ++- /* Unlink the original */ ++- ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), ++- old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); +++ if (flags & RENAME_WHITEOUT) +++ /* Replace with whiteout */ +++ ret = jffs2_whiteout(old_dir_i, old_dentry); +++ else +++ /* Unlink the original */ +++ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), +++ old_dentry->d_name.name, +++ old_dentry->d_name.len, NULL, now); ++ ++ /* We don't touch inode->i_nlink */ ++ +diff --git a/target/linux/generic/pending-4.14/141-jffs2-add-RENAME_EXCHANGE-support.patch b/target/linux/generic/pending-4.14/141-jffs2-add-RENAME_EXCHANGE-support.patch +new file mode 100644 +index 0000000000..093a73ab66 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/141-jffs2-add-RENAME_EXCHANGE-support.patch +@@ -0,0 +1,73 @@ ++From: Felix Fietkau ++Subject: jffs2: add RENAME_EXCHANGE support ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/fs/jffs2/dir.c +++++ b/fs/jffs2/dir.c ++@@ -777,18 +777,31 @@ static int jffs2_rename (struct inode *o ++ int ret; ++ struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); ++ struct jffs2_inode_info *victim_f = NULL; +++ struct inode *fst_inode = d_inode(old_dentry); +++ struct inode *snd_inode = d_inode(new_dentry); ++ uint8_t type; ++ uint32_t now; ++ ++- if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT)) +++ if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT|RENAME_EXCHANGE)) ++ return -EINVAL; ++ +++ if ((flags & RENAME_EXCHANGE) && (old_dir_i != new_dir_i)) { +++ if (S_ISDIR(fst_inode->i_mode) && !S_ISDIR(snd_inode->i_mode)) { +++ inc_nlink(new_dir_i); +++ drop_nlink(old_dir_i); +++ } +++ else if (!S_ISDIR(fst_inode->i_mode) && S_ISDIR(snd_inode->i_mode)) { +++ drop_nlink(new_dir_i); +++ inc_nlink(old_dir_i); +++ } +++ } +++ ++ /* The VFS will check for us and prevent trying to rename a ++ * file over a directory and vice versa, but if it's a directory, ++ * the VFS can't check whether the victim is empty. The filesystem ++ * needs to do that for itself. ++ */ ++- if (d_really_is_positive(new_dentry)) { +++ if (d_really_is_positive(new_dentry) && !(flags & RENAME_EXCHANGE)) { ++ victim_f = JFFS2_INODE_INFO(d_inode(new_dentry)); ++ if (d_is_dir(new_dentry)) { ++ struct jffs2_full_dirent *fd; ++@@ -823,7 +836,7 @@ static int jffs2_rename (struct inode *o ++ if (ret) ++ return ret; ++ ++- if (victim_f) { +++ if (victim_f && !(flags & RENAME_EXCHANGE)) { ++ /* There was a victim. Kill it off nicely */ ++ if (d_is_dir(new_dentry)) ++ clear_nlink(d_inode(new_dentry)); ++@@ -849,6 +862,12 @@ static int jffs2_rename (struct inode *o ++ if (flags & RENAME_WHITEOUT) ++ /* Replace with whiteout */ ++ ret = jffs2_whiteout(old_dir_i, old_dentry); +++ else if (flags & RENAME_EXCHANGE) +++ /* Replace the original */ +++ ret = jffs2_do_link(c, JFFS2_INODE_INFO(old_dir_i), +++ d_inode(new_dentry)->i_ino, type, +++ old_dentry->d_name.name, old_dentry->d_name.len, +++ now); ++ else ++ /* Unlink the original */ ++ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), ++@@ -880,7 +899,7 @@ static int jffs2_rename (struct inode *o ++ return ret; ++ } ++ ++- if (d_is_dir(old_dentry)) +++ if (d_is_dir(old_dentry) && !(flags & RENAME_EXCHANGE)) ++ drop_nlink(old_dir_i); ++ ++ new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); +diff --git a/target/linux/generic/pending-4.14/150-bridge_allow_receiption_on_disabled_port.patch b/target/linux/generic/pending-4.14/150-bridge_allow_receiption_on_disabled_port.patch +new file mode 100644 +index 0000000000..d50280a881 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/150-bridge_allow_receiption_on_disabled_port.patch +@@ -0,0 +1,47 @@ ++From: Stephen Hemminger ++Subject: bridge: allow receiption on disabled port ++ ++When an ethernet device is enslaved to a bridge, and the bridge STP ++detects loss of carrier (or operational state down), then normally ++packet receiption is blocked. ++ ++This breaks control applications like WPA which maybe expecting to ++receive packets to negotiate to bring link up. The bridge needs to ++block forwarding packets from these disabled ports, but there is no ++hard requirement to not allow local packet delivery. ++ ++Signed-off-by: Stephen Hemminger ++Signed-off-by: Felix Fietkau ++ ++--- a/net/bridge/br_input.c +++++ b/net/bridge/br_input.c ++@@ -237,7 +237,10 @@ static void __br_handle_local_finish(str ++ /* note: already called with rcu_read_lock */ ++ static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb) ++ { ++- __br_handle_local_finish(skb); +++ struct net_bridge_port *p = br_port_get_rcu(skb->dev); +++ +++ if (p->state != BR_STATE_DISABLED) +++ __br_handle_local_finish(skb); ++ ++ /* return 1 to signal the okfn() was called so it's ok to use the skb */ ++ return 1; ++@@ -332,6 +335,17 @@ rx_handler_result_t br_handle_frame(stru ++ ++ forward: ++ switch (p->state) { +++ case BR_STATE_DISABLED: +++ if (ether_addr_equal(p->br->dev->dev_addr, dest)) +++ skb->pkt_type = PACKET_HOST; +++ +++ if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, +++ dev_net(skb->dev), NULL, skb, skb->dev, NULL, +++ br_handle_local_finish) == 1) { +++ return RX_HANDLER_PASS; +++ } +++ break; +++ ++ case BR_STATE_FORWARDING: ++ rhook = rcu_dereference(br_should_route_hook); ++ if (rhook) { +diff --git a/target/linux/generic/pending-4.14/161-mtd-part-add-generic-parsing-of-linux-part-probe.patch b/target/linux/generic/pending-4.14/161-mtd-part-add-generic-parsing-of-linux-part-probe.patch +new file mode 100644 +index 0000000000..bf0c289227 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/161-mtd-part-add-generic-parsing-of-linux-part-probe.patch +@@ -0,0 +1,172 @@ ++From: Hauke Mehrtens ++Subject: mtd: part: add generic parsing of linux,part-probe ++ ++This moves the linux,part-probe device tree parsing code from ++physmap_of.c to mtdpart.c. Now all drivers can use this feature by just ++providing a reference to their device tree node in struct ++mtd_part_parser_data. ++ ++THIS METHOD HAS BEEN DEPRECATED ++ ++Linux supports "compatible" property in the "partitions" subnode now. It ++should be used to specify partitions format (and trigger proper parser ++usage) if needed. ++ ++Signed-off-by: Hauke Mehrtens ++--- ++ Documentation/devicetree/bindings/mtd/nand.txt | 16 +++++++++ ++ drivers/mtd/maps/physmap_of.c | 46 +------------------------- ++ drivers/mtd/mtdpart.c | 45 +++++++++++++++++++++++++ ++ 3 files changed, 62 insertions(+), 45 deletions(-) ++ ++--- a/Documentation/devicetree/bindings/mtd/nand.txt +++++ b/Documentation/devicetree/bindings/mtd/nand.txt ++@@ -44,6 +44,22 @@ Optional NAND chip properties: ++ used by the upper layers, and you want to make your NAND ++ as reliable as possible. ++ +++- linux,part-probe: list of name as strings of the partition parser +++ which should be used to parse the partition table. +++ They will be tried in the specified ordering and +++ the next one will be used if the previous one +++ failed. +++ +++ Example: linux,part-probe = "cmdlinepart", "ofpart"; +++ +++ This is also the default value, which will be used +++ if this attribute is not specified. It could be +++ that the flash driver in use overwrote the default +++ value and uses some other default. +++ +++ Possible values are: bcm47xxpart, afs, ar7part, +++ ofoldpart, ofpart, bcm63xxpart, RedBoot, cmdlinepart +++ ++ The ECC strength and ECC step size properties define the correction capability ++ of a controller. Together, they say a controller can correct "{strength} bit ++ errors per {size} bytes". ++--- a/drivers/mtd/maps/physmap_of_core.c +++++ b/drivers/mtd/maps/physmap_of_core.c ++@@ -105,37 +105,9 @@ static struct mtd_info *obsolete_probe(s ++ static const char * const part_probe_types_def[] = { ++ "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL }; ++ ++-static const char * const *of_get_probes(struct device_node *dp) ++-{ ++- const char **res; ++- int count; ++- ++- count = of_property_count_strings(dp, "linux,part-probe"); ++- if (count < 0) ++- return part_probe_types_def; ++- ++- res = kzalloc((count + 1) * sizeof(*res), GFP_KERNEL); ++- if (!res) ++- return NULL; ++- ++- count = of_property_read_string_array(dp, "linux,part-probe", res, ++- count); ++- if (count < 0) ++- return NULL; ++- ++- return res; ++-} ++- ++-static void of_free_probes(const char * const *probes) ++-{ ++- if (probes != part_probe_types_def) ++- kfree(probes); ++-} ++- ++ static const struct of_device_id of_flash_match[]; ++ static int of_flash_probe(struct platform_device *dev) ++ { ++- const char * const *part_probe_types; ++ const struct of_device_id *match; ++ struct device_node *dp = dev->dev.of_node; ++ struct resource res; ++@@ -293,14 +265,8 @@ static int of_flash_probe(struct platfor ++ ++ info->cmtd->dev.parent = &dev->dev; ++ mtd_set_of_node(info->cmtd, dp); ++- part_probe_types = of_get_probes(dp); ++- if (!part_probe_types) { ++- err = -ENOMEM; ++- goto err_out; ++- } ++- mtd_device_parse_register(info->cmtd, part_probe_types, NULL, +++ mtd_device_parse_register(info->cmtd, part_probe_types_def, NULL, ++ NULL, 0); ++- of_free_probes(part_probe_types); ++ ++ kfree(mtd_list); ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -29,6 +29,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ ++@@ -869,6 +870,37 @@ void deregister_mtd_parser(struct mtd_pa ++ } ++ EXPORT_SYMBOL_GPL(deregister_mtd_parser); ++ +++#include +++ +++/* +++ * Parses the linux,part-probe device tree property. +++ * When a non null value is returned it has to be freed with kfree() by +++ * the caller. +++ */ +++static const char * const *of_get_probes(struct device_node *dp) +++{ +++ const char **res; +++ int count; +++ +++ count = of_property_count_strings(dp, "linux,part-probe"); +++ if (count < 0) +++ return NULL; +++ +++ res = kzalloc((count + 1) * sizeof(*res), GFP_KERNEL); +++ if (!res) +++ return NULL; +++ +++ count = of_property_read_string_array(dp, "linux,part-probe", res, +++ count); +++ if (count < 0) +++ return NULL; +++ +++ pr_warn("Support for the generic \"linux,part-probe\" has been deprecated and will be removed soon"); +++ BUILD_BUG_ON(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)); +++ +++ return res; +++} +++ ++ /* ++ * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you ++ * are changing this array! ++@@ -1018,6 +1050,13 @@ int parse_mtd_partitions(struct mtd_info ++ struct mtd_partitions pparts = { }; ++ struct mtd_part_parser *parser; ++ int ret, err = 0; +++ const char *const *types_of = NULL; +++ +++ if (mtd_get_of_node(master)) { +++ types_of = of_get_probes(mtd_get_of_node(master)); +++ if (types_of != NULL) +++ types = types_of; +++ } ++ ++ if (!types) ++ types = mtd_is_partition(master) ? default_subpartition_types : ++@@ -1059,6 +1098,7 @@ int parse_mtd_partitions(struct mtd_info ++ if (ret < 0 && !err) ++ err = ret; ++ } +++ kfree(types_of); ++ return err; ++ } ++ +diff --git a/target/linux/generic/pending-4.14/171-usb-dwc2-Fix-inefficient-copy-of-unaligned-buffers.patch b/target/linux/generic/pending-4.14/171-usb-dwc2-Fix-inefficient-copy-of-unaligned-buffers.patch +new file mode 100644 +index 0000000000..7f21fefc25 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/171-usb-dwc2-Fix-inefficient-copy-of-unaligned-buffers.patch +@@ -0,0 +1,50 @@ ++From 81da1738eee68f1961e03bdeb2d60cf0eb4dd713 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Antti=20Sepp=C3=A4l=C3=A4?= ++Date: Thu, 5 Jul 2018 12:06:18 +0300 ++Subject: [PATCH 2/2] usb: dwc2: Fix inefficient copy of unaligned buffers ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Make sure only to copy any actual data rather than the whole buffer, ++when releasing the temporary buffer used for unaligned non-isochronous ++transfers. ++ ++Taken directly from commit 0efd937e27d5e ("USB: ehci-tegra: fix inefficient ++copy of unaligned buffers") ++ ++Tested with Lantiq xRX200 (MIPS) and RPi Model B Rev 2 (ARM) ++ ++Signed-off-by: Antti Seppälä ++--- ++ drivers/usb/dwc2/hcd.c | 12 +++++++++--- ++ 1 file changed, 9 insertions(+), 3 deletions(-) ++ ++--- a/drivers/usb/dwc2/hcd.c +++++ b/drivers/usb/dwc2/hcd.c ++@@ -2669,6 +2669,7 @@ static int dwc2_alloc_split_dma_aligned_ ++ static void dwc2_free_dma_aligned_buffer(struct urb *urb) ++ { ++ void *stored_xfer_buffer; +++ size_t length; ++ ++ if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) ++ return; ++@@ -2679,9 +2680,14 @@ static void dwc2_free_dma_aligned_buffer ++ dma_get_cache_alignment()), ++ sizeof(urb->transfer_buffer)); ++ ++- if (usb_urb_dir_in(urb)) ++- memcpy(stored_xfer_buffer, urb->transfer_buffer, ++- urb->transfer_buffer_length); +++ if (usb_urb_dir_in(urb)) { +++ if (usb_pipeisoc(urb->pipe)) +++ length = urb->transfer_buffer_length; +++ else +++ length = urb->actual_length; +++ +++ memcpy(stored_xfer_buffer, urb->transfer_buffer, length); +++ } ++ kfree(urb->transfer_buffer); ++ urb->transfer_buffer = stored_xfer_buffer; ++ +diff --git a/target/linux/generic/pending-4.14/180-net-phy-at803x-add-support-for-AT8032.patch b/target/linux/generic/pending-4.14/180-net-phy-at803x-add-support-for-AT8032.patch +new file mode 100644 +index 0000000000..828b160be9 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/180-net-phy-at803x-add-support-for-AT8032.patch +@@ -0,0 +1,73 @@ ++From: Felix Fietkau ++Subject: net: phy: at803x: add support for AT8032 ++ ++Like AT8030, this PHY needs the GPIO reset workaround ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/phy/at803x.c +++++ b/drivers/net/phy/at803x.c ++@@ -62,8 +62,10 @@ ++ ++ #define ATH8030_PHY_ID 0x004dd076 ++ #define ATH8031_PHY_ID 0x004dd074 +++#define ATH8032_PHY_ID 0x004dd023 ++ #define ATH8035_PHY_ID 0x004dd072 ++ #define AT803X_PHY_ID_MASK 0xffffffef +++#define AT8032_PHY_ID_MASK 0xffffffff ++ ++ MODULE_DESCRIPTION("Atheros 803x PHY driver"); ++ MODULE_AUTHOR("Matus Ujhelyi"); ++@@ -256,7 +258,8 @@ static int at803x_probe(struct phy_devic ++ if (!priv) ++ return -ENOMEM; ++ ++- if (phydev->drv->phy_id != ATH8030_PHY_ID) +++ if (phydev->drv->phy_id != ATH8030_PHY_ID && +++ phydev->drv->phy_id != ATH8032_PHY_ID) ++ goto does_not_require_reset_workaround; ++ ++ gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); ++@@ -332,7 +335,7 @@ static void at803x_link_change_notify(st ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* ++- * Conduct a hardware reset for AT8030 every time a link loss is +++ * Conduct a hardware reset for AT8030/2 every time a link loss is ++ * signalled. This is necessary to circumvent a hardware bug that ++ * occurs when the cable is unplugged while TX packets are pending ++ * in the FIFO. In such cases, the FIFO enters an error mode it ++@@ -444,6 +447,24 @@ static struct phy_driver at803x_driver[] ++ .aneg_done = at803x_aneg_done, ++ .ack_interrupt = &at803x_ack_interrupt, ++ .config_intr = &at803x_config_intr, +++}, { +++ /* ATHEROS 8032 */ +++ .phy_id = ATH8032_PHY_ID, +++ .name = "Atheros 8032 ethernet", +++ .phy_id_mask = AT8032_PHY_ID_MASK, +++ .probe = at803x_probe, +++ .config_init = at803x_config_init, +++ .link_change_notify = at803x_link_change_notify, +++ .set_wol = at803x_set_wol, +++ .get_wol = at803x_get_wol, +++ .suspend = at803x_suspend, +++ .resume = at803x_resume, +++ .features = PHY_BASIC_FEATURES, +++ .flags = PHY_HAS_INTERRUPT, +++ .config_aneg = genphy_config_aneg, +++ .read_status = genphy_read_status, +++ .ack_interrupt = at803x_ack_interrupt, +++ .config_intr = at803x_config_intr, ++ } }; ++ ++ module_phy_driver(at803x_driver); ++@@ -451,6 +472,7 @@ module_phy_driver(at803x_driver); ++ static struct mdio_device_id __maybe_unused atheros_tbl[] = { ++ { ATH8030_PHY_ID, AT803X_PHY_ID_MASK }, ++ { ATH8031_PHY_ID, AT803X_PHY_ID_MASK }, +++ { ATH8032_PHY_ID, AT8032_PHY_ID_MASK }, ++ { ATH8035_PHY_ID, AT803X_PHY_ID_MASK }, ++ { } ++ }; +diff --git a/target/linux/generic/pending-4.14/190-2-5-e1000e-Fix-wrong-comment-related-to-link-detection.patch b/target/linux/generic/pending-4.14/190-2-5-e1000e-Fix-wrong-comment-related-to-link-detection.patch +new file mode 100644 +index 0000000000..aaf21f075f +--- /dev/null ++++ b/target/linux/generic/pending-4.14/190-2-5-e1000e-Fix-wrong-comment-related-to-link-detection.patch +@@ -0,0 +1,43 @@ ++From patchwork Fri Jul 21 18:36:24 2017 ++Content-Type: text/plain; charset="utf-8" ++MIME-Version: 1.0 ++Content-Transfer-Encoding: 7bit ++Subject: [2/5] e1000e: Fix wrong comment related to link detection ++From: Benjamin Poirier ++X-Patchwork-Id: 9857489 ++Message-Id: <20170721183627.13373-2-bpoirier@suse.com> ++To: Jeff Kirsher ++Cc: Lennart Sorensen , ++ intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, ++ linux-kernel@vger.kernel.org ++Date: Fri, 21 Jul 2017 11:36:24 -0700 ++ ++Reading e1000e_check_for_copper_link() shows that get_link_status is set to ++false after link has been detected. Therefore, it stays TRUE until then. ++ ++Signed-off-by: Benjamin Poirier ++Tested-by: Aaron Brown ++--- ++ drivers/net/ethernet/intel/e1000e/netdev.c | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++--- a/drivers/net/ethernet/intel/e1000e/netdev.c +++++ b/drivers/net/ethernet/intel/e1000e/netdev.c ++@@ -5080,7 +5080,7 @@ static bool e1000e_has_link(struct e1000 ++ ++ /* get_link_status is set on LSC (link status) interrupt or ++ * Rx sequence error interrupt. get_link_status will stay ++- * false until the check_for_link establishes link +++ * true until the check_for_link establishes link ++ * for copper adapters ONLY ++ */ ++ switch (hw->phy.media_type) { ++@@ -5098,7 +5098,7 @@ static bool e1000e_has_link(struct e1000 ++ break; ++ case e1000_media_type_internal_serdes: ++ ret_val = hw->mac.ops.check_for_link(hw); ++- link_active = adapter->hw.mac.serdes_has_link; +++ link_active = hw->mac.serdes_has_link; ++ break; ++ default: ++ case e1000_media_type_unknown: +diff --git a/target/linux/generic/pending-4.14/201-extra_optimization.patch b/target/linux/generic/pending-4.14/201-extra_optimization.patch +new file mode 100644 +index 0000000000..aef36a8c11 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/201-extra_optimization.patch +@@ -0,0 +1,28 @@ ++From: Felix Fietkau ++Subject: Upgrade to Linux 2.6.19 ++ ++- Includes large parts of the patch from #1021 by dpalffy ++- Includes RB532 NAND driver changes by n0-1 ++ ++[john@phrozen.org: feix will add this to his upstream queue] ++ ++lede-commit: bff468813f78f81e36ebb2a3f4354de7365e640f ++Signed-off-by: Felix Fietkau ++--- ++ Makefile | 6 +++--- ++ 1 file changed, 3 insertions(+), 3 deletions(-) ++ ++--- a/Makefile +++++ b/Makefile ++@@ -652,9 +652,9 @@ KBUILD_CFLAGS += $(call cc-disable-warni ++ KBUILD_CFLAGS += $(call cc-disable-warning, attribute-alias) ++ ++ ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE ++-KBUILD_CFLAGS += -Os +++KBUILD_CFLAGS += -Os $(EXTRA_OPTIMIZATION) ++ else ++-KBUILD_CFLAGS += -O2 +++KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch $(EXTRA_OPTIMIZATION) ++ endif ++ ++ # Tell gcc to never replace conditional load with a non-conditional one +diff --git a/target/linux/generic/pending-4.14/203-kallsyms_uncompressed.patch b/target/linux/generic/pending-4.14/203-kallsyms_uncompressed.patch +new file mode 100644 +index 0000000000..1f5c83e94f +--- /dev/null ++++ b/target/linux/generic/pending-4.14/203-kallsyms_uncompressed.patch +@@ -0,0 +1,119 @@ ++From: Felix Fietkau ++Subject: kernel: add a config option for keeping the kallsyms table uncompressed, saving ~9kb kernel size after lzma on ar71xx ++ ++[john@phrozen.org: added to my upstream queue 30.12.2016] ++lede-commit: e0e3509b5ce2ccf93d4d67ea907613f5f7ec2eed ++Signed-off-by: Felix Fietkau ++--- ++ init/Kconfig | 11 +++++++++++ ++ kernel/kallsyms.c | 8 ++++++++ ++ scripts/kallsyms.c | 12 ++++++++++++ ++ scripts/link-vmlinux.sh | 4 ++++ ++ 4 files changed, 35 insertions(+) ++ ++--- a/init/Kconfig +++++ b/init/Kconfig ++@@ -1081,6 +1081,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW ++ the unaligned access emulation. ++ see arch/parisc/kernel/unaligned.c for reference ++ +++config KALLSYMS_UNCOMPRESSED +++ bool "Keep kallsyms uncompressed" +++ depends on KALLSYMS +++ help +++ Normally kallsyms contains compressed symbols (using a token table), +++ reducing the uncompressed kernel image size. Keeping the symbol table +++ uncompressed significantly improves the size of this part in compressed +++ kernel images. +++ +++ Say N unless you need compressed kernel images to be small. +++ ++ config HAVE_PCSPKR_PLATFORM ++ bool ++ ++--- a/kernel/kallsyms.c +++++ b/kernel/kallsyms.c ++@@ -108,6 +108,11 @@ static unsigned int kallsyms_expand_symb ++ * For every byte on the compressed symbol data, copy the table ++ * entry for that byte. ++ */ +++#ifdef CONFIG_KALLSYMS_UNCOMPRESSED +++ memcpy(result, data + 1, len - 1); +++ result += len - 1; +++ len = 0; +++#endif ++ while (len) { ++ tptr = &kallsyms_token_table[kallsyms_token_index[*data]]; ++ data++; ++@@ -140,6 +145,9 @@ tail: ++ */ ++ static char kallsyms_get_symbol_type(unsigned int off) ++ { +++#ifdef CONFIG_KALLSYMS_UNCOMPRESSED +++ return kallsyms_names[off + 1]; +++#endif ++ /* ++ * Get just the first code, look it up in the token table, ++ * and return the first char from this token. ++--- a/scripts/kallsyms.c +++++ b/scripts/kallsyms.c ++@@ -61,6 +61,7 @@ static struct addr_range percpu_range = ++ static struct sym_entry *table; ++ static unsigned int table_size, table_cnt; ++ static int all_symbols = 0; +++static int uncompressed = 0; ++ static int absolute_percpu = 0; ++ static char symbol_prefix_char = '\0'; ++ static int base_relative = 0; ++@@ -461,6 +462,9 @@ static void write_src(void) ++ ++ free(markers); ++ +++ if (uncompressed) +++ return; +++ ++ output_label("kallsyms_token_table"); ++ off = 0; ++ for (i = 0; i < 256; i++) { ++@@ -521,6 +525,9 @@ static void *find_token(unsigned char *s ++ { ++ int i; ++ +++ if (uncompressed) +++ return NULL; +++ ++ for (i = 0; i < len - 1; i++) { ++ if (str[i] == token[0] && str[i+1] == token[1]) ++ return &str[i]; ++@@ -593,6 +600,9 @@ static void optimize_result(void) ++ { ++ int i, best; ++ +++ if (uncompressed) +++ return; +++ ++ /* using the '\0' symbol last allows compress_symbols to use standard ++ * fast string functions */ ++ for (i = 255; i >= 0; i--) { ++@@ -781,6 +791,8 @@ int main(int argc, char **argv) ++ symbol_prefix_char = *p; ++ } else if (strcmp(argv[i], "--base-relative") == 0) ++ base_relative = 1; +++ else if (strcmp(argv[i], "--uncompressed") == 0) +++ uncompressed = 1; ++ else ++ usage(); ++ } ++--- a/scripts/link-vmlinux.sh +++++ b/scripts/link-vmlinux.sh ++@@ -164,6 +164,10 @@ kallsyms() ++ kallsymopt="${kallsymopt} --base-relative" ++ fi ++ +++ if [ -n "${CONFIG_KALLSYMS_UNCOMPRESSED}" ]; then +++ kallsymopt="${kallsymopt} --uncompressed" +++ fi +++ ++ local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ ++ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" ++ +diff --git a/target/linux/generic/pending-4.14/205-backtrace_module_info.patch b/target/linux/generic/pending-4.14/205-backtrace_module_info.patch +new file mode 100644 +index 0000000000..4040f91021 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/205-backtrace_module_info.patch +@@ -0,0 +1,45 @@ ++From: Felix Fietkau ++Subject: kernel: when KALLSYMS is disabled, print module address + size for matching backtrace entries ++ ++[john@phrozen.org: felix will add this to his upstream queue] ++ ++lede-commit 53827cdc824556cda910b23ce5030c363b8f1461 ++Signed-off-by: Felix Fietkau ++--- ++ lib/vsprintf.c | 15 +++++++++++---- ++ 1 file changed, 11 insertions(+), 4 deletions(-) ++ ++--- a/lib/vsprintf.c +++++ b/lib/vsprintf.c ++@@ -670,8 +670,10 @@ char *symbol_string(char *buf, char *end ++ struct printf_spec spec, const char *fmt) ++ { ++ unsigned long value; ++-#ifdef CONFIG_KALLSYMS ++ char sym[KSYM_SYMBOL_LEN]; +++#ifndef CONFIG_KALLSYMS +++ struct module *mod; +++ int len; ++ #endif ++ ++ if (fmt[1] == 'R') ++@@ -685,11 +687,16 @@ char *symbol_string(char *buf, char *end ++ sprint_symbol(sym, value); ++ else ++ sprint_symbol_no_offset(sym, value); ++- ++- return string(buf, end, sym, spec); ++ #else ++- return special_hex_number(buf, end, value, sizeof(void *)); +++ len = snprintf(sym, sizeof(sym), "0x%lx", value); +++ +++ mod = __module_address(value); +++ if (mod) +++ snprintf(sym + len, sizeof(sym) - len, " [%s@%p+0x%x]", +++ mod->name, mod->core_layout.base, +++ mod->core_layout.size); ++ #endif +++ return string(buf, end, sym, spec); ++ } ++ ++ static noinline_for_stack +diff --git a/target/linux/generic/pending-4.14/220-optimize_inlining.patch b/target/linux/generic/pending-4.14/220-optimize_inlining.patch +new file mode 100644 +index 0000000000..76aabf86db +--- /dev/null ++++ b/target/linux/generic/pending-4.14/220-optimize_inlining.patch +@@ -0,0 +1,165 @@ ++--- a/arch/arm/kernel/atags.h +++++ b/arch/arm/kernel/atags.h ++@@ -5,7 +5,7 @@ void convert_to_tag_list(struct tag *tag ++ const struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer, ++ unsigned int machine_nr); ++ #else ++-static inline const struct machine_desc * +++static inline const struct machine_desc * __init __noreturn ++ setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr) ++ { ++ early_print("no ATAGS support: can't continue\n"); ++--- a/arch/arm64/include/asm/cpufeature.h +++++ b/arch/arm64/include/asm/cpufeature.h ++@@ -347,7 +347,7 @@ static inline bool cpu_have_feature(unsi ++ } ++ ++ /* System capability check for constant caps */ ++-static inline bool __cpus_have_const_cap(int num) +++static __always_inline bool __cpus_have_const_cap(int num) ++ { ++ if (num >= ARM64_NCAPS) ++ return false; ++@@ -361,7 +361,7 @@ static inline bool cpus_have_cap(unsigne ++ return test_bit(num, cpu_hwcaps); ++ } ++ ++-static inline bool cpus_have_const_cap(int num) +++static __always_inline bool cpus_have_const_cap(int num) ++ { ++ if (static_branch_likely(&arm64_const_caps_ready)) ++ return __cpus_have_const_cap(num); ++--- a/arch/mips/include/asm/bitops.h +++++ b/arch/mips/include/asm/bitops.h ++@@ -462,7 +462,7 @@ static inline void __clear_bit_unlock(un ++ * Return the bit position (0..63) of the most significant 1 bit in a word ++ * Returns -1 if no 1 bit exists ++ */ ++-static inline unsigned long __fls(unsigned long word) +++static __always_inline unsigned long __fls(unsigned long word) ++ { ++ int num; ++ ++@@ -528,7 +528,7 @@ static inline unsigned long __fls(unsign ++ * Returns 0..SZLONG-1 ++ * Undefined if no bit exists, so code should check against 0 first. ++ */ ++-static inline unsigned long __ffs(unsigned long word) +++static __always_inline unsigned long __ffs(unsigned long word) ++ { ++ return __fls(word & -word); ++ } ++--- a/arch/mips/kernel/cpu-bugs64.c +++++ b/arch/mips/kernel/cpu-bugs64.c ++@@ -42,8 +42,8 @@ static inline void align_mod(const int a ++ : GCC_IMM_ASM() (align), GCC_IMM_ASM() (mod)); ++ } ++ ++-static inline void mult_sh_align_mod(long *v1, long *v2, long *w, ++- const int align, const int mod) +++static __always_inline void mult_sh_align_mod(long *v1, long *v2, long *w, +++ const int align, const int mod) ++ { ++ unsigned long flags; ++ int m1, m2; ++--- a/arch/powerpc/kernel/prom_init.c +++++ b/arch/powerpc/kernel/prom_init.c ++@@ -474,14 +474,14 @@ static int __init prom_next_node(phandle ++ } ++ } ++ ++-static inline int prom_getprop(phandle node, const char *pname, ++- void *value, size_t valuelen) +++static inline int __init prom_getprop(phandle node, const char *pname, +++ void *value, size_t valuelen) ++ { ++ return call_prom("getprop", 4, 1, node, ADDR(pname), ++ (u32)(unsigned long) value, (u32) valuelen); ++ } ++ ++-static inline int prom_getproplen(phandle node, const char *pname) +++static inline int __init prom_getproplen(phandle node, const char *pname) ++ { ++ return call_prom("getproplen", 2, 1, node, ADDR(pname)); ++ } ++--- a/arch/s390/include/asm/cpacf.h +++++ b/arch/s390/include/asm/cpacf.h ++@@ -184,7 +184,7 @@ static inline int __cpacf_check_opcode(u ++ } ++ } ++ ++-static inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask) +++static __always_inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask) ++ { ++ if (__cpacf_check_opcode(opcode)) { ++ __cpacf_query(opcode, mask); ++--- a/arch/x86/Kconfig.debug +++++ b/arch/x86/Kconfig.debug ++@@ -284,20 +284,6 @@ config CPA_DEBUG ++ ---help--- ++ Do change_page_attr() self-tests every 30 seconds. ++ ++-config OPTIMIZE_INLINING ++- bool "Allow gcc to uninline functions marked 'inline'" ++- ---help--- ++- This option determines if the kernel forces gcc to inline the functions ++- developers have marked 'inline'. Doing so takes away freedom from gcc to ++- do what it thinks is best, which is desirable for the gcc 3.x series of ++- compilers. The gcc 4.x series have a rewritten inlining algorithm and ++- enabling this option will generate a smaller kernel there. Hopefully ++- this algorithm is so good that allowing gcc 4.x and above to make the ++- decision will become the default in the future. Until then this option ++- is there to test gcc for this. ++- ++- If unsure, say N. ++- ++ config DEBUG_ENTRY ++ bool "Debug low-level entry code" ++ depends on DEBUG_KERNEL ++--- a/lib/Kconfig.debug +++++ b/lib/Kconfig.debug ++@@ -305,6 +305,20 @@ config HEADERS_CHECK ++ exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in ++ your build tree), to make sure they're suitable. ++ +++config OPTIMIZE_INLINING +++ bool "Allow compiler to uninline functions marked 'inline'" +++ help +++ This option determines if the kernel forces gcc to inline the functions +++ developers have marked 'inline'. Doing so takes away freedom from gcc to +++ do what it thinks is best, which is desirable for the gcc 3.x series of +++ compilers. The gcc 4.x series have a rewritten inlining algorithm and +++ enabling this option will generate a smaller kernel there. Hopefully +++ this algorithm is so good that allowing gcc 4.x and above to make the +++ decision will become the default in the future. Until then this option +++ is there to test gcc for this. +++ +++ If unsure, say N. +++ ++ config DEBUG_SECTION_MISMATCH ++ bool "Enable full Section mismatch analysis" ++ help ++--- a/arch/x86/Kconfig +++++ b/arch/x86/Kconfig ++@@ -296,9 +296,6 @@ config ZONE_DMA32 ++ config AUDIT_ARCH ++ def_bool y if X86_64 ++ ++-config ARCH_SUPPORTS_OPTIMIZED_INLINING ++- def_bool y ++- ++ config ARCH_SUPPORTS_DEBUG_PAGEALLOC ++ def_bool y ++ ++--- a/include/linux/compiler-gcc.h +++++ b/include/linux/compiler-gcc.h ++@@ -90,8 +90,7 @@ ++ * of extern inline functions at link time. ++ * A lot of inline functions can cause havoc with function tracing. ++ */ ++-#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \ ++- !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4) +++#if !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4) ++ #define inline \ ++ inline __attribute__((always_inline, unused)) notrace __gnu_inline ++ #else +diff --git a/target/linux/generic/pending-4.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch b/target/linux/generic/pending-4.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch +new file mode 100644 +index 0000000000..c0dfe49c9b +--- /dev/null ++++ b/target/linux/generic/pending-4.14/240-remove-unsane-filenames-from-deps_initramfs-list.patch +@@ -0,0 +1,46 @@ ++From: Gabor Juhos ++Subject: usr: sanitize deps_initramfs list ++ ++If any filename in the intramfs dependency ++list contains a colon, that causes a kernel ++build error like this: ++ ++/devel/openwrt/build_dir/linux-ar71xx_generic/linux-3.6.6/usr/Makefile:58: *** multiple target patterns. Stop. ++make[5]: *** [usr] Error 2 ++ ++Fix it by removing such filenames from the ++deps_initramfs list. ++ ++Signed-off-by: Gabor Juhos ++--- ++ usr/Makefile | 8 +++++--- ++ 1 file changed, 5 insertions(+), 3 deletions(-) ++ ++--- a/usr/Makefile +++++ b/usr/Makefile ++@@ -42,20 +42,22 @@ ifneq ($(wildcard $(obj)/$(datafile_d_y) ++ include $(obj)/$(datafile_d_y) ++ endif ++ +++deps_initramfs_sane := $(foreach v,$(deps_initramfs),$(if $(findstring :,$(v)),,$(v))) +++ ++ quiet_cmd_initfs = GEN $@ ++ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input) ++ ++ targets := $(datafile_y) ++ ++ # do not try to update files included in initramfs ++-$(deps_initramfs): ; +++$(deps_initramfs_sane): ; ++ ++-$(deps_initramfs): klibcdirs +++$(deps_initramfs_sane): klibcdirs ++ # We rebuild initramfs_data.cpio if: ++ # 1) Any included file is newer then initramfs_data.cpio ++ # 2) There are changes in which files are included (added or deleted) ++ # 3) If gen_init_cpio are newer than initramfs_data.cpio ++ # 4) arguments to gen_initramfs.sh changes ++-$(obj)/$(datafile_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs +++$(obj)/$(datafile_y): $(obj)/gen_init_cpio $(deps_initramfs_sane) klibcdirs ++ $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/$(datafile_d_y) ++ $(call if_changed,initfs) +diff --git a/target/linux/generic/pending-4.14/261-enable_wilink_platform_without_drivers.patch b/target/linux/generic/pending-4.14/261-enable_wilink_platform_without_drivers.patch +new file mode 100644 +index 0000000000..9955ab3c0b +--- /dev/null ++++ b/target/linux/generic/pending-4.14/261-enable_wilink_platform_without_drivers.patch +@@ -0,0 +1,20 @@ ++From: Imre Kaloz ++Subject: [PATCH] hack: net: wireless: make the wl12xx glue code available with ++ compat-wireless, too ++ ++Signed-off-by: Imre Kaloz ++--- ++ drivers/net/wireless/ti/Kconfig | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/drivers/net/wireless/ti/Kconfig +++++ b/drivers/net/wireless/ti/Kconfig ++@@ -19,7 +19,7 @@ source "drivers/net/wireless/ti/wlcore/K ++ ++ config WILINK_PLATFORM_DATA ++ bool "TI WiLink platform data" ++- depends on WLCORE_SDIO || WL1251_SDIO +++ depends on WLCORE_SDIO || WL1251_SDIO || ARCH_OMAP2PLUS ++ default y ++ ---help--- ++ Small platform data bit needed to pass data to the sdio modules. +diff --git a/target/linux/generic/pending-4.14/270-platform-mikrotik-build-bits.patch b/target/linux/generic/pending-4.14/270-platform-mikrotik-build-bits.patch +new file mode 100644 +index 0000000000..15dfcb2eba +--- /dev/null ++++ b/target/linux/generic/pending-4.14/270-platform-mikrotik-build-bits.patch +@@ -0,0 +1,31 @@ ++From c2deb5ef01a0ef09088832744cbace9e239a6ee0 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= ++Date: Tue, 24 Mar 2020 22:11:50 +0100 ++Subject: [PATCH] generic: platform/mikrotik build bits (4.14) ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This patch adds platform/mikrotik kernel build bits ++ ++Signed-off-by: Thibaut VARÈNE ++--- ++ drivers/platform/Kconfig | 2 ++ ++ drivers/platform/Makefile | 1 + ++ 2 files changed, 3 insertions(+) ++ ++--- a/drivers/platform/Kconfig +++++ b/drivers/platform/Kconfig ++@@ -8,3 +8,5 @@ endif ++ source "drivers/platform/goldfish/Kconfig" ++ ++ source "drivers/platform/chrome/Kconfig" +++ +++source "drivers/platform/mikrotik/Kconfig" ++--- a/drivers/platform/Makefile +++++ b/drivers/platform/Makefile ++@@ -8,3 +8,4 @@ obj-$(CONFIG_MIPS) += mips/ ++ obj-$(CONFIG_OLPC) += olpc/ ++ obj-$(CONFIG_GOLDFISH) += goldfish/ ++ obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ +++obj-$(CONFIG_MIKROTIK) += mikrotik/ +diff --git a/target/linux/generic/pending-4.14/300-mips_expose_boot_raw.patch b/target/linux/generic/pending-4.14/300-mips_expose_boot_raw.patch +new file mode 100644 +index 0000000000..71dff9b930 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/300-mips_expose_boot_raw.patch +@@ -0,0 +1,40 @@ ++From: Mark Miller ++Subject: mips: expose CONFIG_BOOT_RAW ++ ++This exposes the CONFIG_BOOT_RAW symbol in Kconfig. This is needed on ++certain Broadcom chipsets running CFE in order to load the kernel. ++ ++Signed-off-by: Mark Miller ++Acked-by: Rob Landley ++--- ++--- a/arch/mips/Kconfig +++++ b/arch/mips/Kconfig ++@@ -1068,9 +1068,6 @@ config FW_ARC ++ config ARCH_MAY_HAVE_PC_FDC ++ bool ++ ++-config BOOT_RAW ++- bool ++- ++ config CEVT_BCM1480 ++ bool ++ ++@@ -2968,6 +2965,18 @@ choice ++ bool "Extend builtin kernel arguments with bootloader arguments" ++ endchoice ++ +++config BOOT_RAW +++ bool "Enable the kernel to be executed from the load address" +++ default n +++ help +++ Allow the kernel to be executed from the load address for +++ bootloaders which cannot read the ELF format. This places +++ a jump to start_kernel at the load address. +++ +++ If unsure, say N. +++ +++ +++ ++ endmenu ++ ++ config LOCKDEP_SUPPORT +diff --git a/target/linux/generic/pending-4.14/302-mips_no_branch_likely.patch b/target/linux/generic/pending-4.14/302-mips_no_branch_likely.patch +new file mode 100644 +index 0000000000..0e4600237d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/302-mips_no_branch_likely.patch +@@ -0,0 +1,22 @@ ++From: Felix Fietkau ++Subject: mips: use -mno-branch-likely for kernel and userspace ++ ++saves ~11k kernel size after lzma and ~12k squashfs size in the ++ ++lede-commit: 41a039f46450ffae9483d6216422098669da2900 ++Signed-off-by: Felix Fietkau ++--- ++ arch/mips/Makefile | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/arch/mips/Makefile +++++ b/arch/mips/Makefile ++@@ -90,7 +90,7 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin ++ # machines may also. Since BFD is incredibly buggy with respect to ++ # crossformat linking we rely on the elf2ecoff tool for format conversion. ++ # ++-cflags-y += -G 0 -mno-abicalls -fno-pic -pipe +++cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely ++ cflags-y += -msoft-float ++ LDFLAGS_vmlinux += -G 0 -static -n -nostdlib ++ KBUILD_AFLAGS_MODULE += -mlong-calls +diff --git a/target/linux/generic/pending-4.14/304-mips_disable_fpu.patch b/target/linux/generic/pending-4.14/304-mips_disable_fpu.patch +new file mode 100644 +index 0000000000..47983df948 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/304-mips_disable_fpu.patch +@@ -0,0 +1,137 @@ ++From: Manuel Lauss ++Subject: [RFC PATCH v4 2/2] MIPS: make FPU emulator optional ++ ++This small patch makes the MIPS FPU emulator optional. The kernel ++kills float-users on systems without a hardware FPU by sending a SIGILL. ++ ++Disabling the emulator shrinks vmlinux by about 54kBytes (32bit, ++optimizing for size). ++ ++Signed-off-by: Manuel Lauss ++--- ++v4: rediffed because of patch 1/2, should now work with micromips as well ++v3: updated patch description with size savings. ++v2: incorporated changes suggested by Jonas Gorski ++ force the fpu emulator on for micromips: relocating the parts ++ of the mmips code in the emulator to other areas would be a ++ much larger change; I went the cheap route instead with this. ++ ++ arch/mips/Kbuild | 2 +- ++ arch/mips/Kconfig | 14 ++++++++++++++ ++ arch/mips/include/asm/fpu.h | 5 +++-- ++ arch/mips/include/asm/fpu_emulator.h | 15 +++++++++++++++ ++ 4 files changed, 33 insertions(+), 3 deletions(-) ++ ++--- a/arch/mips/Kconfig +++++ b/arch/mips/Kconfig ++@@ -2892,6 +2892,20 @@ config MIPS_O32_FP64_SUPPORT ++ ++ If unsure, say N. ++ +++config MIPS_FPU_EMULATOR +++ bool "MIPS FPU Emulator" +++ default y +++ help +++ This option lets you disable the built-in MIPS FPU (Coprocessor 1) +++ emulator, which handles floating-point instructions on processors +++ without a hardware FPU. It is generally a good idea to keep the +++ emulator built-in, unless you are perfectly sure you have a +++ complete soft-float environment. With the emulator disabled, all +++ users of float operations will be killed with an illegal instr- +++ uction exception. +++ +++ Say Y, please. +++ ++ config USE_OF ++ bool ++ select OF ++--- a/arch/mips/Makefile +++++ b/arch/mips/Makefile ++@@ -326,7 +326,7 @@ OBJCOPYFLAGS += --remove-section=.regin ++ head-y := arch/mips/kernel/head.o ++ ++ libs-y += arch/mips/lib/ ++-libs-y += arch/mips/math-emu/ +++libs-$(CONFIG_MIPS_FPU_EMULATOR) += arch/mips/math-emu/ ++ ++ # See arch/mips/Kbuild for content of core part of the kernel ++ core-y += arch/mips/ ++--- a/arch/mips/include/asm/fpu.h +++++ b/arch/mips/include/asm/fpu.h ++@@ -230,8 +230,10 @@ static inline int init_fpu(void) ++ /* Restore FRE */ ++ write_c0_config5(config5); ++ enable_fpu_hazard(); ++- } else +++ } else if (IS_ENABLED(CONFIG_MIPS_FPU_EMULATOR)) ++ fpu_emulator_init_fpu(); +++ else +++ ret = SIGILL; ++ ++ return ret; ++ } ++--- a/arch/mips/include/asm/fpu_emulator.h +++++ b/arch/mips/include/asm/fpu_emulator.h ++@@ -30,6 +30,7 @@ ++ #include ++ #include ++ +++#ifdef CONFIG_MIPS_FPU_EMULATOR ++ #ifdef CONFIG_DEBUG_FS ++ ++ struct mips_fpu_emulator_stats { ++@@ -179,6 +180,16 @@ do { \ ++ extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, ++ struct mips_fpu_struct *ctx, int has_fpu, ++ void __user **fault_addr); +++#else /* no CONFIG_MIPS_FPU_EMULATOR */ +++static inline int fpu_emulator_cop1Handler(struct pt_regs *xcp, +++ struct mips_fpu_struct *ctx, int has_fpu, +++ void __user **fault_addr) +++{ +++ *fault_addr = NULL; +++ return SIGILL; /* we don't speak MIPS FPU */ +++} +++#endif /* CONFIG_MIPS_FPU_EMULATOR */ +++ ++ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, ++ struct task_struct *tsk); ++ int process_fpemu_return(int sig, void __user *fault_addr, ++--- a/arch/mips/include/asm/dsemul.h +++++ b/arch/mips/include/asm/dsemul.h ++@@ -41,6 +41,7 @@ struct task_struct; ++ extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, ++ unsigned long branch_pc, unsigned long cont_pc); ++ +++#ifdef CONFIG_MIPS_FPU_EMULATOR ++ /** ++ * do_dsemulret() - Return from a delay slot 'emulation' frame ++ * @xcp: User thread register context. ++@@ -88,5 +89,27 @@ extern bool dsemul_thread_rollback(struc ++ * before @mm is freed in order to avoid memory leaks. ++ */ ++ extern void dsemul_mm_cleanup(struct mm_struct *mm); +++#else +++static inline bool do_dsemulret(struct pt_regs *xcp) +++{ +++ return false; +++} +++ +++static inline bool dsemul_thread_cleanup(struct task_struct *tsk) +++{ +++ return false; +++} +++ +++static inline bool dsemul_thread_rollback(struct pt_regs *regs) +++{ +++ return false; +++} +++ +++static inline void dsemul_mm_cleanup(struct mm_struct *mm) +++{ +++ +++} +++ +++#endif ++ ++ #endif /* __MIPS_ASM_DSEMUL_H__ */ +diff --git a/target/linux/generic/pending-4.14/305-mips_module_reloc.patch b/target/linux/generic/pending-4.14/305-mips_module_reloc.patch +new file mode 100644 +index 0000000000..609a96db49 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/305-mips_module_reloc.patch +@@ -0,0 +1,371 @@ ++From: Felix Fietkau ++Subject: mips: replace -mlong-calls with -mno-long-calls to make function calls faster in kernel modules to achieve this, try to ++ ++lede-commit: 3b3d64743ba2a874df9d70cd19e242205b0a788c ++Signed-off-by: Felix Fietkau ++--- ++ arch/mips/Makefile | 5 + ++ arch/mips/include/asm/module.h | 5 + ++ arch/mips/kernel/module.c | 279 ++++++++++++++++++++++++++++++++++++++++- ++ 3 files changed, 284 insertions(+), 5 deletions(-) ++ ++--- a/arch/mips/Makefile +++++ b/arch/mips/Makefile ++@@ -93,8 +93,18 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin ++ cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely ++ cflags-y += -msoft-float ++ LDFLAGS_vmlinux += -G 0 -static -n -nostdlib +++ifdef CONFIG_64BIT ++ KBUILD_AFLAGS_MODULE += -mlong-calls ++ KBUILD_CFLAGS_MODULE += -mlong-calls +++else +++ ifdef CONFIG_DYNAMIC_FTRACE +++ KBUILD_AFLAGS_MODULE += -mlong-calls +++ KBUILD_CFLAGS_MODULE += -mlong-calls +++ else +++ KBUILD_AFLAGS_MODULE += -mno-long-calls +++ KBUILD_CFLAGS_MODULE += -mno-long-calls +++ endif +++endif ++ ++ ifeq ($(CONFIG_RELOCATABLE),y) ++ LDFLAGS_vmlinux += --emit-relocs ++--- a/arch/mips/include/asm/module.h +++++ b/arch/mips/include/asm/module.h ++@@ -12,6 +12,11 @@ struct mod_arch_specific { ++ const struct exception_table_entry *dbe_start; ++ const struct exception_table_entry *dbe_end; ++ struct mips_hi16 *r_mips_hi16_list; +++ +++ void *phys_plt_tbl; +++ void *virt_plt_tbl; +++ unsigned int phys_plt_offset; +++ unsigned int virt_plt_offset; ++ }; ++ ++ typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ ++--- a/arch/mips/kernel/module.c +++++ b/arch/mips/kernel/module.c ++@@ -44,14 +44,221 @@ struct mips_hi16 { ++ static LIST_HEAD(dbe_list); ++ static DEFINE_SPINLOCK(dbe_lock); ++ ++-#ifdef MODULE_START +++/* +++ * Get the potential max trampolines size required of the init and +++ * non-init sections. Only used if we cannot find enough contiguous +++ * physically mapped memory to put the module into. +++ */ +++static unsigned int +++get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, +++ const char *secstrings, unsigned int symindex, bool is_init) +++{ +++ unsigned long ret = 0; +++ unsigned int i, j; +++ Elf_Sym *syms; +++ +++ /* Everything marked ALLOC (this includes the exported symbols) */ +++ for (i = 1; i < hdr->e_shnum; ++i) { +++ unsigned int info = sechdrs[i].sh_info; +++ +++ if (sechdrs[i].sh_type != SHT_REL +++ && sechdrs[i].sh_type != SHT_RELA) +++ continue; +++ +++ /* Not a valid relocation section? */ +++ if (info >= hdr->e_shnum) +++ continue; +++ +++ /* Don't bother with non-allocated sections */ +++ if (!(sechdrs[info].sh_flags & SHF_ALLOC)) +++ continue; +++ +++ /* If it's called *.init*, and we're not init, we're +++ not interested */ +++ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) +++ != is_init) +++ continue; +++ +++ syms = (Elf_Sym *) sechdrs[symindex].sh_addr; +++ if (sechdrs[i].sh_type == SHT_REL) { +++ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr; +++ unsigned int size = sechdrs[i].sh_size / sizeof(*rel); +++ +++ for (j = 0; j < size; ++j) { +++ Elf_Sym *sym; +++ +++ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26) +++ continue; +++ +++ sym = syms + ELF_MIPS_R_SYM(rel[j]); +++ if (!is_init && sym->st_shndx != SHN_UNDEF) +++ continue; +++ +++ ret += 4 * sizeof(int); +++ } +++ } else { +++ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr; +++ unsigned int size = sechdrs[i].sh_size / sizeof(*rela); +++ +++ for (j = 0; j < size; ++j) { +++ Elf_Sym *sym; +++ +++ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26) +++ continue; +++ +++ sym = syms + ELF_MIPS_R_SYM(rela[j]); +++ if (!is_init && sym->st_shndx != SHN_UNDEF) +++ continue; +++ +++ ret += 4 * sizeof(int); +++ } +++ } +++ } +++ +++ return ret; +++} +++ +++#ifndef MODULE_START +++static void *alloc_phys(unsigned long size) +++{ +++ unsigned order; +++ struct page *page; +++ struct page *p; +++ +++ size = PAGE_ALIGN(size); +++ order = get_order(size); +++ +++ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | +++ __GFP_THISNODE, order); +++ if (!page) +++ return NULL; +++ +++ split_page(page, order); +++ +++ /* mark all pages except for the last one */ +++ for (p = page; p + 1 < page + (size >> PAGE_SHIFT); ++p) +++ set_bit(PG_owner_priv_1, &p->flags); +++ +++ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p) +++ __free_page(p); +++ +++ return page_address(page); +++} +++#endif +++ +++static void free_phys(void *ptr) +++{ +++ struct page *page; +++ bool free; +++ +++ page = virt_to_page(ptr); +++ do { +++ free = test_and_clear_bit(PG_owner_priv_1, &page->flags); +++ __free_page(page); +++ page++; +++ } while (free); +++} +++ +++ ++ void *module_alloc(unsigned long size) ++ { +++#ifdef MODULE_START ++ return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END, ++ GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE, ++ __builtin_return_address(0)); +++#else +++ void *ptr; +++ +++ if (size == 0) +++ return NULL; +++ +++ ptr = alloc_phys(size); +++ +++ /* If we failed to allocate physically contiguous memory, +++ * fall back to regular vmalloc. The module loader code will +++ * create jump tables to handle long jumps */ +++ if (!ptr) +++ return vmalloc(size); +++ +++ return ptr; +++#endif ++ } +++ +++static inline bool is_phys_addr(void *ptr) +++{ +++#ifdef CONFIG_64BIT +++ return (KSEGX((unsigned long)ptr) == CKSEG0); +++#else +++ return (KSEGX(ptr) == KSEG0); ++ #endif +++} +++ +++/* Free memory returned from module_alloc */ +++void module_memfree(void *module_region) +++{ +++ if (is_phys_addr(module_region)) +++ free_phys(module_region); +++ else +++ vfree(module_region); +++} +++ +++static void *__module_alloc(int size, bool phys) +++{ +++ void *ptr; +++ +++ if (phys) +++ ptr = kmalloc(size, GFP_KERNEL); +++ else +++ ptr = vmalloc(size); +++ return ptr; +++} +++ +++static void __module_free(void *ptr) +++{ +++ if (is_phys_addr(ptr)) +++ kfree(ptr); +++ else +++ vfree(ptr); +++} +++ +++int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, +++ char *secstrings, struct module *mod) +++{ +++ unsigned int symindex = 0; +++ unsigned int core_size, init_size; +++ int i; +++ +++ mod->arch.phys_plt_offset = 0; +++ mod->arch.virt_plt_offset = 0; +++ mod->arch.phys_plt_tbl = NULL; +++ mod->arch.virt_plt_tbl = NULL; +++ +++ if (IS_ENABLED(CONFIG_64BIT)) +++ return 0; +++ +++ for (i = 1; i < hdr->e_shnum; i++) +++ if (sechdrs[i].sh_type == SHT_SYMTAB) +++ symindex = i; +++ +++ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); +++ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); +++ +++ if ((core_size + init_size) == 0) +++ return 0; +++ +++ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); +++ if (!mod->arch.phys_plt_tbl) +++ return -ENOMEM; +++ +++ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); +++ if (!mod->arch.virt_plt_tbl) { +++ __module_free(mod->arch.phys_plt_tbl); +++ mod->arch.phys_plt_tbl = NULL; +++ return -ENOMEM; +++ } +++ +++ return 0; +++} ++ ++ static int apply_r_mips_none(struct module *me, u32 *location, ++ u32 base, Elf_Addr v, bool rela) ++@@ -67,9 +274,40 @@ static int apply_r_mips_32(struct module ++ return 0; ++ } ++ +++static Elf_Addr add_plt_entry_to(unsigned *plt_offset, +++ void *start, Elf_Addr v) +++{ +++ unsigned *tramp = start + *plt_offset; +++ *plt_offset += 4 * sizeof(int); +++ +++ /* adjust carry for addiu */ +++ if (v & 0x00008000) +++ v += 0x10000; +++ +++ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ +++ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ +++ tramp[2] = 0x03200008; /* jr t9 */ +++ tramp[3] = 0x00000000; /* nop */ +++ +++ return (Elf_Addr) tramp; +++} +++ +++static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) +++{ +++ if (is_phys_addr(location)) +++ return add_plt_entry_to(&me->arch.phys_plt_offset, +++ me->arch.phys_plt_tbl, v); +++ else +++ return add_plt_entry_to(&me->arch.virt_plt_offset, +++ me->arch.virt_plt_tbl, v); +++ +++} +++ ++ static int apply_r_mips_26(struct module *me, u32 *location, ++ u32 base, Elf_Addr v, bool rela) ++ { +++ u32 ofs = base & 0x03ffffff; +++ ++ if (v % 4) { ++ pr_err("module %s: dangerous R_MIPS_26 relocation\n", ++ me->name); ++@@ -77,13 +315,17 @@ static int apply_r_mips_26(struct module ++ } ++ ++ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { ++- pr_err("module %s: relocation overflow\n", ++- me->name); ++- return -ENOEXEC; +++ v = add_plt_entry(me, location, v + (ofs << 2)); +++ if (!v) { +++ pr_err("module %s: relocation overflow\n", +++ me->name); +++ return -ENOEXEC; +++ } +++ ofs = 0; ++ } ++ ++ *location = (*location & ~0x03ffffff) | ++- ((base + (v >> 2)) & 0x03ffffff); +++ ((ofs + (v >> 2)) & 0x03ffffff); ++ ++ return 0; ++ } ++@@ -459,9 +701,36 @@ int module_finalize(const Elf_Ehdr *hdr, ++ list_add(&me->arch.dbe_list, &dbe_list); ++ spin_unlock_irq(&dbe_lock); ++ } +++ +++ /* Get rid of the fixup trampoline if we're running the module +++ * from physically mapped address space */ +++ if (me->arch.phys_plt_offset == 0) { +++ __module_free(me->arch.phys_plt_tbl); +++ me->arch.phys_plt_tbl = NULL; +++ } +++ if (me->arch.virt_plt_offset == 0) { +++ __module_free(me->arch.virt_plt_tbl); +++ me->arch.virt_plt_tbl = NULL; +++ } +++ ++ return 0; ++ } ++ +++void module_arch_freeing_init(struct module *mod) +++{ +++ if (mod->state == MODULE_STATE_LIVE) +++ return; +++ +++ if (mod->arch.phys_plt_tbl) { +++ __module_free(mod->arch.phys_plt_tbl); +++ mod->arch.phys_plt_tbl = NULL; +++ } +++ if (mod->arch.virt_plt_tbl) { +++ __module_free(mod->arch.virt_plt_tbl); +++ mod->arch.virt_plt_tbl = NULL; +++ } +++} +++ ++ void module_arch_cleanup(struct module *mod) ++ { ++ spin_lock_irq(&dbe_lock); +diff --git a/target/linux/generic/pending-4.14/306-mips_mem_functions_performance.patch b/target/linux/generic/pending-4.14/306-mips_mem_functions_performance.patch +new file mode 100644 +index 0000000000..e73cfd61b3 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/306-mips_mem_functions_performance.patch +@@ -0,0 +1,106 @@ ++From: Felix Fietkau ++Subject: [PATCH] mips: allow the compiler to optimize memset, memcmp, memcpy for better performance and (in some instances) smaller code ++ ++lede-commit: 07e59c7bc7f375f792ec9734be42fe4fa391a8bb ++Signed-off-by: Felix Fietkau ++--- ++ arch/mips/boot/compressed/Makefile | 3 ++- ++ arch/mips/include/asm/string.h | 38 ++++++++++++++++++++++++++++++++++++++ ++ arch/mips/lib/Makefile | 2 +- ++ arch/mips/lib/memcmp.c | 22 ++++++++++++++++++++++ ++ 4 files changed, 63 insertions(+), 2 deletions(-) ++ create mode 100644 arch/mips/lib/memcmp.c ++ ++--- a/arch/mips/boot/compressed/Makefile +++++ b/arch/mips/boot/compressed/Makefile ++@@ -23,7 +23,8 @@ KBUILD_CFLAGS := $(filter-out -pg, $(KBU ++ KBUILD_CFLAGS := $(filter-out -fstack-protector, $(KBUILD_CFLAGS)) ++ ++ KBUILD_CFLAGS := $(KBUILD_CFLAGS) -D__KERNEL__ \ ++- -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" +++ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" \ +++ -D__ZBOOT__ ++ ++ KBUILD_AFLAGS := $(KBUILD_AFLAGS) -D__ASSEMBLY__ \ ++ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \ ++--- a/arch/mips/include/asm/string.h +++++ b/arch/mips/include/asm/string.h ++@@ -140,4 +140,42 @@ extern void *memcpy(void *__to, __const_ ++ #define __HAVE_ARCH_MEMMOVE ++ extern void *memmove(void *__dest, __const__ void *__src, size_t __n); ++ +++#ifndef __ZBOOT__ +++#define memset(__s, __c, len) \ +++({ \ +++ size_t __len = (len); \ +++ void *__ret; \ +++ if (__builtin_constant_p(len) && __len >= 64) \ +++ __ret = memset((__s), (__c), __len); \ +++ else \ +++ __ret = __builtin_memset((__s), (__c), __len); \ +++ __ret; \ +++}) +++ +++#define memcpy(dst, src, len) \ +++({ \ +++ size_t __len = (len); \ +++ void *__ret; \ +++ if (__builtin_constant_p(len) && __len >= 64) \ +++ __ret = memcpy((dst), (src), __len); \ +++ else \ +++ __ret = __builtin_memcpy((dst), (src), __len); \ +++ __ret; \ +++}) +++ +++#define memmove(dst, src, len) \ +++({ \ +++ size_t __len = (len); \ +++ void *__ret; \ +++ if (__builtin_constant_p(len) && __len >= 64) \ +++ __ret = memmove((dst), (src), __len); \ +++ else \ +++ __ret = __builtin_memmove((dst), (src), __len); \ +++ __ret; \ +++}) +++ +++#define __HAVE_ARCH_MEMCMP +++#define memcmp(src1, src2, len) __builtin_memcmp((src1), (src2), (len)) +++#endif +++ ++ #endif /* _ASM_STRING_H */ ++--- a/arch/mips/lib/Makefile +++++ b/arch/mips/lib/Makefile ++@@ -5,7 +5,7 @@ ++ ++ lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \ ++ mips-atomic.o strncpy_user.o \ ++- strnlen_user.o uncached.o +++ strnlen_user.o uncached.o memcmp.o ++ ++ obj-y += iomap.o iomap_copy.o ++ obj-$(CONFIG_PCI) += iomap-pci.o ++--- /dev/null +++++ b/arch/mips/lib/memcmp.c ++@@ -0,0 +1,22 @@ +++/* +++ * copied from linux/lib/string.c +++ * +++ * Copyright (C) 1991, 1992 Linus Torvalds +++ */ +++ +++#include +++#include +++ +++#undef memcmp +++int memcmp(const void *cs, const void *ct, size_t count) +++{ +++ const unsigned char *su1, *su2; +++ int res = 0; +++ +++ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) +++ if ((res = *su1 - *su2) != 0) +++ break; +++ return res; +++} +++EXPORT_SYMBOL(memcmp); +++ +diff --git a/target/linux/generic/pending-4.14/307-mips_highmem_offset.patch b/target/linux/generic/pending-4.14/307-mips_highmem_offset.patch +new file mode 100644 +index 0000000000..0529b0c5c8 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/307-mips_highmem_offset.patch +@@ -0,0 +1,19 @@ ++From: Felix Fietkau ++Subject: kernel: adjust mips highmem offset to avoid the need for -mlong-calls on systems with >256M RAM ++ ++Signed-off-by: Felix Fietkau ++--- ++ arch/mips/include/asm/mach-generic/spaces.h | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/arch/mips/include/asm/mach-generic/spaces.h +++++ b/arch/mips/include/asm/mach-generic/spaces.h ++@@ -46,7 +46,7 @@ ++ * Memory above this physical address will be considered highmem. ++ */ ++ #ifndef HIGHMEM_START ++-#define HIGHMEM_START _AC(0x20000000, UL) +++#define HIGHMEM_START _AC(0x10000000, UL) ++ #endif ++ ++ #endif /* CONFIG_32BIT */ +diff --git a/target/linux/generic/pending-4.14/308-mips32r2_tune.patch b/target/linux/generic/pending-4.14/308-mips32r2_tune.patch +new file mode 100644 +index 0000000000..a67306031c +--- /dev/null ++++ b/target/linux/generic/pending-4.14/308-mips32r2_tune.patch +@@ -0,0 +1,22 @@ ++From: Felix Fietkau ++Subject: kernel: add -mtune=34kc to MIPS CFLAGS when building for mips32r2 ++ ++This provides a good tradeoff across at least 24Kc-74Kc, while also ++producing smaller code. ++ ++Signed-off-by: Felix Fietkau ++--- ++ arch/mips/Makefile | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/arch/mips/Makefile +++++ b/arch/mips/Makefile ++@@ -166,7 +166,7 @@ cflags-$(CONFIG_CPU_VR41XX) += -march=r4 ++ cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap ++ cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap ++ cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap ++-cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,--trap +++cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -mtune=34kc -Wa,--trap ++ cflags-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,--trap -modd-spreg ++ cflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,--trap ++ cflags-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,--trap +diff --git a/target/linux/generic/pending-4.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch b/target/linux/generic/pending-4.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch +new file mode 100644 +index 0000000000..954830509c +--- /dev/null ++++ b/target/linux/generic/pending-4.14/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch +@@ -0,0 +1,140 @@ ++From 87ec87c2ad615c1a177cd08ef5fa29fc739f6e50 Mon Sep 17 00:00:00 2001 ++From: Hauke Mehrtens ++Date: Sun, 23 Dec 2018 18:06:53 +0100 ++Subject: [PATCH] MIPS: Add CPU option reporting to /proc/cpuinfo ++ ++Many MIPS CPUs have optional CPU features which are not activates for ++all CPU cores. Print the CPU options which are implemented in the core ++in /proc/cpuinfo. This makes it possible to see what features are ++supported and which are not supported. This should cover all standard ++MIPS extensions, before it only printed information about the main MIPS ++ASEs. ++ ++Signed-off-by: Hauke Mehrtens ++--- ++ arch/mips/kernel/proc.c | 116 ++++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 116 insertions(+) ++ ++--- a/arch/mips/kernel/proc.c +++++ b/arch/mips/kernel/proc.c ++@@ -130,6 +130,120 @@ static int show_cpuinfo(struct seq_file ++ seq_printf(m, "micromips kernel\t: %s\n", ++ (read_c0_config3() & MIPS_CONF3_ISA_OE) ? "yes" : "no"); ++ } +++ +++ seq_printf(m, "Options implemented\t:"); +++ if (cpu_has_tlb) +++ seq_printf(m, "%s", " tlb"); +++ if (cpu_has_ftlb) +++ seq_printf(m, "%s", " ftlb"); +++ if (cpu_has_tlbinv) +++ seq_printf(m, "%s", " tlbinv"); +++ if (cpu_has_segments) +++ seq_printf(m, "%s", " segments"); +++ if (cpu_has_rixiex) +++ seq_printf(m, "%s", " rixiex"); +++ if (cpu_has_ldpte) +++ seq_printf(m, "%s", " ldpte"); +++ if (cpu_has_maar) +++ seq_printf(m, "%s", " maar"); +++ if (cpu_has_rw_llb) +++ seq_printf(m, "%s", " rw_llb"); +++ if (cpu_has_4kex) +++ seq_printf(m, "%s", " 4kex"); +++ if (cpu_has_3k_cache) +++ seq_printf(m, "%s", " 3k_cache"); +++ if (cpu_has_4k_cache) +++ seq_printf(m, "%s", " 4k_cache"); +++ if (cpu_has_6k_cache) +++ seq_printf(m, "%s", " 6k_cache"); +++ if (cpu_has_8k_cache) +++ seq_printf(m, "%s", " 8k_cache"); +++ if (cpu_has_tx39_cache) +++ seq_printf(m, "%s", " tx39_cache"); +++ if (cpu_has_octeon_cache) +++ seq_printf(m, "%s", " octeon_cache"); +++ if (cpu_has_fpu) +++ seq_printf(m, "%s", " fpu"); +++ if (cpu_has_32fpr) +++ seq_printf(m, "%s", " 32fpr"); +++ if (cpu_has_cache_cdex_p) +++ seq_printf(m, "%s", " cache_cdex_p"); +++ if (cpu_has_cache_cdex_s) +++ seq_printf(m, "%s", " cache_cdex_s"); +++ if (cpu_has_prefetch) +++ seq_printf(m, "%s", " prefetch"); +++ if (cpu_has_mcheck) +++ seq_printf(m, "%s", " mcheck"); +++ if (cpu_has_ejtag) +++ seq_printf(m, "%s", " ejtag"); +++ if (cpu_has_llsc) +++ seq_printf(m, "%s", " llsc"); +++ if (cpu_has_bp_ghist) +++ seq_printf(m, "%s", " bp_ghist"); +++ if (cpu_has_guestctl0ext) +++ seq_printf(m, "%s", " guestctl0ext"); +++ if (cpu_has_guestctl1) +++ seq_printf(m, "%s", " guestctl1"); +++ if (cpu_has_guestctl2) +++ seq_printf(m, "%s", " guestctl2"); +++ if (cpu_has_guestid) +++ seq_printf(m, "%s", " guestid"); +++ if (cpu_has_drg) +++ seq_printf(m, "%s", " drg"); +++ if (cpu_has_rixi) +++ seq_printf(m, "%s", " rixi"); +++ if (cpu_has_lpa) +++ seq_printf(m, "%s", " lpa"); +++ if (cpu_has_mvh) +++ seq_printf(m, "%s", " mvh"); +++ if (cpu_has_vtag_icache) +++ seq_printf(m, "%s", " vtag_icache"); +++ if (cpu_has_dc_aliases) +++ seq_printf(m, "%s", " dc_aliases"); +++ if (cpu_has_ic_fills_f_dc) +++ seq_printf(m, "%s", " ic_fills_f_dc"); +++ if (cpu_has_pindexed_dcache) +++ seq_printf(m, "%s", " pindexed_dcache"); +++ if (cpu_has_userlocal) +++ seq_printf(m, "%s", " userlocal"); +++ if (cpu_has_nofpuex) +++ seq_printf(m, "%s", " nofpuex"); +++ if (cpu_has_vint) +++ seq_printf(m, "%s", " vint"); +++ if (cpu_has_veic) +++ seq_printf(m, "%s", " veic"); +++ if (cpu_has_inclusive_pcaches) +++ seq_printf(m, "%s", " inclusive_pcaches"); +++ if (cpu_has_perf_cntr_intr_bit) +++ seq_printf(m, "%s", " perf_cntr_intr_bit"); +++ if (cpu_has_ufr) +++ seq_printf(m, "%s", " ufr"); +++ if (cpu_has_fre) +++ seq_printf(m, "%s", " fre"); +++ if (cpu_has_cdmm) +++ seq_printf(m, "%s", " cdmm"); +++ if (cpu_has_small_pages) +++ seq_printf(m, "%s", " small_pages"); +++ if (cpu_has_nan_legacy) +++ seq_printf(m, "%s", " nan_legacy"); +++ if (cpu_has_nan_2008) +++ seq_printf(m, "%s", " nan_2008"); +++ if (cpu_has_ebase_wg) +++ seq_printf(m, "%s", " ebase_wg"); +++ if (cpu_has_badinstr) +++ seq_printf(m, "%s", " badinstr"); +++ if (cpu_has_badinstrp) +++ seq_printf(m, "%s", " badinstrp"); +++ if (cpu_has_contextconfig) +++ seq_printf(m, "%s", " contextconfig"); +++ if (cpu_has_perf) +++ seq_printf(m, "%s", " perf"); +++ if (cpu_has_shared_ftlb_ram) +++ seq_printf(m, "%s", " shared_ftlb_ram"); +++ if (cpu_has_shared_ftlb_entries) +++ seq_printf(m, "%s", " shared_ftlb_entries"); +++ seq_printf(m, "\n"); +++ ++ seq_printf(m, "shadow register sets\t: %d\n", ++ cpu_data[n].srsets); ++ seq_printf(m, "kscratch registers\t: %d\n", +diff --git a/target/linux/generic/pending-4.14/310-arm_module_unresolved_weak_sym.patch b/target/linux/generic/pending-4.14/310-arm_module_unresolved_weak_sym.patch +new file mode 100644 +index 0000000000..bc9f0a4c4d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/310-arm_module_unresolved_weak_sym.patch +@@ -0,0 +1,22 @@ ++From: Felix Fietkau ++Subject: fix errors in unresolved weak symbols on arm ++ ++lede-commit: 570699d4838a907c3ef9f2819bf19eb72997b32f ++Signed-off-by: Felix Fietkau ++--- ++ arch/arm/kernel/module.c | 4 ++++ ++ 1 file changed, 4 insertions(+) ++ ++--- a/arch/arm/kernel/module.c +++++ b/arch/arm/kernel/module.c ++@@ -95,6 +95,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons ++ return -ENOEXEC; ++ } ++ +++ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) && +++ ELF_ST_BIND(sym->st_info) == STB_WEAK) +++ continue; +++ ++ loc = dstsec->sh_addr + rel->r_offset; ++ ++ switch (ELF32_R_TYPE(rel->r_info)) { +diff --git a/target/linux/generic/pending-4.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/target/linux/generic/pending-4.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch +new file mode 100644 +index 0000000000..44d85b5b86 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch +@@ -0,0 +1,274 @@ ++From: Yousong Zhou ++Subject: MIPS: kexec: Accept command line parameters from userspace. ++ ++Signed-off-by: Yousong Zhou ++--- ++ arch/mips/kernel/machine_kexec.c | 153 +++++++++++++++++++++++++++++++----- ++ arch/mips/kernel/machine_kexec.h | 20 +++++ ++ arch/mips/kernel/relocate_kernel.S | 21 +++-- ++ 3 files changed, 167 insertions(+), 27 deletions(-) ++ create mode 100644 arch/mips/kernel/machine_kexec.h ++ ++--- a/arch/mips/kernel/machine_kexec.c +++++ b/arch/mips/kernel/machine_kexec.c ++@@ -10,14 +10,11 @@ ++ #include ++ #include ++ +++#include ++ #include ++ #include ++- ++-extern const unsigned char relocate_new_kernel[]; ++-extern const size_t relocate_new_kernel_size; ++- ++-extern unsigned long kexec_start_address; ++-extern unsigned long kexec_indirection_page; +++#include +++#include "machine_kexec.h" ++ ++ int (*_machine_kexec_prepare)(struct kimage *) = NULL; ++ void (*_machine_kexec_shutdown)(void) = NULL; ++@@ -28,6 +25,101 @@ atomic_t kexec_ready_to_reboot = ATOMIC_ ++ void (*_crash_smp_send_stop)(void) = NULL; ++ #endif ++ +++static void machine_kexec_print_args(void) +++{ +++ unsigned long argc = (int)kexec_args[0]; +++ int i; +++ +++ pr_info("kexec_args[0] (argc): %lu\n", argc); +++ pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]); +++ pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]); +++ pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]); +++ +++ for (i = 0; i < argc; i++) { +++ pr_info("kexec_argv[%d] = %p, %s\n", +++ i, kexec_argv[i], kexec_argv[i]); +++ } +++} +++ +++static void machine_kexec_init_argv(struct kimage *image) +++{ +++ void __user *buf = NULL; +++ size_t bufsz; +++ size_t size; +++ int i; +++ +++ bufsz = 0; +++ for (i = 0; i < image->nr_segments; i++) { +++ struct kexec_segment *seg; +++ +++ seg = &image->segment[i]; +++ if (seg->bufsz < 6) +++ continue; +++ +++ if (strncmp((char *) seg->buf, "kexec ", 6)) +++ continue; +++ +++ buf = seg->buf; +++ bufsz = seg->bufsz; +++ break; +++ } +++ +++ if (!buf) +++ return; +++ +++ size = KEXEC_COMMAND_LINE_SIZE; +++ size = min(size, bufsz); +++ if (size < bufsz) +++ pr_warn("kexec command line truncated to %zd bytes\n", size); +++ +++ /* Copy to kernel space */ +++ if (copy_from_user(kexec_argv_buf, buf, size)) +++ pr_warn("kexec command line copy to kernel space failed\n"); +++ +++ kexec_argv_buf[size - 1] = 0; +++} +++ +++static void machine_kexec_parse_argv(struct kimage *image) +++{ +++ char *reboot_code_buffer; +++ int reloc_delta; +++ char *ptr; +++ int argc; +++ int i; +++ +++ ptr = kexec_argv_buf; +++ argc = 0; +++ +++ /* +++ * convert command line string to array of parameters +++ * (as bootloader does). +++ */ +++ while (ptr && *ptr && (KEXEC_MAX_ARGC > argc)) { +++ if (*ptr == ' ') { +++ *ptr++ = '\0'; +++ continue; +++ } +++ +++ kexec_argv[argc++] = ptr; +++ ptr = strchr(ptr, ' '); +++ } +++ +++ if (!argc) +++ return; +++ +++ kexec_args[0] = argc; +++ kexec_args[1] = (unsigned long)kexec_argv; +++ kexec_args[2] = 0; +++ kexec_args[3] = 0; +++ +++ reboot_code_buffer = page_address(image->control_code_page); +++ reloc_delta = reboot_code_buffer - (char *)kexec_relocate_new_kernel; +++ +++ kexec_args[1] += reloc_delta; +++ for (i = 0; i < argc; i++) +++ kexec_argv[i] += reloc_delta; +++} +++ ++ static void kexec_image_info(const struct kimage *kimage) ++ { ++ unsigned long i; ++@@ -52,6 +144,18 @@ int ++ machine_kexec_prepare(struct kimage *kimage) ++ { ++ kexec_image_info(kimage); +++ /* +++ * Whenever arguments passed from kexec-tools, Init the arguments as +++ * the original ones to try avoiding booting failure. +++ */ +++ +++ kexec_args[0] = fw_arg0; +++ kexec_args[1] = fw_arg1; +++ kexec_args[2] = fw_arg2; +++ kexec_args[3] = fw_arg3; +++ +++ machine_kexec_init_argv(kimage); +++ machine_kexec_parse_argv(kimage); ++ ++ if (_machine_kexec_prepare) ++ return _machine_kexec_prepare(kimage); ++@@ -89,10 +193,12 @@ machine_kexec(struct kimage *image) ++ unsigned long *ptr; ++ ++ reboot_code_buffer = ++- (unsigned long)page_address(image->control_code_page); +++ (unsigned long)page_address(image->control_code_page); +++ pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer); ++ ++ kexec_start_address = ++ (unsigned long) phys_to_virt(image->start); +++ pr_info("kexec_start_address = %p\n", (void *)kexec_start_address); ++ ++ if (image->type == KEXEC_TYPE_DEFAULT) { ++ kexec_indirection_page = ++@@ -100,9 +206,19 @@ machine_kexec(struct kimage *image) ++ } else { ++ kexec_indirection_page = (unsigned long)&image->head; ++ } +++ pr_info("kexec_indirection_page = %p\n", (void *)kexec_indirection_page); ++ ++- memcpy((void*)reboot_code_buffer, relocate_new_kernel, ++- relocate_new_kernel_size); +++ pr_info("Where is memcpy: %p\n", memcpy); +++ pr_info("kexec_relocate_new_kernel = %p, kexec_relocate_new_kernel_end = %p\n", +++ (void *)kexec_relocate_new_kernel, &kexec_relocate_new_kernel_end); +++ pr_info("Copy %lu bytes from %p to %p\n", KEXEC_RELOCATE_NEW_KERNEL_SIZE, +++ (void *)kexec_relocate_new_kernel, (void *)reboot_code_buffer); +++ memcpy((void*)reboot_code_buffer, kexec_relocate_new_kernel, +++ KEXEC_RELOCATE_NEW_KERNEL_SIZE); +++ +++ pr_info("Before _print_args().\n"); +++ machine_kexec_print_args(); +++ pr_info("Before eval loop.\n"); ++ ++ /* ++ * The generic kexec code builds a page list with physical ++@@ -124,15 +240,16 @@ machine_kexec(struct kimage *image) ++ /* ++ * we do not want to be bothered. ++ */ +++ pr_info("Before irq_disable.\n"); ++ local_irq_disable(); ++ ++- printk("Will call new kernel at %08lx\n", image->start); ++- printk("Bye ...\n"); +++ pr_info("Will call new kernel at %08lx\n", image->start); +++ pr_info("Bye ...\n"); ++ __flush_cache_all(); ++ #ifdef CONFIG_SMP ++ /* All secondary cpus now may jump to kexec_wait cycle */ ++ relocated_kexec_smp_wait = reboot_code_buffer + ++- (void *)(kexec_smp_wait - relocate_new_kernel); +++ (void *)(kexec_smp_wait - kexec_relocate_new_kernel); ++ smp_wmb(); ++ atomic_set(&kexec_ready_to_reboot, 1); ++ #endif ++--- /dev/null +++++ b/arch/mips/kernel/machine_kexec.h ++@@ -0,0 +1,20 @@ +++#ifndef _MACHINE_KEXEC_H +++#define _MACHINE_KEXEC_H +++ +++#ifndef __ASSEMBLY__ +++extern const unsigned char kexec_relocate_new_kernel[]; +++extern unsigned long kexec_relocate_new_kernel_end; +++extern unsigned long kexec_start_address; +++extern unsigned long kexec_indirection_page; +++ +++extern char kexec_argv_buf[]; +++extern char *kexec_argv[]; +++ +++#define KEXEC_RELOCATE_NEW_KERNEL_SIZE ((unsigned long)&kexec_relocate_new_kernel_end - (unsigned long)kexec_relocate_new_kernel) +++#endif /* !__ASSEMBLY__ */ +++ +++#define KEXEC_COMMAND_LINE_SIZE 256 +++#define KEXEC_ARGV_SIZE (KEXEC_COMMAND_LINE_SIZE / 16) +++#define KEXEC_MAX_ARGC (KEXEC_ARGV_SIZE / sizeof(long)) +++ +++#endif ++--- a/arch/mips/kernel/relocate_kernel.S +++++ b/arch/mips/kernel/relocate_kernel.S ++@@ -12,8 +12,9 @@ ++ #include ++ #include ++ #include +++#include "machine_kexec.h" ++ ++-LEAF(relocate_new_kernel) +++LEAF(kexec_relocate_new_kernel) ++ PTR_L a0, arg0 ++ PTR_L a1, arg1 ++ PTR_L a2, arg2 ++@@ -98,7 +99,7 @@ done: ++ #endif ++ /* jump to kexec_start_address */ ++ j s1 ++- END(relocate_new_kernel) +++ END(kexec_relocate_new_kernel) ++ ++ #ifdef CONFIG_SMP ++ /* ++@@ -184,9 +185,15 @@ kexec_indirection_page: ++ PTR 0 ++ .size kexec_indirection_page, PTRSIZE ++ ++-relocate_new_kernel_end: +++kexec_argv_buf: +++ EXPORT(kexec_argv_buf) +++ .skip KEXEC_COMMAND_LINE_SIZE +++ .size kexec_argv_buf, KEXEC_COMMAND_LINE_SIZE +++ +++kexec_argv: +++ EXPORT(kexec_argv) +++ .skip KEXEC_ARGV_SIZE +++ .size kexec_argv, KEXEC_ARGV_SIZE ++ ++-relocate_new_kernel_size: ++- EXPORT(relocate_new_kernel_size) ++- PTR relocate_new_kernel_end - relocate_new_kernel ++- .size relocate_new_kernel_size, PTRSIZE +++kexec_relocate_new_kernel_end: +++ EXPORT(kexec_relocate_new_kernel_end) +diff --git a/target/linux/generic/pending-4.14/332-arc-add-OWRTDTB-section.patch b/target/linux/generic/pending-4.14/332-arc-add-OWRTDTB-section.patch +new file mode 100644 +index 0000000000..1b75bf2a06 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/332-arc-add-OWRTDTB-section.patch +@@ -0,0 +1,84 @@ ++From 34ef04f3845ed2b47d57dd9d3b795b16e1f8185a Mon Sep 17 00:00:00 2001 ++From: Evgeniy Didin ++Date: Fri, 15 Mar 2019 18:53:38 +0300 ++Subject: [PATCH] arc add OWRTDTB section ++ ++This change allows OpenWRT to patch resulting kernel binary with ++external .dtb. ++ ++That allows us to re-use exactky the same vmlinux on different boards ++given its ARC core configurations match (at least cache line sizes etc). ++ ++""patch-dtb" searches for ASCII "OWRTDTB:" strign and copies external ++.dtb right after it, keeping the string in place. ++ ++Signed-off-by: Eugeniy Paltsev ++Signed-off-by: Alexey Brodkin ++Signed-off-by: Evgeniy Didin ++--- ++ arch/arc/kernel/head.S | 10 ++++++++++ ++ arch/arc/kernel/setup.c | 4 +++- ++ arch/arc/kernel/vmlinux.lds.S | 13 +++++++++++++ ++ 3 files changed, 26 insertions(+), 1 deletion(-) ++ ++--- a/arch/arc/kernel/head.S +++++ b/arch/arc/kernel/head.S ++@@ -59,6 +59,16 @@ ++ #endif ++ .endm ++ +++ ; Here "patch-dtb" will embed external .dtb +++ ; Note "patch-dtb" searches for ASCII "OWRTDTB:" string +++ ; and pastes .dtb right after it, hense the string precedes +++ ; __image_dtb symbol. +++ .section .owrt, "aw",@progbits +++ .ascii "OWRTDTB:" +++ENTRY(__image_dtb) +++ .fill 0x4000 +++END(__image_dtb) +++ ++ .section .init.text, "ax",@progbits ++ ++ ;---------------------------------------------------------------- ++--- a/arch/arc/kernel/setup.c +++++ b/arch/arc/kernel/setup.c ++@@ -438,6 +438,8 @@ static inline bool uboot_arg_invalid(uns ++ /* We always pass 0 as magic from U-boot */ ++ #define UBOOT_MAGIC_VALUE 0 ++ +++extern struct boot_param_header __image_dtb; +++ ++ void __init handle_uboot_args(void) ++ { ++ bool use_embedded_dtb = true; ++@@ -478,7 +480,7 @@ ignore_uboot_args: ++ #endif ++ ++ if (use_embedded_dtb) { ++- machine_desc = setup_machine_fdt(__dtb_start); +++ machine_desc = setup_machine_fdt(&__image_dtb); ++ if (!machine_desc) ++ panic("Embedded DT invalid\n"); ++ } ++--- a/arch/arc/kernel/vmlinux.lds.S +++++ b/arch/arc/kernel/vmlinux.lds.S ++@@ -29,6 +29,19 @@ SECTIONS ++ */ ++ ++ . = CONFIG_LINUX_LINK_BASE; +++ /* +++ * In OpenWRT we want to patch built binary embedding .dtb of choice. +++ * This is implemented with "patch-dtb" utility which searches for +++ * "OWRTDTB:" string in first 16k of image and if it is found +++ * copies .dtb right after mentioned string. +++ * +++ * Note: "OWRTDTB:" won't be overwritten with .dtb, .dtb will follow it. +++ */ +++ .owrt : { +++ *(.owrt) +++ . = ALIGN(PAGE_SIZE); +++ } +++ ++ ++ _int_vec_base_lds = .; ++ .vector : { +diff --git a/target/linux/generic/pending-4.14/333-arc-enable-unaligned-access-in-kernel-mode.patch b/target/linux/generic/pending-4.14/333-arc-enable-unaligned-access-in-kernel-mode.patch +new file mode 100644 +index 0000000000..4e0265aef5 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/333-arc-enable-unaligned-access-in-kernel-mode.patch +@@ -0,0 +1,24 @@ ++From: Alexey Brodkin ++Subject: arc: enable unaligned access in kernel mode ++ ++This enables misaligned access handling even in kernel mode. ++Some wireless drivers (ath9k-htc and mt7601u) use misaligned accesses ++here and there and to cope with that without fixing stuff in the drivers ++we're just gracefully handling it on ARC. ++ ++Signed-off-by: Alexey Brodkin ++--- ++ arch/arc/kernel/unaligned.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/arch/arc/kernel/unaligned.c +++++ b/arch/arc/kernel/unaligned.c ++@@ -206,7 +206,7 @@ int misaligned_fixup(unsigned long addre ++ char buf[TASK_COMM_LEN]; ++ ++ /* handle user mode only and only if enabled by sysadmin */ ++- if (!user_mode(regs) || !unaligned_enabled) +++ if (!unaligned_enabled) ++ return 1; ++ ++ if (no_unaligned_warning) { +diff --git a/target/linux/generic/pending-4.14/340-MIPS-mm-remove-mips_dma_mapping_error.patch b/target/linux/generic/pending-4.14/340-MIPS-mm-remove-mips_dma_mapping_error.patch +new file mode 100644 +index 0000000000..8d6cada842 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/340-MIPS-mm-remove-mips_dma_mapping_error.patch +@@ -0,0 +1,32 @@ ++From: Felix Fietkau ++Date: Tue, 5 Dec 2017 12:34:31 +0100 ++Subject: [PATCH] MIPS: mm: remove mips_dma_mapping_error ++ ++dma_mapping_error() already checks if ops->mapping_error is a null ++pointer ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/arch/mips/mm/dma-default.c +++++ b/arch/mips/mm/dma-default.c ++@@ -373,11 +373,6 @@ static void mips_dma_sync_sg_for_device( ++ } ++ } ++ ++-static int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) ++-{ ++- return 0; ++-} ++- ++ static int mips_dma_supported(struct device *dev, u64 mask) ++ { ++ return plat_dma_supported(dev, mask); ++@@ -406,7 +401,6 @@ static const struct dma_map_ops mips_def ++ .sync_single_for_device = mips_dma_sync_single_for_device, ++ .sync_sg_for_cpu = mips_dma_sync_sg_for_cpu, ++ .sync_sg_for_device = mips_dma_sync_sg_for_device, ++- .mapping_error = mips_dma_mapping_error, ++ .dma_supported = mips_dma_supported ++ }; ++ +diff --git a/target/linux/generic/pending-4.14/341-MIPS-mm-remove-no-op-dma_map_ops-where-possible.patch b/target/linux/generic/pending-4.14/341-MIPS-mm-remove-no-op-dma_map_ops-where-possible.patch +new file mode 100644 +index 0000000000..6f5f11350a +--- /dev/null ++++ b/target/linux/generic/pending-4.14/341-MIPS-mm-remove-no-op-dma_map_ops-where-possible.patch +@@ -0,0 +1,140 @@ ++From: Felix Fietkau ++Date: Tue, 5 Dec 2017 12:46:01 +0100 ++Subject: [PATCH] MIPS: mm: remove no-op dma_map_ops where possible ++ ++If no post-DMA flush is required, and the platform does not provide ++plat_unmap_dma_mem(), there is no need to include unmap or sync_for_cpu ++ops. ++ ++With this patch they are compiled out to improve icache footprint ++on devices that handle lots of DMA traffic (especially network routers). ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/arch/mips/Kconfig +++++ b/arch/mips/Kconfig ++@@ -221,6 +221,7 @@ config BMIPS_GENERIC ++ select BRCMSTB_L2_IRQ ++ select IRQ_MIPS_CPU ++ select DMA_NONCOHERENT +++ select DMA_UNMAP_POST_FLUSH ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_LITTLE_ENDIAN ++ select SYS_SUPPORTS_BIG_ENDIAN ++@@ -346,6 +347,7 @@ config MACH_JAZZ ++ select CSRC_R4K ++ select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN ++ select GENERIC_ISA_DMA +++ select DMA_UNMAP_POST_FLUSH ++ select HAVE_PCSPKR_PLATFORM ++ select IRQ_MIPS_CPU ++ select I8253 ++@@ -1129,6 +1131,9 @@ config DMA_NONCOHERENT ++ bool ++ select NEED_DMA_MAP_STATE ++ +++config DMA_UNMAP_POST_FLUSH +++ bool +++ ++ config NEED_DMA_MAP_STATE ++ bool ++ ++@@ -1653,6 +1658,7 @@ config CPU_R10000 ++ select CPU_SUPPORTS_64BIT_KERNEL ++ select CPU_SUPPORTS_HIGHMEM ++ select CPU_SUPPORTS_HUGEPAGES +++ select DMA_UNMAP_POST_FLUSH ++ help ++ MIPS Technologies R10000-series processors. ++ ++@@ -1901,9 +1907,11 @@ config SYS_HAS_CPU_MIPS32_R3_5 ++ bool ++ ++ config SYS_HAS_CPU_MIPS32_R5 +++ select DMA_UNMAP_POST_FLUSH ++ bool ++ ++ config SYS_HAS_CPU_MIPS32_R6 +++ select DMA_UNMAP_POST_FLUSH ++ bool ++ ++ config SYS_HAS_CPU_MIPS64_R1 ++@@ -1913,6 +1921,7 @@ config SYS_HAS_CPU_MIPS64_R2 ++ bool ++ ++ config SYS_HAS_CPU_MIPS64_R6 +++ select DMA_UNMAP_POST_FLUSH ++ bool ++ ++ config SYS_HAS_CPU_R3000 ++--- a/arch/mips/mm/dma-default.c +++++ b/arch/mips/mm/dma-default.c ++@@ -267,8 +267,9 @@ static inline void __dma_sync(struct pag ++ } while (left); ++ } ++ ++-static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, ++- size_t size, enum dma_data_direction direction, unsigned long attrs) +++static void __maybe_unused +++mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, +++ enum dma_data_direction direction, unsigned long attrs) ++ { ++ if (cpu_needs_post_dma_flush(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) ++ __dma_sync(dma_addr_to_page(dev, dma_addr), ++@@ -308,9 +309,10 @@ static dma_addr_t mips_dma_map_page(stru ++ return plat_map_dma_mem_page(dev, page) + offset; ++ } ++ ++-static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, ++- int nhwentries, enum dma_data_direction direction, ++- unsigned long attrs) +++static void __maybe_unused +++mips_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, +++ int nhwentries, enum dma_data_direction direction, +++ unsigned long attrs) ++ { ++ int i; ++ struct scatterlist *sg; ++@@ -325,8 +327,9 @@ static void mips_dma_unmap_sg(struct dev ++ } ++ } ++ ++-static void mips_dma_sync_single_for_cpu(struct device *dev, ++- dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) +++static void __maybe_unused +++mips_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, +++ size_t size, enum dma_data_direction direction) ++ { ++ if (cpu_needs_post_dma_flush(dev)) ++ __dma_sync(dma_addr_to_page(dev, dma_handle), ++@@ -342,9 +345,9 @@ static void mips_dma_sync_single_for_dev ++ dma_handle & ~PAGE_MASK, size, direction); ++ } ++ ++-static void mips_dma_sync_sg_for_cpu(struct device *dev, ++- struct scatterlist *sglist, int nelems, ++- enum dma_data_direction direction) +++static void __maybe_unused +++mips_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, +++ int nelems, enum dma_data_direction direction) ++ { ++ int i; ++ struct scatterlist *sg; ++@@ -394,12 +397,14 @@ static const struct dma_map_ops mips_def ++ .free = mips_dma_free_coherent, ++ .mmap = mips_dma_mmap, ++ .map_page = mips_dma_map_page, ++- .unmap_page = mips_dma_unmap_page, ++ .map_sg = mips_dma_map_sg, +++#ifdef CONFIG_DMA_UNMAP_POST_FLUSH +++ .unmap_page = mips_dma_unmap_page, ++ .unmap_sg = mips_dma_unmap_sg, ++ .sync_single_for_cpu = mips_dma_sync_single_for_cpu, ++- .sync_single_for_device = mips_dma_sync_single_for_device, ++ .sync_sg_for_cpu = mips_dma_sync_sg_for_cpu, +++#endif +++ .sync_single_for_device = mips_dma_sync_single_for_device, ++ .sync_sg_for_device = mips_dma_sync_sg_for_device, ++ .dma_supported = mips_dma_supported ++ }; +diff --git a/target/linux/generic/pending-4.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch b/target/linux/generic/pending-4.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch +new file mode 100644 +index 0000000000..e3ae02a067 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch +@@ -0,0 +1,24 @@ ++From 8cabf9d8bd67d3f8603a4c1ceedaa629a7212be8 Mon Sep 17 00:00:00 2001 ++From: Pawel Dembicki ++Date: Fri, 24 May 2019 17:56:19 +0200 ++Subject: [PATCH] powerpc: Enable kernel XZ compression option on PPC_85xx ++ ++Enable kernel XZ compression option on PPC_85xx. Tested with ++simpleImage on TP-Link TL-WDR4900 (Freescale P1014 processor). ++ ++Suggested-by: Christian Lamparter ++Signed-off-by: Pawel Dembicki ++--- ++ arch/powerpc/Kconfig | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/arch/powerpc/Kconfig +++++ b/arch/powerpc/Kconfig ++@@ -199,6 +199,7 @@ config PPC ++ select HAVE_IOREMAP_PROT ++ select HAVE_IRQ_EXIT_ON_IRQ_STACK ++ select HAVE_KERNEL_GZIP +++ select HAVE_KERNEL_XZ if PPC_85xx ++ select HAVE_KPROBES ++ select HAVE_KPROBES_ON_FTRACE ++ select HAVE_KRETPROBES +diff --git a/target/linux/generic/pending-4.14/400-mtd-add-rootfs-split-support.patch b/target/linux/generic/pending-4.14/400-mtd-add-rootfs-split-support.patch +new file mode 100644 +index 0000000000..10ad99585d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/400-mtd-add-rootfs-split-support.patch +@@ -0,0 +1,108 @@ ++From: Felix Fietkau ++Subject: make rootfs split/detection more generic - patch can be moved to generic-2.6 after testing on other platforms ++ ++lede-commit: 328e660b31f0937d52c5ae3d6e7029409918a9df ++Signed-off-by: Felix Fietkau ++--- ++ drivers/mtd/Kconfig | 17 +++++++++++++++++ ++ drivers/mtd/mtdpart.c | 35 +++++++++++++++++++++++++++++++++++ ++ include/linux/mtd/partitions.h | 2 ++ ++ 3 files changed, 54 insertions(+) ++ ++--- a/drivers/mtd/Kconfig +++++ b/drivers/mtd/Kconfig ++@@ -12,6 +12,23 @@ menuconfig MTD ++ ++ if MTD ++ +++menu "OpenWrt specific MTD options" +++ +++config MTD_ROOTFS_ROOT_DEV +++ bool "Automatically set 'rootfs' partition to be root filesystem" +++ default y +++ +++config MTD_SPLIT_FIRMWARE +++ bool "Automatically split firmware partition for kernel+rootfs" +++ default y +++ +++config MTD_SPLIT_FIRMWARE_NAME +++ string "Firmware partition name" +++ depends on MTD_SPLIT_FIRMWARE +++ default "firmware" +++ +++endmenu +++ ++ config MTD_TESTS ++ tristate "MTD tests support (DANGEROUS)" ++ depends on m ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -29,11 +29,13 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++ ++ #include "mtdcore.h" +++#include "mtdsplit/mtdsplit.h" ++ ++ /* Our partition linked list */ ++ static LIST_HEAD(mtd_partitions); ++@@ -53,6 +55,8 @@ struct mtd_part { ++ struct list_head list; ++ }; ++ +++static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part); +++ ++ /* ++ * Given a pointer to the MTD object in the mtd_part structure, we can retrieve ++ * the pointer to that structure. ++@@ -671,6 +675,7 @@ int mtd_add_partition(struct mtd_info *p ++ if (ret) ++ goto err_remove_part; ++ +++ mtd_partition_split(parent, new); ++ mtd_add_partition_attrs(new); ++ ++ return 0; ++@@ -757,6 +762,29 @@ int mtd_del_partition(struct mtd_info *m ++ } ++ EXPORT_SYMBOL_GPL(mtd_del_partition); ++ +++#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME +++#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME +++#else +++#define SPLIT_FIRMWARE_NAME "unused" +++#endif +++ +++static void split_firmware(struct mtd_info *master, struct mtd_part *part) +++{ +++} +++ +++static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part) +++{ +++ static int rootfs_found = 0; +++ +++ if (rootfs_found) +++ return; +++ +++ if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) && +++ !strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) && +++ !of_find_property(mtd_get_of_node(&part->mtd), "compatible", NULL)) +++ split_firmware(master, part); +++} +++ ++ /* ++ * This function, given a master MTD object and a partition table, creates ++ * and registers slave MTD objects which are bound to the master according to ++@@ -797,6 +825,7 @@ int add_mtd_partitions(struct mtd_info * ++ goto err_del_partitions; ++ } ++ +++ mtd_partition_split(master, slave); ++ mtd_add_partition_attrs(slave); ++ /* Look for subpartitions */ ++ parse_mtd_partitions(&slave->mtd, parts[i].types, NULL); +diff --git a/target/linux/generic/pending-4.14/401-mtd-add-support-for-different-partition-parser-types.patch b/target/linux/generic/pending-4.14/401-mtd-add-support-for-different-partition-parser-types.patch +new file mode 100644 +index 0000000000..057d473684 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/401-mtd-add-support-for-different-partition-parser-types.patch +@@ -0,0 +1,142 @@ ++From: Gabor Juhos ++Subject: mtd: add support for different partition parser types ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/mtd/mtdpart.c | 56 ++++++++++++++++++++++++++++++++++++++++ ++ include/linux/mtd/partitions.h | 11 ++++++++ ++ 2 files changed, 67 insertions(+) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -56,6 +56,10 @@ struct mtd_part { ++ }; ++ ++ static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part); +++static int parse_mtd_partitions_by_type(struct mtd_info *master, +++ enum mtd_parser_type type, +++ const struct mtd_partition **pparts, +++ struct mtd_part_parser_data *data); ++ ++ /* ++ * Given a pointer to the MTD object in the mtd_part structure, we can retrieve ++@@ -762,6 +766,36 @@ int mtd_del_partition(struct mtd_info *m ++ } ++ EXPORT_SYMBOL_GPL(mtd_del_partition); ++ +++static int +++run_parsers_by_type(struct mtd_part *slave, enum mtd_parser_type type) +++{ +++ struct mtd_partition *parts; +++ int nr_parts; +++ int i; +++ +++ nr_parts = parse_mtd_partitions_by_type(&slave->mtd, type, (const struct mtd_partition **)&parts, +++ NULL); +++ if (nr_parts <= 0) +++ return nr_parts; +++ +++ if (WARN_ON(!parts)) +++ return 0; +++ +++ for (i = 0; i < nr_parts; i++) { +++ /* adjust partition offsets */ +++ parts[i].offset += slave->offset; +++ +++ mtd_add_partition(slave->parent, +++ parts[i].name, +++ parts[i].offset, +++ parts[i].size); +++ } +++ +++ kfree(parts); +++ +++ return nr_parts; +++} +++ ++ #ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME ++ #define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME ++ #else ++@@ -1147,6 +1181,61 @@ void mtd_part_parser_cleanup(struct mtd_ ++ } ++ } ++ +++static struct mtd_part_parser * +++get_partition_parser_by_type(enum mtd_parser_type type, +++ struct mtd_part_parser *start) +++{ +++ struct mtd_part_parser *p, *ret = NULL; +++ +++ spin_lock(&part_parser_lock); +++ +++ p = list_prepare_entry(start, &part_parsers, list); +++ if (start) +++ mtd_part_parser_put(start); +++ +++ list_for_each_entry_continue(p, &part_parsers, list) { +++ if (p->type == type && try_module_get(p->owner)) { +++ ret = p; +++ break; +++ } +++ } +++ +++ spin_unlock(&part_parser_lock); +++ +++ return ret; +++} +++ +++static int parse_mtd_partitions_by_type(struct mtd_info *master, +++ enum mtd_parser_type type, +++ const struct mtd_partition **pparts, +++ struct mtd_part_parser_data *data) +++{ +++ struct mtd_part_parser *prev = NULL; +++ int ret = 0; +++ +++ while (1) { +++ struct mtd_part_parser *parser; +++ +++ parser = get_partition_parser_by_type(type, prev); +++ if (!parser) +++ break; +++ +++ ret = (*parser->parse_fn)(master, pparts, data); +++ +++ if (ret > 0) { +++ mtd_part_parser_put(parser); +++ printk(KERN_NOTICE +++ "%d %s partitions found on MTD device %s\n", +++ ret, parser->name, master->name); +++ break; +++ } +++ +++ prev = parser; +++ } +++ +++ return ret; +++} +++ ++ int mtd_is_partition(const struct mtd_info *mtd) ++ { ++ struct mtd_part *part; ++--- a/include/linux/mtd/partitions.h +++++ b/include/linux/mtd/partitions.h ++@@ -73,6 +73,10 @@ struct mtd_part_parser_data { ++ * Functions dealing with the various ways of partitioning the space ++ */ ++ +++enum mtd_parser_type { +++ MTD_PARSER_TYPE_DEVICE = 0, +++}; +++ ++ struct mtd_part_parser { ++ struct list_head list; ++ struct module *owner; ++@@ -81,6 +85,7 @@ struct mtd_part_parser { ++ int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, ++ struct mtd_part_parser_data *); ++ void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); +++ enum mtd_parser_type type; ++ }; ++ ++ /* Container for passing around a set of parsed partitions */ +diff --git a/target/linux/generic/pending-4.14/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch b/target/linux/generic/pending-4.14/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch +new file mode 100644 +index 0000000000..2cc06dd463 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch +@@ -0,0 +1,44 @@ ++From: Gabor Juhos ++Subject: kernel/3.10: allow to use partition parsers for rootfs and firmware split ++ ++lede-commit: 3b71cd94bc9517bc25267dccb393b07d4b54564e ++Signed-off-by: Gabor Juhos ++--- ++ drivers/mtd/mtdpart.c | 37 +++++++++++++++++++++++++++++++++++++ ++ include/linux/mtd/partitions.h | 2 ++ ++ 2 files changed, 39 insertions(+) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -804,6 +804,7 @@ run_parsers_by_type(struct mtd_part *sla ++ ++ static void split_firmware(struct mtd_info *master, struct mtd_part *part) ++ { +++ run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE); ++ } ++ ++ static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part) ++@@ -813,6 +814,12 @@ static void mtd_partition_split(struct m ++ if (rootfs_found) ++ return; ++ +++ if (!strcmp(part->mtd.name, "rootfs")) { +++ run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS); +++ +++ rootfs_found = 1; +++ } +++ ++ if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) && ++ !strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) && ++ !of_find_property(mtd_get_of_node(&part->mtd), "compatible", NULL)) ++--- a/include/linux/mtd/partitions.h +++++ b/include/linux/mtd/partitions.h ++@@ -75,6 +75,8 @@ struct mtd_part_parser_data { ++ ++ enum mtd_parser_type { ++ MTD_PARSER_TYPE_DEVICE = 0, +++ MTD_PARSER_TYPE_ROOTFS, +++ MTD_PARSER_TYPE_FIRMWARE, ++ }; ++ ++ struct mtd_part_parser { +diff --git a/target/linux/generic/pending-4.14/403-mtd-hook-mtdsplit-to-Kbuild.patch b/target/linux/generic/pending-4.14/403-mtd-hook-mtdsplit-to-Kbuild.patch +new file mode 100644 +index 0000000000..89c202bc0d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/403-mtd-hook-mtdsplit-to-Kbuild.patch +@@ -0,0 +1,32 @@ ++From: Gabor Juhos ++Subject: [PATCH] kernel/3.10: move squashfs check from rootfs split code into a separate file ++ ++lede-commit: d89bea92b31b4e157a0fa438e75370f089f73427 ++Signed-off-by: Gabor Juhos ++--- ++ drivers/mtd/Kconfig | 2 ++ ++ drivers/mtd/Makefile | 2 ++ ++ 2 files changed, 4 insertions(+) ++ ++--- a/drivers/mtd/Kconfig +++++ b/drivers/mtd/Kconfig ++@@ -27,6 +27,8 @@ config MTD_SPLIT_FIRMWARE_NAME ++ depends on MTD_SPLIT_FIRMWARE ++ default "firmware" ++ +++source "drivers/mtd/mtdsplit/Kconfig" +++ ++ endmenu ++ ++ config MTD_TESTS ++--- a/drivers/mtd/Makefile +++++ b/drivers/mtd/Makefile ++@@ -7,6 +7,8 @@ ++ obj-$(CONFIG_MTD) += mtd.o ++ mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o ++ +++obj-$(CONFIG_MTD_SPLIT) += mtdsplit/ +++ ++ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o ++ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o ++ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o +diff --git a/target/linux/generic/pending-4.14/404-mtd-add-more-helper-functions.patch b/target/linux/generic/pending-4.14/404-mtd-add-more-helper-functions.patch +new file mode 100644 +index 0000000000..7b481ffb47 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/404-mtd-add-more-helper-functions.patch +@@ -0,0 +1,76 @@ ++From: Gabor Juhos ++Subject: kernel/3.10: add separate rootfs partition parser ++ ++lede-commit: daec7ad7688415156e2730e401503d09bd3acf91 ++Signed-off-by: Gabor Juhos ++--- ++ drivers/mtd/mtdpart.c | 29 +++++++++++++++++++++++++++++ ++ include/linux/mtd/mtd.h | 18 ++++++++++++++++++ ++ include/linux/mtd/partitions.h | 2 ++ ++ 3 files changed, 49 insertions(+) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -1260,6 +1260,24 @@ int mtd_is_partition(const struct mtd_in ++ } ++ EXPORT_SYMBOL_GPL(mtd_is_partition); ++ +++struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd) +++{ +++ if (!mtd_is_partition(mtd)) +++ return (struct mtd_info *)mtd; +++ +++ return mtd_to_part(mtd)->parent; +++} +++EXPORT_SYMBOL_GPL(mtdpart_get_master); +++ +++uint64_t mtdpart_get_offset(const struct mtd_info *mtd) +++{ +++ if (!mtd_is_partition(mtd)) +++ return 0; +++ +++ return mtd_to_part(mtd)->offset; +++} +++EXPORT_SYMBOL_GPL(mtdpart_get_offset); +++ ++ /* Returns the size of the entire flash chip */ ++ uint64_t mtd_get_device_size(const struct mtd_info *mtd) ++ { ++--- a/include/linux/mtd/mtd.h +++++ b/include/linux/mtd/mtd.h ++@@ -494,6 +494,24 @@ static inline uint32_t mtd_mod_by_eb(uin ++ return do_div(sz, mtd->erasesize); ++ } ++ +++static inline uint64_t mtd_roundup_to_eb(uint64_t sz, struct mtd_info *mtd) +++{ +++ if (mtd_mod_by_eb(sz, mtd) == 0) +++ return sz; +++ +++ /* Round up to next erase block */ +++ return (mtd_div_by_eb(sz, mtd) + 1) * mtd->erasesize; +++} +++ +++static inline uint64_t mtd_rounddown_to_eb(uint64_t sz, struct mtd_info *mtd) +++{ +++ if (mtd_mod_by_eb(sz, mtd) == 0) +++ return sz; +++ +++ /* Round down to the start of the current erase block */ +++ return (mtd_div_by_eb(sz, mtd)) * mtd->erasesize; +++} +++ ++ static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) ++ { ++ if (mtd->writesize_shift) ++--- a/include/linux/mtd/partitions.h +++++ b/include/linux/mtd/partitions.h ++@@ -116,6 +116,8 @@ int mtd_is_partition(const struct mtd_in ++ int mtd_add_partition(struct mtd_info *master, const char *name, ++ long long offset, long long length); ++ int mtd_del_partition(struct mtd_info *master, int partno); +++struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd); +++uint64_t mtdpart_get_offset(const struct mtd_info *mtd); ++ uint64_t mtd_get_device_size(const struct mtd_info *mtd); ++ ++ #endif +diff --git a/target/linux/generic/pending-4.14/411-mtd-partial_eraseblock_write.patch b/target/linux/generic/pending-4.14/411-mtd-partial_eraseblock_write.patch +new file mode 100644 +index 0000000000..52f1cb5abf +--- /dev/null ++++ b/target/linux/generic/pending-4.14/411-mtd-partial_eraseblock_write.patch +@@ -0,0 +1,153 @@ ++From: Felix Fietkau ++Subject: mtd: implement write support for partitions covering only a part of an eraseblock (buffer data that would otherwise be erased) ++ ++lede-commit: 87a8e8ac1067f58ba831c4aae443f3655c31cd80 ++Signed-off-by: Felix Fietkau ++--- ++ drivers/mtd/mtdpart.c | 90 ++++++++++++++++++++++++++++++++++++++++++++----- ++ include/linux/mtd/mtd.h | 4 +++ ++ 2 files changed, 85 insertions(+), 9 deletions(-) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -37,6 +37,8 @@ ++ #include "mtdcore.h" ++ #include "mtdsplit/mtdsplit.h" ++ +++#define MTD_ERASE_PARTIAL 0x8000 /* partition only covers parts of an erase block */ +++ ++ /* Our partition linked list */ ++ static LIST_HEAD(mtd_partitions); ++ static DEFINE_MUTEX(mtd_partitions_mutex); ++@@ -255,13 +257,61 @@ static int part_erase(struct mtd_info *m ++ struct mtd_part *part = mtd_to_part(mtd); ++ int ret; ++ +++ +++ instr->partial_start = false; +++ if (mtd->flags & MTD_ERASE_PARTIAL) { +++ size_t readlen = 0; +++ u64 mtd_ofs; +++ +++ instr->erase_buf = kmalloc(part->parent->erasesize, GFP_ATOMIC); +++ if (!instr->erase_buf) +++ return -ENOMEM; +++ +++ mtd_ofs = part->offset + instr->addr; +++ instr->erase_buf_ofs = do_div(mtd_ofs, part->parent->erasesize); +++ +++ if (instr->erase_buf_ofs > 0) { +++ instr->addr -= instr->erase_buf_ofs; +++ ret = mtd_read(part->parent, +++ instr->addr + part->offset, +++ part->parent->erasesize, +++ &readlen, instr->erase_buf); +++ +++ instr->len += instr->erase_buf_ofs; +++ instr->partial_start = true; +++ } else { +++ mtd_ofs = part->offset + part->mtd.size; +++ instr->erase_buf_ofs = part->parent->erasesize - +++ do_div(mtd_ofs, part->parent->erasesize); +++ +++ if (instr->erase_buf_ofs > 0) { +++ instr->len += instr->erase_buf_ofs; +++ ret = mtd_read(part->parent, +++ part->offset + instr->addr + +++ instr->len - part->parent->erasesize, +++ part->parent->erasesize, &readlen, +++ instr->erase_buf); +++ } else { +++ ret = 0; +++ } +++ } +++ if (ret < 0) { +++ kfree(instr->erase_buf); +++ return ret; +++ } +++ +++ } +++ ++ instr->addr += part->offset; ++ ret = part->parent->_erase(part->parent, instr); ++ if (ret) { ++ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) ++ instr->fail_addr -= part->offset; ++ instr->addr -= part->offset; +++ if (mtd->flags & MTD_ERASE_PARTIAL) +++ kfree(instr->erase_buf); ++ } +++ ++ return ret; ++ } ++ ++@@ -269,6 +319,25 @@ void mtd_erase_callback(struct erase_inf ++ { ++ if (instr->mtd->_erase == part_erase) { ++ struct mtd_part *part = mtd_to_part(instr->mtd); +++ size_t wrlen = 0; +++ +++ if (instr->mtd->flags & MTD_ERASE_PARTIAL) { +++ if (instr->partial_start) { +++ part->parent->_write(part->parent, +++ instr->addr, instr->erase_buf_ofs, +++ &wrlen, instr->erase_buf); +++ instr->addr += instr->erase_buf_ofs; +++ } else { +++ instr->len -= instr->erase_buf_ofs; +++ part->parent->_write(part->parent, +++ instr->addr + instr->len, +++ instr->erase_buf_ofs, &wrlen, +++ instr->erase_buf + +++ part->parent->erasesize - +++ instr->erase_buf_ofs); +++ } +++ kfree(instr->erase_buf); +++ } ++ ++ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) ++ instr->fail_addr -= part->offset; ++@@ -584,19 +653,22 @@ static struct mtd_part *allocate_partiti ++ remainder = do_div(tmp, wr_alignment); ++ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { ++ /* Doesn't start on a boundary of major erase size */ ++- /* FIXME: Let it be writable if it is on a boundary of ++- * _minor_ erase size though */ ++- slave->mtd.flags &= ~MTD_WRITEABLE; ++- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n", ++- part->name); +++ slave->mtd.flags |= MTD_ERASE_PARTIAL; +++ if (((u32)slave->mtd.size) > parent->erasesize) +++ slave->mtd.flags &= ~MTD_WRITEABLE; +++ else +++ slave->mtd.erasesize = slave->mtd.size; ++ } ++ ++ tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size; ++ remainder = do_div(tmp, wr_alignment); ++ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { ++- slave->mtd.flags &= ~MTD_WRITEABLE; ++- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n", ++- part->name); +++ slave->mtd.flags |= MTD_ERASE_PARTIAL; +++ +++ if ((u32)slave->mtd.size > parent->erasesize) +++ slave->mtd.flags &= ~MTD_WRITEABLE; +++ else +++ slave->mtd.erasesize = slave->mtd.size; ++ } ++ ++ mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops); ++--- a/include/linux/mtd/mtd.h +++++ b/include/linux/mtd/mtd.h ++@@ -56,6 +56,10 @@ struct erase_info { ++ u_long priv; ++ u_char state; ++ struct erase_info *next; +++ +++ u8 *erase_buf; +++ u32 erase_buf_ofs; +++ bool partial_start; ++ }; ++ ++ struct mtd_erase_region_info { +diff --git a/target/linux/generic/pending-4.14/412-mtd-partial_eraseblock_unlock.patch b/target/linux/generic/pending-4.14/412-mtd-partial_eraseblock_unlock.patch +new file mode 100644 +index 0000000000..3ac3496c69 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/412-mtd-partial_eraseblock_unlock.patch +@@ -0,0 +1,40 @@ ++From: Tim Harvey ++Subject: mtd: allow partial block unlock ++ ++This allows sysupgrade for devices such as the Gateworks Avila/Cambria ++product families based on the ixp4xx using the redboot bootloader with ++combined FIS directory and RedBoot config partitions on larger FLASH ++devices with larger eraseblocks. ++ ++This second iteration of this patch addresses previous issues: ++- whitespace breakage fixed ++- unlock in all scenarios ++- simplification and fix logic bug ++ ++[john@phrozen.org: this should be moved to the ixp4xx folder] ++ ++Signed-off-by: Tim Harvey ++--- ++ drivers/mtd/mtdpart.c | 11 ++++++++++- ++ 1 file changed, 10 insertions(+), 1 deletion(-) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -357,7 +357,16 @@ static int part_lock(struct mtd_info *mt ++ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) ++ { ++ struct mtd_part *part = mtd_to_part(mtd); ++- return part->parent->_unlock(part->parent, ofs + part->offset, len); +++ +++ ofs += part->offset; +++ +++ if (mtd->flags & MTD_ERASE_PARTIAL) { +++ /* round up len to next erasesize and round down offset to prev block */ +++ len = (mtd_div_by_eb(len, part->parent) + 1) * part->parent->erasesize; +++ ofs &= ~(part->parent->erasesize - 1); +++ } +++ +++ return part->parent->_unlock(part->parent, ofs, len); ++ } ++ ++ static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) +diff --git a/target/linux/generic/pending-4.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch b/target/linux/generic/pending-4.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch +new file mode 100644 +index 0000000000..fbf9a0553c +--- /dev/null ++++ b/target/linux/generic/pending-4.14/419-mtd-redboot-add-of_match_table-with-DT-binding.patch +@@ -0,0 +1,31 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Subject: [PATCH] mtd: redboot: add of_match_table with DT binding ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This allows parsing RedBoot compatible partitions for properly described ++flash device in DT. ++ ++Signed-off-by: Rafał Miłecki ++--- ++ ++--- a/drivers/mtd/redboot.c +++++ b/drivers/mtd/redboot.c ++@@ -289,9 +289,16 @@ static int parse_redboot_partitions(stru ++ return ret; ++ } ++ +++static const struct of_device_id redboot_parser_of_match_table[] = { +++ { .compatible = "ecoscentric,redboot-fis-partitions" }, +++ {}, +++}; +++MODULE_DEVICE_TABLE(of, redboot_parser_of_match_table); +++ ++ static struct mtd_part_parser redboot_parser = { ++ .parse_fn = parse_redboot_partitions, ++ .name = "RedBoot", +++ .of_match_table = redboot_parser_of_match_table, ++ }; ++ module_mtd_part_parser(redboot_parser); ++ +diff --git a/target/linux/generic/pending-4.14/420-mtd-redboot_space.patch b/target/linux/generic/pending-4.14/420-mtd-redboot_space.patch +new file mode 100644 +index 0000000000..85fbe0512d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/420-mtd-redboot_space.patch +@@ -0,0 +1,41 @@ ++From: Felix Fietkau ++Subject: add patch for including unpartitioned space in the rootfs partition for redboot devices (if applicable) ++ ++[john@phrozen.org: used by ixp and others] ++ ++lede-commit: 394918851f84e4d00fa16eb900e7700e95091f00 ++Signed-off-by: Felix Fietkau ++--- ++ drivers/mtd/redboot.c | 19 +++++++++++++------ ++ 1 file changed, 13 insertions(+), 6 deletions(-) ++ ++--- a/drivers/mtd/redboot.c +++++ b/drivers/mtd/redboot.c ++@@ -265,14 +265,21 @@ static int parse_redboot_partitions(stru ++ #endif ++ names += strlen(names)+1; ++ ++-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED ++ if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { ++- i++; ++- parts[i].offset = parts[i-1].size + parts[i-1].offset; ++- parts[i].size = fl->next->img->flash_base - parts[i].offset; ++- parts[i].name = nullname; ++- } +++ if (!strcmp(parts[i].name, "rootfs")) { +++ parts[i].size = fl->next->img->flash_base; +++ parts[i].size &= ~(master->erasesize - 1); +++ parts[i].size -= parts[i].offset; +++#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED +++ nrparts--; +++ } else { +++ i++; +++ parts[i].offset = parts[i-1].size + parts[i-1].offset; +++ parts[i].size = fl->next->img->flash_base - parts[i].offset; +++ parts[i].name = nullname; ++ #endif +++ } +++ } ++ tmp_fl = fl; ++ fl = fl->next; ++ kfree(tmp_fl); +diff --git a/target/linux/generic/pending-4.14/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-4.14/430-mtd-add-myloader-partition-parser.patch +new file mode 100644 +index 0000000000..bf6670a91e +--- /dev/null ++++ b/target/linux/generic/pending-4.14/430-mtd-add-myloader-partition-parser.patch +@@ -0,0 +1,229 @@ ++From: Florian Fainelli ++Subject: Add myloader partition table parser ++ ++[john@phozen.org: shoud be upstreamable] ++ ++lede-commit: d8bf22859b51faa09d22c056fe221a45d2f7a3b8 ++Signed-off-by: Florian Fainelli ++[add myloader.c to patch] ++Signed-off-by: Adrian Schmutzler ++ ++--- a/drivers/mtd/Kconfig +++++ b/drivers/mtd/Kconfig ++@@ -178,6 +178,22 @@ menu "Partition parsers" ++ source "drivers/mtd/parsers/Kconfig" ++ endmenu ++ +++config MTD_MYLOADER_PARTS +++ tristate "MyLoader partition parsing" +++ depends on ADM5120 || ATH25 || ATH79 +++ ---help--- +++ MyLoader is a bootloader which allows the user to define partitions +++ in flash devices, by putting a table in the second erase block +++ on the device, similar to a partition table. This table gives the +++ offsets and lengths of the user defined partitions. +++ +++ If you need code which can detect and parse these tables, and +++ register MTD 'partitions' corresponding to each image detected, +++ enable this option. +++ +++ You will still need the parsing functions to be called by the driver +++ for your particular device. It won't happen automatically. +++ ++ comment "User Modules And Translation Layers" ++ ++ # ++--- a/drivers/mtd/Makefile +++++ b/drivers/mtd/Makefile ++@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o ++ obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o ++ obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o ++ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o +++obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o ++ obj-y += parsers/ ++ ++ # 'Users' - code which presents functionality to userspace. ++--- /dev/null +++++ b/drivers/mtd/myloader.c ++@@ -0,0 +1,181 @@ +++/* +++ * Parse MyLoader-style flash partition tables and produce a Linux partition +++ * array to match. +++ * +++ * Copyright (C) 2007-2009 Gabor Juhos +++ * +++ * This file was based on drivers/mtd/redboot.c +++ * Author: Red Hat, Inc. - David Woodhouse +++ * +++ * 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 +++#include +++#include +++#include +++ +++#define BLOCK_LEN_MIN 0x10000 +++#define PART_NAME_LEN 32 +++ +++struct part_data { +++ struct mylo_partition_table tab; +++ char names[MYLO_MAX_PARTITIONS][PART_NAME_LEN]; +++}; +++ +++static int myloader_parse_partitions(struct mtd_info *master, +++ const struct mtd_partition **pparts, +++ struct mtd_part_parser_data *data) +++{ +++ struct part_data *buf; +++ struct mylo_partition_table *tab; +++ struct mylo_partition *part; +++ struct mtd_partition *mtd_parts; +++ struct mtd_partition *mtd_part; +++ int num_parts; +++ int ret, i; +++ size_t retlen; +++ char *names; +++ unsigned long offset; +++ unsigned long blocklen; +++ +++ buf = vmalloc(sizeof(*buf)); +++ if (!buf) { +++ return -ENOMEM; +++ goto out; +++ } +++ tab = &buf->tab; +++ +++ blocklen = master->erasesize; +++ if (blocklen < BLOCK_LEN_MIN) +++ blocklen = BLOCK_LEN_MIN; +++ +++ offset = blocklen; +++ +++ /* Find the partition table */ +++ for (i = 0; i < 4; i++, offset += blocklen) { +++ printk(KERN_DEBUG "%s: searching for MyLoader partition table" +++ " at offset 0x%lx\n", master->name, offset); +++ +++ ret = mtd_read(master, offset, sizeof(*buf), &retlen, +++ (void *)buf); +++ if (ret) +++ goto out_free_buf; +++ +++ if (retlen != sizeof(*buf)) { +++ ret = -EIO; +++ goto out_free_buf; +++ } +++ +++ /* Check for Partition Table magic number */ +++ if (tab->magic == le32_to_cpu(MYLO_MAGIC_PARTITIONS)) +++ break; +++ +++ } +++ +++ if (tab->magic != le32_to_cpu(MYLO_MAGIC_PARTITIONS)) { +++ printk(KERN_DEBUG "%s: no MyLoader partition table found\n", +++ master->name); +++ ret = 0; +++ goto out_free_buf; +++ } +++ +++ /* The MyLoader and the Partition Table is always present */ +++ num_parts = 2; +++ +++ /* Detect number of used partitions */ +++ for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { +++ part = &tab->partitions[i]; +++ +++ if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) +++ continue; +++ +++ num_parts++; +++ } +++ +++ mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + +++ num_parts * PART_NAME_LEN), GFP_KERNEL); +++ +++ if (!mtd_parts) { +++ ret = -ENOMEM; +++ goto out_free_buf; +++ } +++ +++ mtd_part = mtd_parts; +++ names = (char *)&mtd_parts[num_parts]; +++ +++ strncpy(names, "myloader", PART_NAME_LEN); +++ mtd_part->name = names; +++ mtd_part->offset = 0; +++ mtd_part->size = offset; +++ mtd_part->mask_flags = MTD_WRITEABLE; +++ mtd_part++; +++ names += PART_NAME_LEN; +++ +++ strncpy(names, "partition_table", PART_NAME_LEN); +++ mtd_part->name = names; +++ mtd_part->offset = offset; +++ mtd_part->size = blocklen; +++ mtd_part->mask_flags = MTD_WRITEABLE; +++ mtd_part++; +++ names += PART_NAME_LEN; +++ +++ for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { +++ part = &tab->partitions[i]; +++ +++ if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) +++ continue; +++ +++ if ((buf->names[i][0]) && (buf->names[i][0] != '\xff')) +++ strncpy(names, buf->names[i], PART_NAME_LEN); +++ else +++ snprintf(names, PART_NAME_LEN, "partition%d", i); +++ +++ mtd_part->offset = le32_to_cpu(part->addr); +++ mtd_part->size = le32_to_cpu(part->size); +++ mtd_part->name = names; +++ mtd_part++; +++ names += PART_NAME_LEN; +++ } +++ +++ *pparts = mtd_parts; +++ ret = num_parts; +++ +++ out_free_buf: +++ vfree(buf); +++ out: +++ return ret; +++} +++ +++static struct mtd_part_parser myloader_mtd_parser = { +++ .owner = THIS_MODULE, +++ .parse_fn = myloader_parse_partitions, +++ .name = "MyLoader", +++}; +++ +++static int __init myloader_mtd_parser_init(void) +++{ +++ register_mtd_parser(&myloader_mtd_parser); +++ +++ return 0; +++} +++ +++static void __exit myloader_mtd_parser_exit(void) +++{ +++ deregister_mtd_parser(&myloader_mtd_parser); +++} +++ +++module_init(myloader_mtd_parser_init); +++module_exit(myloader_mtd_parser_exit); +++ +++MODULE_AUTHOR("Gabor Juhos "); +++MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); +++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/generic/pending-4.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch b/target/linux/generic/pending-4.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch +new file mode 100644 +index 0000000000..d54c284c34 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch +@@ -0,0 +1,68 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating offsets ++ ++Signed-off-by: Rafał Miłecki ++--- ++ ++--- a/drivers/mtd/parsers/parser_trx.c +++++ b/drivers/mtd/parsers/parser_trx.c ++@@ -29,6 +29,33 @@ struct trx_header { ++ uint32_t offset[3]; ++ } __packed; ++ +++/* +++ * Calculate real end offset (address) for a given amount of data. It checks +++ * all blocks skipping bad ones. +++ */ +++static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes) +++{ +++ size_t real_offset = 0; +++ +++ if (mtd_block_isbad(mtd, real_offset)) +++ pr_warn("Base offset shouldn't be at bad block"); +++ +++ while (bytes >= mtd->erasesize) { +++ bytes -= mtd->erasesize; +++ real_offset += mtd->erasesize; +++ while (mtd_block_isbad(mtd, real_offset)) { +++ real_offset += mtd->erasesize; +++ +++ if (real_offset >= mtd->size) +++ return real_offset - mtd->erasesize; +++ } +++ } +++ +++ real_offset += bytes; +++ +++ return real_offset; +++} +++ ++ static const char *parser_trx_data_part_name(struct mtd_info *master, ++ size_t offset) ++ { ++@@ -83,21 +110,21 @@ static int parser_trx_parse(struct mtd_i ++ if (trx.offset[2]) { ++ part = &parts[curr_part++]; ++ part->name = "loader"; ++- part->offset = trx.offset[i]; +++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); ++ i++; ++ } ++ ++ if (trx.offset[i]) { ++ part = &parts[curr_part++]; ++ part->name = "linux"; ++- part->offset = trx.offset[i]; +++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); ++ i++; ++ } ++ ++ if (trx.offset[i]) { ++ part = &parts[curr_part++]; ++- part->name = parser_trx_data_part_name(mtd, trx.offset[i]); ++- part->offset = trx.offset[i]; +++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); +++ part->name = parser_trx_data_part_name(mtd, part->offset); ++ i++; ++ } ++ +diff --git a/target/linux/generic/pending-4.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch b/target/linux/generic/pending-4.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch +new file mode 100644 +index 0000000000..a6d0828b99 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch +@@ -0,0 +1,37 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Subject: mtd: bcm47xxpart: detect T_Meter partition ++ ++It can be found on many Netgear devices. It consists of many 0x30 blocks ++starting with 4D 54. ++ ++Signed-off-by: Rafał Miłecki ++--- ++ drivers/mtd/bcm47xxpart.c | 10 ++++++++++ ++ 1 file changed, 10 insertions(+) ++ ++--- a/drivers/mtd/bcm47xxpart.c +++++ b/drivers/mtd/bcm47xxpart.c ++@@ -39,6 +39,7 @@ ++ #define NVRAM_HEADER 0x48534C46 /* FLSH */ ++ #define POT_MAGIC1 0x54544f50 /* POTT */ ++ #define POT_MAGIC2 0x504f /* OP */ +++#define T_METER_MAGIC 0x4D540000 /* MT */ ++ #define ML_MAGIC1 0x39685a42 ++ #define ML_MAGIC2 0x26594131 ++ #define TRX_MAGIC 0x30524448 ++@@ -182,6 +183,15 @@ static int bcm47xxpart_parse(struct mtd_ ++ MTD_WRITEABLE); ++ continue; ++ } +++ +++ /* T_Meter */ +++ if ((le32_to_cpu(buf[0x000 / 4]) & 0xFFFF0000) == T_METER_MAGIC && +++ (le32_to_cpu(buf[0x030 / 4]) & 0xFFFF0000) == T_METER_MAGIC && +++ (le32_to_cpu(buf[0x060 / 4]) & 0xFFFF0000) == T_METER_MAGIC) { +++ bcm47xxpart_add_part(&parts[curr_part++], "T_Meter", offset, +++ MTD_WRITEABLE); +++ continue; +++ } ++ ++ /* TRX */ ++ if (buf[0x000 / 4] == TRX_MAGIC) { +diff --git a/target/linux/generic/pending-4.14/435-mtd-add-routerbootpart-parser-config.patch b/target/linux/generic/pending-4.14/435-mtd-add-routerbootpart-parser-config.patch +new file mode 100644 +index 0000000000..946af76f5b +--- /dev/null ++++ b/target/linux/generic/pending-4.14/435-mtd-add-routerbootpart-parser-config.patch +@@ -0,0 +1,36 @@ ++From 4437e01fb6bca63fccdba5d6c44888b0935885c2 Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= ++Date: Tue, 24 Mar 2020 11:45:07 +0100 ++Subject: [PATCH] generic: routerboot partition build bits (4.14) ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This patch adds routerbootpart kernel build bits ++ ++Signed-off-by: Thibaut VARÈNE ++--- ++ drivers/mtd/parsers/Kconfig | 9 +++++++++ ++ drivers/mtd/parsers/Makefile | 1 + ++ 2 files changed, 10 insertions(+) ++ ++--- a/drivers/mtd/parsers/Kconfig +++++ b/drivers/mtd/parsers/Kconfig ++@@ -6,3 +6,12 @@ config MTD_PARSER_TRX ++ may contain up to 3/4 partitions (depending on the version). ++ This driver will parse TRX header and report at least two partitions: ++ kernel and rootfs. +++ +++config MTD_ROUTERBOOT_PARTS +++ tristate "RouterBoot flash partition parser" +++ depends on MTD && OF +++ help +++ MikroTik RouterBoot is implemented as a multi segment system on the +++ flash, some of which are fixed and some of which are located at +++ variable offsets. This parser handles both cases via properly +++ formatted DTS. ++--- a/drivers/mtd/parsers/Makefile +++++ b/drivers/mtd/parsers/Makefile ++@@ -1 +1,2 @@ ++ obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o +++obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o +diff --git a/target/linux/generic/pending-4.14/440-block2mtd_init.patch b/target/linux/generic/pending-4.14/440-block2mtd_init.patch +new file mode 100644 +index 0000000000..8834788732 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/440-block2mtd_init.patch +@@ -0,0 +1,116 @@ ++From: Felix Fietkau ++Subject: block2mtd ++ ++Signed-off-by: Felix Fietkau ++--- ++ drivers/mtd/devices/block2mtd.c | 30 ++++++++++++++++++++---------- ++ 1 file changed, 20 insertions(+), 10 deletions(-) ++ ++--- a/drivers/mtd/devices/block2mtd.c +++++ b/drivers/mtd/devices/block2mtd.c ++@@ -26,6 +26,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -219,7 +220,7 @@ static void block2mtd_free_device(struct ++ ++ ++ static struct block2mtd_dev *add_device(char *devname, int erase_size, ++- int timeout) +++ const char *mtdname, int timeout) ++ { ++ #ifndef MODULE ++ int i; ++@@ -227,6 +228,7 @@ static struct block2mtd_dev *add_device( ++ const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; ++ struct block_device *bdev = ERR_PTR(-ENODEV); ++ struct block2mtd_dev *dev; +++ struct mtd_partition *part; ++ char *name; ++ ++ if (!devname) ++@@ -283,13 +285,16 @@ static struct block2mtd_dev *add_device( ++ ++ /* Setup the MTD structure */ ++ /* make the name contain the block device in */ ++- name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname); +++ if (!mtdname) +++ mtdname = devname; +++ name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL); ++ if (!name) ++ goto err_destroy_mutex; ++ +++ strcpy(name, mtdname); ++ dev->mtd.name = name; ++ ++- dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; +++ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1); ++ dev->mtd.erasesize = erase_size; ++ dev->mtd.writesize = 1; ++ dev->mtd.writebufsize = PAGE_SIZE; ++@@ -302,7 +307,11 @@ static struct block2mtd_dev *add_device( ++ dev->mtd.priv = dev; ++ dev->mtd.owner = THIS_MODULE; ++ ++- if (mtd_device_register(&dev->mtd, NULL, 0)) { +++ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); +++ part->name = name; +++ part->offset = 0; +++ part->size = dev->mtd.size; +++ if (mtd_device_register(&dev->mtd, part, 1)) { ++ /* Device didn't get added, so free the entry */ ++ goto err_destroy_mutex; ++ } ++@@ -310,8 +319,7 @@ static struct block2mtd_dev *add_device( ++ list_add(&dev->list, &blkmtd_device_list); ++ pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n", ++ dev->mtd.index, ++- dev->mtd.name + strlen("block2mtd: "), ++- dev->mtd.erasesize >> 10, dev->mtd.erasesize); +++ mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize); ++ return dev; ++ ++ err_destroy_mutex: ++@@ -384,7 +392,7 @@ static int block2mtd_setup2(const char * ++ /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */ ++ char buf[80 + 12 + 80 + 8]; ++ char *str = buf; ++- char *token[2]; +++ char *token[3]; ++ char *name; ++ size_t erase_size = PAGE_SIZE; ++ unsigned long timeout = MTD_DEFAULT_TIMEOUT; ++@@ -398,7 +406,7 @@ static int block2mtd_setup2(const char * ++ strcpy(str, val); ++ kill_final_newline(str); ++ ++- for (i = 0; i < 2; i++) +++ for (i = 0; i < 3; i++) ++ token[i] = strsep(&str, ","); ++ ++ if (str) { ++@@ -424,8 +432,10 @@ static int block2mtd_setup2(const char * ++ return 0; ++ } ++ } +++ if (token[2] && (strlen(token[2]) + 1 > 80)) +++ pr_err("mtd device name too long\n"); ++ ++- add_device(name, erase_size, timeout); +++ add_device(name, erase_size, token[2], timeout); ++ ++ return 0; ++ } ++@@ -459,7 +469,7 @@ static int block2mtd_setup(const char *v ++ ++ ++ module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); ++-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,]\""); +++MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,[,]]\""); ++ ++ static int __init block2mtd_init(void) ++ { +diff --git a/target/linux/generic/pending-4.14/441-block2mtd_probe.patch b/target/linux/generic/pending-4.14/441-block2mtd_probe.patch +new file mode 100644 +index 0000000000..fee970ab61 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/441-block2mtd_probe.patch +@@ -0,0 +1,47 @@ ++From: Felix Fietkau ++Subject: block2mtd ++ ++Signed-off-by: Felix Fietkau ++--- ++ drivers/mtd/devices/block2mtd.c | 9 ++++++--- ++ 1 file changed, 6 insertions(+), 3 deletions(-) ++ ++--- a/drivers/mtd/devices/block2mtd.c +++++ b/drivers/mtd/devices/block2mtd.c ++@@ -392,7 +392,7 @@ static int block2mtd_setup2(const char * ++ /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */ ++ char buf[80 + 12 + 80 + 8]; ++ char *str = buf; ++- char *token[3]; +++ char *token[4]; ++ char *name; ++ size_t erase_size = PAGE_SIZE; ++ unsigned long timeout = MTD_DEFAULT_TIMEOUT; ++@@ -406,7 +406,7 @@ static int block2mtd_setup2(const char * ++ strcpy(str, val); ++ kill_final_newline(str); ++ ++- for (i = 0; i < 3; i++) +++ for (i = 0; i < 4; i++) ++ token[i] = strsep(&str, ","); ++ ++ if (str) { ++@@ -435,6 +435,9 @@ static int block2mtd_setup2(const char * ++ if (token[2] && (strlen(token[2]) + 1 > 80)) ++ pr_err("mtd device name too long\n"); ++ +++ if (token[3] && kstrtoul(token[3], 0, &timeout)) +++ pr_err("invalid timeout\n"); +++ ++ add_device(name, erase_size, token[2], timeout); ++ ++ return 0; ++@@ -469,7 +472,7 @@ static int block2mtd_setup(const char *v ++ ++ ++ module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); ++-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,[,]]\""); +++MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,[,[,]]]\""); ++ ++ static int __init block2mtd_init(void) ++ { +diff --git a/target/linux/generic/pending-4.14/450-mtd-m25p80-allow-fallback-from-spi_flash_read-to-reg.patch b/target/linux/generic/pending-4.14/450-mtd-m25p80-allow-fallback-from-spi_flash_read-to-reg.patch +new file mode 100644 +index 0000000000..accd63df58 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/450-mtd-m25p80-allow-fallback-from-spi_flash_read-to-reg.patch +@@ -0,0 +1,36 @@ ++From: Felix Fietkau ++Date: Fri, 23 Feb 2018 17:12:16 +0100 ++Subject: [PATCH] mtd: m25p80: allow fallback from spi_flash_read to regular ++ SPI transfer ++ ++Some flash controllers, e.g. on the ath79 platform can support a fast ++flash read via memory mapping, but only if the flash chip is in ++3-byte address mode. ++ ++Since spi_flash_read_supported does not have access to the same data as ++spi_flash_read, the driver can't detect an unsupported call until m25p80 ++has decided to use spi_flash_read. ++ ++Allow the driver to indicate a fallback to a regular SPI transfer by ++returning -EOPNOTSUPP ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/mtd/devices/m25p80.c +++++ b/drivers/mtd/devices/m25p80.c ++@@ -170,9 +170,11 @@ static ssize_t m25p80_read(struct spi_no ++ msg.data_nbits = data_nbits; ++ ++ ret = spi_flash_read(spi, &msg); ++- if (ret < 0) ++- return ret; ++- return msg.retlen; +++ if (ret != -EOPNOTSUPP) { +++ if (ret < 0) +++ return ret; +++ return msg.retlen; +++ } ++ } ++ ++ spi_message_init(&m); +diff --git a/target/linux/generic/pending-4.14/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch b/target/linux/generic/pending-4.14/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch +new file mode 100644 +index 0000000000..571c9b885f +--- /dev/null ++++ b/target/linux/generic/pending-4.14/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch +@@ -0,0 +1,36 @@ ++From: Felix Fietkau ++Date: Thu, 22 Feb 2018 11:11:57 +0100 ++Subject: [PATCH] mtd: spi-nor: allow NOR driver to write fewer bytes than ++ requested ++ ++The write size can be constrained by the maximum message/transfer size ++of the SPI controller. Only check for ret = 0 to avoid an infinite loop. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1377,7 +1377,7 @@ static int spi_nor_write(struct mtd_info ++ ++ write_enable(nor); ++ ret = nor->write(nor, addr, page_remain, buf + i); ++- if (ret < 0) +++ if (ret <= 0) ++ goto write_err; ++ written = ret; ++ ++@@ -1386,13 +1386,6 @@ static int spi_nor_write(struct mtd_info ++ goto write_err; ++ *retlen += written; ++ i += written; ++- if (written != page_remain) { ++- dev_err(nor->dev, ++- "While writing %zu bytes written %zd bytes\n", ++- page_remain, written); ++- ret = -EIO; ++- goto write_err; ++- } ++ } ++ ++ write_err: +diff --git a/target/linux/generic/pending-4.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch b/target/linux/generic/pending-4.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch +new file mode 100644 +index 0000000000..41f9d31cb0 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch +@@ -0,0 +1,25 @@ ++From: Felix Fietkau ++Subject: kernel: disable cfi cmdset 0002 erase suspend ++ ++on some platforms, erase suspend leads to data corruption and lockups when write ++ops collide with erase ops. this has been observed on the buffalo wzr-hp-g300nh. ++rather than play whack-a-mole with a hard to reproduce issue on a variety of devices, ++simply disable erase suspend, as it will usually not produce any useful gain on ++the small filesystems used on embedded hardware. ++ ++Signed-off-by: Felix Fietkau ++--- ++ drivers/mtd/chips/cfi_cmdset_0002.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/drivers/mtd/chips/cfi_cmdset_0002.c +++++ b/drivers/mtd/chips/cfi_cmdset_0002.c ++@@ -811,7 +811,7 @@ static int get_chip(struct map_info *map ++ return 0; ++ ++ case FL_ERASING: ++- if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) || +++ if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) || ++ !(mode == FL_READY || mode == FL_POINT || ++ (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) ++ goto sleep; +diff --git a/target/linux/generic/pending-4.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/target/linux/generic/pending-4.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch +new file mode 100644 +index 0000000000..932f219cf2 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch +@@ -0,0 +1,17 @@ ++From: George Kashperko ++Subject: Issue map read after Write Buffer Load command to ensure chip is ready to receive data. ++ ++Signed-off-by: George Kashperko ++--- ++ drivers/mtd/chips/cfi_cmdset_0002.c | 1 + ++ 1 file changed, 1 insertion(+) ++--- a/drivers/mtd/chips/cfi_cmdset_0002.c +++++ b/drivers/mtd/chips/cfi_cmdset_0002.c ++@@ -1839,6 +1839,7 @@ static int __xipram do_write_buffer(stru ++ ++ /* Write Buffer Load */ ++ map_write(map, CMD(0x25), cmd_adr); +++ (void) map_read(map, cmd_adr); ++ ++ chip->state = FL_WRITING_TO_BUFFER; ++ +diff --git a/target/linux/generic/pending-4.14/465-m25p80-mx-disable-software-protection.patch b/target/linux/generic/pending-4.14/465-m25p80-mx-disable-software-protection.patch +new file mode 100644 +index 0000000000..b41710276f +--- /dev/null ++++ b/target/linux/generic/pending-4.14/465-m25p80-mx-disable-software-protection.patch +@@ -0,0 +1,18 @@ ++From: Felix Fietkau ++Subject: Disable software protection bits for Macronix flashes. ++ ++Signed-off-by: Felix Fietkau ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -2714,6 +2714,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ ++ if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || ++ JEDEC_MFR(info) == SNOR_MFR_INTEL || +++ JEDEC_MFR(info) == SNOR_MFR_MACRONIX || ++ JEDEC_MFR(info) == SNOR_MFR_SST || ++ info->flags & SPI_NOR_HAS_LOCK) { ++ write_enable(nor); +diff --git a/target/linux/generic/pending-4.14/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch b/target/linux/generic/pending-4.14/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +new file mode 100644 +index 0000000000..55d9709761 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +@@ -0,0 +1,37 @@ ++From: Matthias Schiffer ++Date: Tue, 9 Jan 2018 20:41:48 +0100 ++Subject: [PATCH] Revert "mtd: spi-nor: fix Spansion regressions (aliased with ++ Winbond)" ++ ++This reverts commit 67b9bcd36906e12a15ffec19463afbbd6a41660e. ++ ++The underlying issue breaking Spansion flash has been fixed with "mtd: spi-nor: ++wait until lock/unlock operations are ready" and "mtd: spi-nor: wait for SR_WIP ++to clear on initial unlock", so we can support unlocking for Winbond flash ++again. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 4 +++- ++ 1 file changed, 3 insertions(+), 1 deletion(-) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -2716,6 +2716,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ JEDEC_MFR(info) == SNOR_MFR_INTEL || ++ JEDEC_MFR(info) == SNOR_MFR_MACRONIX || ++ JEDEC_MFR(info) == SNOR_MFR_SST || +++ JEDEC_MFR(info) == SNOR_MFR_WINBOND || ++ info->flags & SPI_NOR_HAS_LOCK) { ++ write_enable(nor); ++ write_sr(nor, 0); ++@@ -2734,7 +2735,8 @@ int spi_nor_scan(struct spi_nor *nor, co ++ ++ /* NOR protection support for STmicro/Micron chips and similar */ ++ if (JEDEC_MFR(info) == SNOR_MFR_MICRON || ++- info->flags & SPI_NOR_HAS_LOCK) { +++ JEDEC_MFR(info) == SNOR_MFR_WINBOND || +++ info->flags & SPI_NOR_HAS_LOCK) { ++ nor->flash_lock = stm_lock; ++ nor->flash_unlock = stm_unlock; ++ nor->flash_is_locked = stm_is_locked; +diff --git a/target/linux/generic/pending-4.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/target/linux/generic/pending-4.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch +new file mode 100644 +index 0000000000..0f4ea32688 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch +@@ -0,0 +1,56 @@ ++From: Felix Fietkau ++Date: Sat, 4 Nov 2017 07:40:23 +0100 ++Subject: [PATCH] mtd: spi-nor: support limiting 4K sectors support based on ++ flash size ++ ++Some devices need 4K sectors to be able to deal with small flash chips. ++For instance, w25x05 is 64 KiB in size, and without 4K sectors, the ++entire chip is just one erase block. ++On bigger flash chip sizes, using 4K sectors can significantly slow down ++many operations, including using a writable filesystem. There are several ++platforms where it makes sense to use a single kernel on both kinds of ++devices. ++ ++To support this properly, allow configuring an upper flash chip size ++limit for 4K sectors support. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/mtd/spi-nor/Kconfig +++++ b/drivers/mtd/spi-nor/Kconfig ++@@ -39,6 +39,17 @@ config SPI_ASPEED_SMC ++ and support for the SPI flash memory controller (SPI) for ++ the host firmware. The implementation only supports SPI NOR. ++ +++config MTD_SPI_NOR_USE_4K_SECTORS_LIMIT +++ int "Maximum flash chip size to use 4K sectors on (in KiB)" +++ depends on MTD_SPI_NOR_USE_4K_SECTORS +++ default "4096" +++ help +++ There are many flash chips that support 4K sectors, but are so large +++ that using them significantly slows down writing large amounts of +++ data or using a writable filesystem. +++ Any flash chip larger than the size specified in this option will +++ not use 4K sectors. +++ ++ config SPI_ATMEL_QUADSPI ++ tristate "Atmel Quad SPI Controller" ++ depends on ARCH_AT91 || (ARM && COMPILE_TEST && !ARCH_EBSA110) ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -2561,10 +2561,12 @@ static int spi_nor_select_erase(struct s ++ ++ #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS ++ /* prefer "small sector" erase if possible */ ++- if (info->flags & SECT_4K) { +++ if ((info->flags & SECT_4K) && (mtd->size <= +++ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT * 1024)) { ++ nor->erase_opcode = SPINOR_OP_BE_4K; ++ mtd->erasesize = 4096; ++- } else if (info->flags & SECT_4K_PMC) { +++ } else if ((info->flags & SECT_4K_PMC) && (mtd->size <= +++ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT * 1024)) { ++ nor->erase_opcode = SPINOR_OP_BE_4K_PMC; ++ mtd->erasesize = 4096; ++ } else +diff --git a/target/linux/generic/pending-4.14/475-mtd-spi-nor-Add-Winbond-w25q128jv-support.patch b/target/linux/generic/pending-4.14/475-mtd-spi-nor-Add-Winbond-w25q128jv-support.patch +new file mode 100644 +index 0000000000..f751bfd3b2 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/475-mtd-spi-nor-Add-Winbond-w25q128jv-support.patch +@@ -0,0 +1,34 @@ ++From: Robert Marko ++To: linux-mtd@lists.infradead.org ++Subject: mtd: spi-nor: Add Winbond w25q128jv support ++Date: Mon, 25 Jun 2018 13:17:48 +0200 ++ ++Datasheet: ++http://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf ++ ++Testing done on Mikrotik Routerboard wAP R board. ++It does not support Dual or Quad modes. ++ ++Signed-off-by: Robert Marko ++--- ++ ++Changes in v2: ++ - Correct the title ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 5 +++++ ++ 1 file changed, 5 insertions(+) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1165,6 +1165,11 @@ static const struct flash_info spi_nor_i ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, +++ { +++ "w25q128jv", INFO(0xef7018, 0, 64 * 1024, 256, +++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | +++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) +++ }, ++ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, ++ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, ++ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, +diff --git a/target/linux/generic/pending-4.14/476-mtd-spi-nor-add-eon-en25q128.patch b/target/linux/generic/pending-4.14/476-mtd-spi-nor-add-eon-en25q128.patch +new file mode 100644 +index 0000000000..ac1fda5159 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/476-mtd-spi-nor-add-eon-en25q128.patch +@@ -0,0 +1,18 @@ ++From: Piotr Dymacz ++Subject: kernel/mtd: add support for EON EN25Q128 ++ ++Signed-off-by: Piotr Dymacz ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -954,6 +954,7 @@ static const struct flash_info spi_nor_i ++ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, ++ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, ++ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, +++ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256, SECT_4K) }, ++ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, ++ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, ++ { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, +diff --git a/target/linux/generic/pending-4.14/477-mtd-add-spi-nor-add-mx25u3235f.patch b/target/linux/generic/pending-4.14/477-mtd-add-spi-nor-add-mx25u3235f.patch +new file mode 100644 +index 0000000000..2d94959c5c +--- /dev/null ++++ b/target/linux/generic/pending-4.14/477-mtd-add-spi-nor-add-mx25u3235f.patch +@@ -0,0 +1,18 @@ ++From: André Valentin ++Subject: linux/mtd: add id for mx25u3235f needed by ZyXEL NBG6817 ++ ++Signed-off-by: André Valentin ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1022,6 +1022,7 @@ static const struct flash_info spi_nor_i ++ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) }, ++ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, ++ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) }, +++ { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64, 0) }, ++ { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) }, ++ { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) }, ++ { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) }, +diff --git a/target/linux/generic/pending-4.14/478-mtd-spi-nor-Add-support-for-XM25QH64A-and-XM25QH128A.patch b/target/linux/generic/pending-4.14/478-mtd-spi-nor-Add-support-for-XM25QH64A-and-XM25QH128A.patch +new file mode 100644 +index 0000000000..4ecf53621d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/478-mtd-spi-nor-Add-support-for-XM25QH64A-and-XM25QH128A.patch +@@ -0,0 +1,30 @@ ++From b02f3405c935a28200db26b63e42086057565cf4 Mon Sep 17 00:00:00 2001 ++From: Hauke Mehrtens ++Date: Sat, 31 Mar 2018 20:09:54 +0200 ++Subject: [PATCH] mtd: spi-nor: Add support for XM25QH64A and XM25QH128A ++ ++These devices are produced by Wuhan Xinxin Semiconductor Manufacturing ++Corp. (XMC) and found on some routers from Chinese manufactures. ++ ++The data sheets can be found here: ++http://www.xmcwh.com/Uploads/2018-03-01/5a9799e4cb355.pdf ++http://www.xmcwh.com/Uploads/2018-02-05/5a77e6dbe968b.pdf ++ ++Signed-off-by: Hauke Mehrtens ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 4 ++++ ++ 1 file changed, 4 insertions(+) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1192,6 +1192,10 @@ static const struct flash_info spi_nor_i ++ { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) }, ++ { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) }, ++ { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) }, +++ +++ /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ +++ { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +++ { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { }, ++ }; ++ +diff --git a/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-eon-en25qh32.patch b/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-eon-en25qh32.patch +new file mode 100644 +index 0000000000..b8d5101514 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-eon-en25qh32.patch +@@ -0,0 +1,10 @@ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -955,6 +955,7 @@ static const struct flash_info spi_nor_i ++ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, ++ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256, SECT_4K) }, +++ { "en25qh32", INFO(0x1c7016, 0, 64 * 1024, 64, 0) }, ++ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, ++ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, ++ { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, +diff --git a/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-eon-en25qh64.patch b/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-eon-en25qh64.patch +new file mode 100644 +index 0000000000..c290a784d0 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-eon-en25qh64.patch +@@ -0,0 +1,10 @@ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -956,6 +956,7 @@ static const struct flash_info spi_nor_i ++ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256, SECT_4K) }, ++ { "en25qh32", INFO(0x1c7016, 0, 64 * 1024, 64, 0) }, +++ { "en25qh64", INFO(0x1c7017, 0, 64 * 1024, 128, 0) }, ++ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, ++ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, ++ { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, +diff --git a/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch +new file mode 100644 +index 0000000000..7545cf8427 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/479-mtd-spi-nor-add-xtx-xt25f128b.patch +@@ -0,0 +1,42 @@ ++From patchwork Thu Feb 6 17:19:41 2020 ++Content-Type: text/plain; charset="utf-8" ++MIME-Version: 1.0 ++Content-Transfer-Encoding: 7bit ++X-Patchwork-Submitter: Daniel Golle ++X-Patchwork-Id: 1234465 ++Date: Thu, 6 Feb 2020 19:19:41 +0200 ++From: Daniel Golle ++To: linux-mtd@lists.infradead.org ++Subject: [PATCH v2] mtd: spi-nor: Add support for xt25f128b chip ++Message-ID: <20200206171941.GA2398@makrotopia.org> ++MIME-Version: 1.0 ++Content-Disposition: inline ++List-Subscribe: , ++ ++Cc: Eitan Cohen , Piotr Dymacz , ++ Tudor Ambarus ++Sender: "linux-mtd" ++Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org ++ ++Add XT25F128B made by XTX Technology (Shenzhen) Limited. ++This chip supports dual and quad read and uniform 4K-byte erase. ++Verified on Teltonika RUT955 which comes with XT25F128B in recent ++versions of the device. ++ ++Signed-off-by: Daniel Golle ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 4 ++++ ++ 1 file changed, 4 insertions(+) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1198,6 +1198,9 @@ static const struct flash_info spi_nor_i ++ /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ ++ { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +++ +++ /* XTX Technology (Shenzhen) Limited */ +++ { "xt25f128b", INFO(0x0B4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { }, ++ }; ++ +diff --git a/target/linux/generic/pending-4.14/480-mtd-set-rootfs-to-be-root-dev.patch b/target/linux/generic/pending-4.14/480-mtd-set-rootfs-to-be-root-dev.patch +new file mode 100644 +index 0000000000..6cddaf01b7 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/480-mtd-set-rootfs-to-be-root-dev.patch +@@ -0,0 +1,38 @@ ++From: Gabor Juhos ++Subject: kernel/3.1[02]: move MTD root device setup code to mtdcore ++ ++The current code only allows to automatically set ++root device on MTD partitions. Move the code to MTD ++core to allow to use it with all MTD devices. ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/mtd/mtdcore.c | 10 ++++++++++ ++ 1 file changed, 10 insertions(+) ++ ++--- a/drivers/mtd/mtdcore.c +++++ b/drivers/mtd/mtdcore.c ++@@ -41,6 +41,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include ++ #include ++@@ -578,6 +579,15 @@ int add_mtd_device(struct mtd_info *mtd) ++ of this try_ nonsense, and no bitching about it ++ either. :) */ ++ __module_get(THIS_MODULE); +++ +++ if (!strcmp(mtd->name, "rootfs") && +++ IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && +++ ROOT_DEV == 0) { +++ pr_notice("mtd: device %d (%s) set to be root filesystem\n", +++ mtd->index, mtd->name); +++ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); +++ } +++ ++ return 0; ++ ++ fail_added: +diff --git a/target/linux/generic/pending-4.14/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch b/target/linux/generic/pending-4.14/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch +new file mode 100644 +index 0000000000..4e632b05a0 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/481-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch +@@ -0,0 +1,24 @@ ++From d68b4aa22e8c625685bfad642dd7337948dc0ad1 Mon Sep 17 00:00:00 2001 ++From: Koen Vandeputte ++Date: Mon, 6 Jan 2020 13:07:56 +0100 ++Subject: [PATCH] mtd: spi-nor: add support for Gigadevice GD25D05 ++ ++Signed-off-by: Koen Vandeputte ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 5 +++++ ++ 1 file changed, 5 insertions(+) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -976,6 +976,11 @@ static const struct flash_info spi_nor_i ++ ++ /* GigaDevice */ ++ { +++ "gd25d05", INFO(0xc84010, 0, 64 * 1024, 1, +++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | +++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) +++ }, +++ { ++ "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) +diff --git a/target/linux/generic/pending-4.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/target/linux/generic/pending-4.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch +new file mode 100644 +index 0000000000..992aa4662e +--- /dev/null ++++ b/target/linux/generic/pending-4.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch +@@ -0,0 +1,97 @@ ++From: Daniel Golle ++Subject: ubi: auto-attach mtd device named "ubi" or "data" on boot ++ ++Signed-off-by: Daniel Golle ++--- ++ drivers/mtd/ubi/build.c | 36 ++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 36 insertions(+) ++ ++--- a/drivers/mtd/ubi/build.c +++++ b/drivers/mtd/ubi/build.c ++@@ -1172,6 +1172,73 @@ static struct mtd_info * __init open_mtd ++ return mtd; ++ } ++ +++/* +++ * This function tries attaching mtd partitions named either "ubi" or "data" +++ * during boot. +++ */ +++static void __init ubi_auto_attach(void) +++{ +++ int err; +++ struct mtd_info *mtd; +++ loff_t offset = 0; +++ size_t len; +++ char magic[4]; +++ +++ /* try attaching mtd device named "ubi" or "data" */ +++ mtd = open_mtd_device("ubi"); +++ if (IS_ERR(mtd)) +++ mtd = open_mtd_device("data"); +++ +++ if (IS_ERR(mtd)) +++ return; +++ +++ /* get the first not bad block */ +++ if (mtd_can_have_bb(mtd)) +++ while (mtd_block_isbad(mtd, offset)) { +++ offset += mtd->erasesize; +++ +++ if (offset > mtd->size) { +++ pr_err("UBI error: Failed to find a non-bad " +++ "block on mtd%d\n", mtd->index); +++ goto cleanup; +++ } +++ } +++ +++ /* check if the read from flash was successful */ +++ err = mtd_read(mtd, offset, 4, &len, (void *) magic); +++ if ((err && !mtd_is_bitflip(err)) || len != 4) { +++ pr_err("UBI error: unable to read from mtd%d\n", mtd->index); +++ goto cleanup; +++ } +++ +++ /* check for a valid ubi magic */ +++ if (strncmp(magic, "UBI#", 4)) { +++ pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index); +++ goto cleanup; +++ } +++ +++ /* don't auto-add media types where UBI doesn't makes sense */ +++ if (mtd->type != MTD_NANDFLASH && +++ mtd->type != MTD_NORFLASH && +++ mtd->type != MTD_DATAFLASH && +++ mtd->type != MTD_MLCNANDFLASH) +++ goto cleanup; +++ +++ mutex_lock(&ubi_devices_mutex); +++ pr_notice("UBI: auto-attach mtd%d\n", mtd->index); +++ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0); +++ mutex_unlock(&ubi_devices_mutex); +++ if (err < 0) { +++ pr_err("UBI error: cannot attach mtd%d\n", mtd->index); +++ goto cleanup; +++ } +++ +++ return; +++ +++cleanup: +++ put_mtd_device(mtd); +++} +++ ++ static int __init ubi_init(void) ++ { ++ int err, i, k; ++@@ -1255,6 +1322,12 @@ static int __init ubi_init(void) ++ } ++ } ++ +++ /* auto-attach mtd devices only if built-in to the kernel and no ubi.mtd +++ * parameter was given */ +++ if (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && +++ !ubi_is_module() && !mtd_devs) +++ ubi_auto_attach(); +++ ++ err = ubiblock_init(); ++ if (err) { ++ pr_err("UBI error: block: cannot initialize, error %d\n", err); +diff --git a/target/linux/generic/pending-4.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/target/linux/generic/pending-4.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch +new file mode 100644 +index 0000000000..cb2d525610 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch +@@ -0,0 +1,66 @@ ++From: Daniel Golle ++Subject: ubi: auto-create ubiblock device for rootfs ++ ++Signed-off-by: Daniel Golle ++--- ++ drivers/mtd/ubi/block.c | 42 ++++++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 42 insertions(+) ++ ++--- a/drivers/mtd/ubi/block.c +++++ b/drivers/mtd/ubi/block.c ++@@ -633,6 +633,44 @@ static void __init ubiblock_create_from_ ++ } ++ } ++ +++#define UBIFS_NODE_MAGIC 0x06101831 +++static inline int ubi_vol_is_ubifs(struct ubi_volume_desc *desc) +++{ +++ int ret; +++ uint32_t magic_of, magic; +++ ret = ubi_read(desc, 0, (char *)&magic_of, 0, 4); +++ if (ret) +++ return 0; +++ magic = le32_to_cpu(magic_of); +++ return magic == UBIFS_NODE_MAGIC; +++} +++ +++static void __init ubiblock_create_auto_rootfs(void) +++{ +++ int ubi_num, ret, is_ubifs; +++ struct ubi_volume_desc *desc; +++ struct ubi_volume_info vi; +++ +++ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) { +++ desc = ubi_open_volume_nm(ubi_num, "rootfs", UBI_READONLY); +++ if (IS_ERR(desc)) +++ continue; +++ +++ ubi_get_volume_info(desc, &vi); +++ is_ubifs = ubi_vol_is_ubifs(desc); +++ ubi_close_volume(desc); +++ if (is_ubifs) +++ break; +++ +++ ret = ubiblock_create(&vi); +++ if (ret) +++ pr_err("UBI error: block: can't add '%s' volume, err=%d\n", +++ vi.name, ret); +++ /* always break if we get here */ +++ break; +++ } +++} +++ ++ static void ubiblock_remove_all(void) ++ { ++ struct ubiblock *next; ++@@ -665,6 +703,10 @@ int __init ubiblock_init(void) ++ */ ++ ubiblock_create_from_param(); ++ +++ /* auto-attach "rootfs" volume if existing and non-ubifs */ +++ if (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV)) +++ ubiblock_create_auto_rootfs(); +++ ++ /* ++ * Block devices are only created upon user requests, so we ignore ++ * existing volumes. +diff --git a/target/linux/generic/pending-4.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/target/linux/generic/pending-4.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch +new file mode 100644 +index 0000000000..3c82a064eb +--- /dev/null ++++ b/target/linux/generic/pending-4.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch +@@ -0,0 +1,51 @@ ++From: Daniel Golle ++Subject: try auto-mounting ubi0:rootfs in init/do_mounts.c ++ ++Signed-off-by: Daniel Golle ++--- ++ init/do_mounts.c | 26 +++++++++++++++++++++++++- ++ 1 file changed, 25 insertions(+), 1 deletion(-) ++ ++--- a/init/do_mounts.c +++++ b/init/do_mounts.c ++@@ -437,7 +437,28 @@ retry: ++ out: ++ put_page(page); ++ } ++- +++ +++static int __init mount_ubi_rootfs(void) +++{ +++ int flags = MS_SILENT; +++ int err, tried = 0; +++ +++ while (tried < 2) { +++ err = do_mount_root("ubi0:rootfs", "ubifs", flags, \ +++ root_mount_data); +++ switch (err) { +++ case -EACCES: +++ flags |= MS_RDONLY; +++ tried++; +++ break; +++ default: +++ return err; +++ } +++ } +++ +++ return -EINVAL; +++} +++ ++ #ifdef CONFIG_ROOT_NFS ++ ++ #define NFSROOT_TIMEOUT_MIN 5 ++@@ -531,6 +552,10 @@ void __init mount_root(void) ++ change_floppy("root floppy"); ++ } ++ #endif +++#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV +++ if (!mount_ubi_rootfs()) +++ return; +++#endif ++ #ifdef CONFIG_BLOCK ++ { ++ int err = create_dev("/dev/root", ROOT_DEV); +diff --git a/target/linux/generic/pending-4.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/target/linux/generic/pending-4.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch +new file mode 100644 +index 0000000000..1bb53ada7f +--- /dev/null ++++ b/target/linux/generic/pending-4.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch +@@ -0,0 +1,34 @@ ++From: Daniel Golle ++Subject: ubi: set ROOT_DEV to ubiblock "rootfs" if unset ++ ++Signed-off-by: Daniel Golle ++--- ++ drivers/mtd/ubi/block.c | 10 ++++++++++ ++ 1 file changed, 10 insertions(+) ++ ++--- a/drivers/mtd/ubi/block.c +++++ b/drivers/mtd/ubi/block.c ++@@ -50,6 +50,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "ubi-media.h" ++ #include "ubi.h" ++@@ -445,6 +446,15 @@ int ubiblock_create(struct ubi_volume_in ++ dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", ++ dev->ubi_num, dev->vol_id, vi->name); ++ mutex_unlock(&devices_mutex); +++ +++ if (!strcmp(vi->name, "rootfs") && +++ IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && +++ ROOT_DEV == 0) { +++ pr_notice("ubiblock: device ubiblock%d_%d (%s) set to be root filesystem\n", +++ dev->ubi_num, dev->vol_id, vi->name); +++ ROOT_DEV = MKDEV(gd->major, gd->first_minor); +++ } +++ ++ return 0; ++ ++ out_free_queue: +diff --git a/target/linux/generic/pending-4.14/494-mtd-ubi-add-EOF-marker-support.patch b/target/linux/generic/pending-4.14/494-mtd-ubi-add-EOF-marker-support.patch +new file mode 100644 +index 0000000000..a3b58dd66f +--- /dev/null ++++ b/target/linux/generic/pending-4.14/494-mtd-ubi-add-EOF-marker-support.patch +@@ -0,0 +1,60 @@ ++From: Gabor Juhos ++Subject: mtd: add EOF marker support to the UBI layer ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/mtd/ubi/attach.c | 25 ++++++++++++++++++++++--- ++ drivers/mtd/ubi/ubi.h | 1 + ++ 2 files changed, 23 insertions(+), 3 deletions(-) ++ ++--- a/drivers/mtd/ubi/attach.c +++++ b/drivers/mtd/ubi/attach.c ++@@ -939,6 +939,13 @@ static bool vol_ignored(int vol_id) ++ #endif ++ } ++ +++static bool ec_hdr_has_eof(struct ubi_ec_hdr *ech) +++{ +++ return ech->padding1[0] == 'E' && +++ ech->padding1[1] == 'O' && +++ ech->padding1[2] == 'F'; +++} +++ ++ /** ++ * scan_peb - scan and process UBI headers of a PEB. ++ * @ubi: UBI device description object ++@@ -971,9 +978,21 @@ static int scan_peb(struct ubi_device *u ++ return 0; ++ } ++ ++- err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); ++- if (err < 0) ++- return err; +++ if (!ai->eof_found) { +++ err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); +++ if (err < 0) +++ return err; +++ +++ if (ec_hdr_has_eof(ech)) { +++ pr_notice("UBI: EOF marker found, PEBs from %d will be erased\n", +++ pnum); +++ ai->eof_found = true; +++ } +++ } +++ +++ if (ai->eof_found) +++ err = UBI_IO_FF_BITFLIPS; +++ ++ switch (err) { ++ case 0: ++ break; ++--- a/drivers/mtd/ubi/ubi.h +++++ b/drivers/mtd/ubi/ubi.h ++@@ -785,6 +785,7 @@ struct ubi_attach_info { ++ int mean_ec; ++ uint64_t ec_sum; ++ int ec_count; +++ bool eof_found; ++ struct kmem_cache *aeb_slab_cache; ++ struct ubi_ec_hdr *ech; ++ struct ubi_vid_io_buf *vidb; +diff --git a/target/linux/generic/pending-4.14/495-mtd-core-add-get_mtd_device_by_node.patch b/target/linux/generic/pending-4.14/495-mtd-core-add-get_mtd_device_by_node.patch +new file mode 100644 +index 0000000000..2886742d4d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/495-mtd-core-add-get_mtd_device_by_node.patch +@@ -0,0 +1,75 @@ ++From 1bd1b740f208d1cf4071932cc51860d37266c402 Mon Sep 17 00:00:00 2001 ++From: Bernhard Frauendienst ++Date: Sat, 1 Sep 2018 00:30:11 +0200 ++Subject: [PATCH 495/497] mtd: core: add get_mtd_device_by_node ++ ++Add function to retrieve a mtd device by its OF node. Since drivers can ++assign arbitrary names to mtd devices in the absence of a label ++property, there is no other reliable way to retrieve a mtd device for a ++given OF node. ++ ++Signed-off-by: Bernhard Frauendienst ++Reviewed-by: Miquel Raynal ++--- ++ drivers/mtd/mtdcore.c | 38 ++++++++++++++++++++++++++++++++++++++ ++ include/linux/mtd/mtd.h | 2 ++ ++ 2 files changed, 40 insertions(+) ++ ++--- a/drivers/mtd/mtdcore.c +++++ b/drivers/mtd/mtdcore.c ++@@ -924,6 +924,44 @@ out_unlock: ++ } ++ EXPORT_SYMBOL_GPL(get_mtd_device_nm); ++ +++/** +++ * get_mtd_device_by_node - obtain a validated handle for an MTD device +++ * by of_node +++ * @of_node: OF node of MTD device to open +++ * +++ * This function returns MTD device description structure in case of +++ * success and an error code in case of failure. +++ */ +++struct mtd_info *get_mtd_device_by_node(const struct device_node *of_node) +++{ +++ int err = -ENODEV; +++ struct mtd_info *mtd = NULL, *other; +++ +++ mutex_lock(&mtd_table_mutex); +++ +++ mtd_for_each_device(other) { +++ if (of_node == other->dev.of_node) { +++ mtd = other; +++ break; +++ } +++ } +++ +++ if (!mtd) +++ goto out_unlock; +++ +++ err = __get_mtd_device(mtd); +++ if (err) +++ goto out_unlock; +++ +++ mutex_unlock(&mtd_table_mutex); +++ return mtd; +++ +++out_unlock: +++ mutex_unlock(&mtd_table_mutex); +++ return ERR_PTR(err); +++} +++EXPORT_SYMBOL_GPL(get_mtd_device_by_node); +++ ++ void put_mtd_device(struct mtd_info *mtd) ++ { ++ mutex_lock(&mtd_table_mutex); ++--- a/include/linux/mtd/mtd.h +++++ b/include/linux/mtd/mtd.h ++@@ -580,6 +580,8 @@ extern struct mtd_info *get_mtd_device(s ++ extern int __get_mtd_device(struct mtd_info *mtd); ++ extern void __put_mtd_device(struct mtd_info *mtd); ++ extern struct mtd_info *get_mtd_device_nm(const char *name); +++extern struct mtd_info *get_mtd_device_by_node( +++ const struct device_node *of_node); ++ extern void put_mtd_device(struct mtd_info *mtd); ++ ++ +diff --git a/target/linux/generic/pending-4.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch b/target/linux/generic/pending-4.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch +new file mode 100644 +index 0000000000..01f3b9ec2d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch +@@ -0,0 +1,52 @@ ++From 5734c6669fba7ddb5ef491ccff7159d15dba0b59 Mon Sep 17 00:00:00 2001 ++From: Bernhard Frauendienst ++Date: Wed, 5 Sep 2018 01:32:51 +0200 ++Subject: [PATCH 496/497] dt-bindings: add bindings for mtd-concat devices ++ ++Document virtual mtd-concat device bindings. ++ ++Signed-off-by: Bernhard Frauendienst ++--- ++ .../devicetree/bindings/mtd/mtd-concat.txt | 36 +++++++++++++++++++ ++ 1 file changed, 36 insertions(+) ++ create mode 100644 Documentation/devicetree/bindings/mtd/mtd-concat.txt ++ ++--- /dev/null +++++ b/Documentation/devicetree/bindings/mtd/mtd-concat.txt ++@@ -0,0 +1,36 @@ +++Virtual MTD concat device +++ +++Requires properties: +++- devices: list of phandles to mtd nodes that should be concatenated +++ +++Example: +++ +++&spi { +++ flash0: flash@0 { +++ ... +++ }; +++ flash1: flash@1 { +++ ... +++ }; +++}; +++ +++flash { +++ compatible = "mtd-concat"; +++ +++ devices = <&flash0 &flash1>; +++ +++ partitions { +++ compatible = "fixed-partitions"; +++ +++ partition@0 { +++ label = "boot"; +++ reg = <0x0000000 0x0040000>; +++ read-only; +++ }; +++ +++ partition@40000 { +++ label = "firmware"; +++ reg = <0x0040000 0x1fc0000>; +++ }; +++ } +++} +diff --git a/target/linux/generic/pending-4.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/target/linux/generic/pending-4.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch +new file mode 100644 +index 0000000000..94acc883f3 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch +@@ -0,0 +1,216 @@ ++From e53f712d8eac71f54399b61038ccf87d2cee99d7 Mon Sep 17 00:00:00 2001 ++From: Bernhard Frauendienst ++Date: Sat, 25 Aug 2018 12:35:22 +0200 ++Subject: [PATCH 497/497] mtd: mtdconcat: add dt driver for concat devices ++ ++Some mtd drivers like physmap variants have support for concatenating ++multiple mtd devices, but there is no generic way to define such a ++concat device from within the device tree. ++ ++This is useful for some SoC boards that use multiple flash chips as ++memory banks of a single mtd device, with partitions spanning chip ++borders. ++ ++This commit adds a driver for creating virtual mtd-concat devices. They ++must have a compatible = "mtd-concat" line, and define a list of devices ++to concat in the 'devices' property, for example: ++ ++flash { ++ compatible = "mtd-concat"; ++ ++ devices = <&flash0 &flash1>; ++ ++ partitions { ++ ... ++ }; ++}; ++ ++The driver is added to the very end of the mtd Makefile to increase the ++likelyhood of all child devices already being loaded at the time of ++probing, preventing unnecessary deferred probes. ++ ++Signed-off-by: Bernhard Frauendienst ++--- ++ drivers/mtd/Kconfig | 2 + ++ drivers/mtd/Makefile | 3 + ++ drivers/mtd/composite/Kconfig | 12 +++ ++ drivers/mtd/composite/Makefile | 6 ++ ++ drivers/mtd/composite/virt_concat.c | 128 ++++++++++++++++++++++++++++ ++ 5 files changed, 151 insertions(+) ++ create mode 100644 drivers/mtd/composite/Kconfig ++ create mode 100644 drivers/mtd/composite/Makefile ++ create mode 100644 drivers/mtd/composite/virt_concat.c ++ ++--- a/drivers/mtd/Kconfig +++++ b/drivers/mtd/Kconfig ++@@ -377,4 +377,6 @@ source "drivers/mtd/spi-nor/Kconfig" ++ ++ source "drivers/mtd/ubi/Kconfig" ++ +++source "drivers/mtd/composite/Kconfig" +++ ++ endif # MTD ++--- a/drivers/mtd/Makefile +++++ b/drivers/mtd/Makefile ++@@ -39,3 +39,6 @@ obj-y += chips/ lpddr/ maps/ devices/ n ++ ++ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ ++ obj-$(CONFIG_MTD_UBI) += ubi/ +++ +++# Composite drivers must be loaded last +++obj-y += composite/ ++--- /dev/null +++++ b/drivers/mtd/composite/Kconfig ++@@ -0,0 +1,12 @@ +++menu "Composite MTD device drivers" +++ depends on MTD!=n +++ +++config MTD_VIRT_CONCAT +++ tristate "Virtual concat MTD device" +++ help +++ This driver allows creation of a virtual MTD concat device, which +++ concatenates multiple underlying MTD devices to a single device. +++ This is required by some SoC boards where multiple memory banks are +++ used as one device with partitions spanning across device boundaries. +++ +++endmenu ++--- /dev/null +++++ b/drivers/mtd/composite/Makefile ++@@ -0,0 +1,6 @@ +++# SPDX-License-Identifier: GPL-2.0 +++# +++# linux/drivers/mtd/composite/Makefile +++# +++ +++obj-$(CONFIG_MTD_VIRT_CONCAT) += virt_concat.o ++--- /dev/null +++++ b/drivers/mtd/composite/virt_concat.c ++@@ -0,0 +1,128 @@ +++// SPDX-License-Identifier: GPL-2.0+ +++/* +++ * Virtual concat MTD device driver +++ * +++ * Copyright (C) 2018 Bernhard Frauendienst +++ * Author: Bernhard Frauendienst, kernel@nospam.obeliks.de +++ */ +++ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++/* +++ * struct of_virt_concat - platform device driver data. +++ * @cmtd the final mtd_concat device +++ * @num_devices the number of devices in @devices +++ * @devices points to an array of devices already loaded +++ */ +++struct of_virt_concat { +++ struct mtd_info *cmtd; +++ int num_devices; +++ struct mtd_info **devices; +++}; +++ +++static int virt_concat_remove(struct platform_device *pdev) +++{ +++ struct of_virt_concat *info; +++ int i; +++ +++ info = platform_get_drvdata(pdev); +++ if (!info) +++ return 0; +++ +++ // unset data for when this is called after a probe error +++ platform_set_drvdata(pdev, NULL); +++ +++ if (info->cmtd) { +++ mtd_device_unregister(info->cmtd); +++ mtd_concat_destroy(info->cmtd); +++ } +++ +++ if (info->devices) { +++ for (i = 0; i < info->num_devices; i++) +++ put_mtd_device(info->devices[i]); +++ } +++ +++ return 0; +++} +++ +++static int virt_concat_probe(struct platform_device *pdev) +++{ +++ struct device_node *node = pdev->dev.of_node; +++ struct of_phandle_iterator it; +++ struct of_virt_concat *info; +++ struct mtd_info *mtd; +++ int err = 0, count; +++ +++ count = of_count_phandle_with_args(node, "devices", NULL); +++ if (count <= 0) +++ return -EINVAL; +++ +++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); +++ if (!info) +++ return -ENOMEM; +++ info->devices = devm_kcalloc(&pdev->dev, count, +++ sizeof(*(info->devices)), GFP_KERNEL); +++ if (!info->devices) { +++ err = -ENOMEM; +++ goto err_remove; +++ } +++ +++ platform_set_drvdata(pdev, info); +++ +++ of_for_each_phandle(&it, err, node, "devices", NULL, 0) { +++ mtd = get_mtd_device_by_node(it.node); +++ if (IS_ERR(mtd)) { +++ of_node_put(it.node); +++ err = -EPROBE_DEFER; +++ goto err_remove; +++ } +++ +++ info->devices[info->num_devices++] = mtd; +++ } +++ +++ info->cmtd = mtd_concat_create(info->devices, info->num_devices, +++ dev_name(&pdev->dev)); +++ if (!info->cmtd) { +++ err = -ENXIO; +++ goto err_remove; +++ } +++ +++ info->cmtd->dev.parent = &pdev->dev; +++ mtd_set_of_node(info->cmtd, node); +++ mtd_device_register(info->cmtd, NULL, 0); +++ +++ return 0; +++ +++err_remove: +++ virt_concat_remove(pdev); +++ +++ return err; +++} +++ +++static const struct of_device_id virt_concat_of_match[] = { +++ { .compatible = "mtd-concat", }, +++ { /* sentinel */ } +++}; +++MODULE_DEVICE_TABLE(of, virt_concat_of_match); +++ +++static struct platform_driver virt_concat_driver = { +++ .probe = virt_concat_probe, +++ .remove = virt_concat_remove, +++ .driver = { +++ .name = "virt-mtdconcat", +++ .of_match_table = virt_concat_of_match, +++ }, +++}; +++ +++module_platform_driver(virt_concat_driver); +++ +++MODULE_LICENSE("GPL v2"); +++MODULE_AUTHOR("Bernhard Frauendienst "); +++MODULE_DESCRIPTION("Virtual concat MTD device driver"); +diff --git a/target/linux/generic/pending-4.14/530-jffs2_make_lzma_available.patch b/target/linux/generic/pending-4.14/530-jffs2_make_lzma_available.patch +new file mode 100644 +index 0000000000..e74a6a11ed +--- /dev/null ++++ b/target/linux/generic/pending-4.14/530-jffs2_make_lzma_available.patch +@@ -0,0 +1,5180 @@ ++From: Alexandros C. Couloumbis ++Subject: fs: add jffs2/lzma support (not activated by default yet) ++ ++lede-commit: c2c88d315fa0e881f8b19da07b62859b915b11b2 ++Signed-off-by: Alexandros C. Couloumbis ++--- ++ fs/jffs2/Kconfig | 9 + ++ fs/jffs2/Makefile | 3 + ++ fs/jffs2/compr.c | 6 + ++ fs/jffs2/compr.h | 10 +- ++ fs/jffs2/compr_lzma.c | 128 +++ ++ fs/jffs2/super.c | 33 +- ++ include/linux/lzma.h | 62 ++ ++ include/linux/lzma/LzFind.h | 115 +++ ++ include/linux/lzma/LzHash.h | 54 + ++ include/linux/lzma/LzmaDec.h | 231 +++++ ++ include/linux/lzma/LzmaEnc.h | 80 ++ ++ include/linux/lzma/Types.h | 226 +++++ ++ include/uapi/linux/jffs2.h | 1 + ++ lib/Kconfig | 6 + ++ lib/Makefile | 12 + ++ lib/lzma/LzFind.c | 761 ++++++++++++++ ++ lib/lzma/LzmaDec.c | 999 +++++++++++++++++++ ++ lib/lzma/LzmaEnc.c | 2271 ++++++++++++++++++++++++++++++++++++++++++ ++ lib/lzma/Makefile | 7 + ++ 19 files changed, 5008 insertions(+), 6 deletions(-) ++ create mode 100644 fs/jffs2/compr_lzma.c ++ create mode 100644 include/linux/lzma.h ++ create mode 100644 include/linux/lzma/LzFind.h ++ create mode 100644 include/linux/lzma/LzHash.h ++ create mode 100644 include/linux/lzma/LzmaDec.h ++ create mode 100644 include/linux/lzma/LzmaEnc.h ++ create mode 100644 include/linux/lzma/Types.h ++ create mode 100644 lib/lzma/LzFind.c ++ create mode 100644 lib/lzma/LzmaDec.c ++ create mode 100644 lib/lzma/LzmaEnc.c ++ create mode 100644 lib/lzma/Makefile ++ ++--- a/fs/jffs2/Kconfig +++++ b/fs/jffs2/Kconfig ++@@ -139,6 +139,15 @@ config JFFS2_LZO ++ This feature was added in July, 2007. Say 'N' if you need ++ compatibility with older bootloaders or kernels. ++ +++config JFFS2_LZMA +++ bool "JFFS2 LZMA compression support" if JFFS2_COMPRESSION_OPTIONS +++ select LZMA_COMPRESS +++ select LZMA_DECOMPRESS +++ depends on JFFS2_FS +++ default n +++ help +++ JFFS2 wrapper to the LZMA C SDK +++ ++ config JFFS2_RTIME ++ bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS ++ depends on JFFS2_FS ++--- a/fs/jffs2/Makefile +++++ b/fs/jffs2/Makefile ++@@ -19,4 +19,7 @@ jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rub ++ jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o ++ jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o ++ jffs2-$(CONFIG_JFFS2_LZO) += compr_lzo.o +++jffs2-$(CONFIG_JFFS2_LZMA) += compr_lzma.o ++ jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o +++ +++CFLAGS_compr_lzma.o += -Iinclude/linux -Ilib/lzma ++--- a/fs/jffs2/compr.c +++++ b/fs/jffs2/compr.c ++@@ -378,6 +378,9 @@ int __init jffs2_compressors_init(void) ++ #ifdef CONFIG_JFFS2_LZO ++ jffs2_lzo_init(); ++ #endif +++#ifdef CONFIG_JFFS2_LZMA +++ jffs2_lzma_init(); +++#endif ++ /* Setting default compression mode */ ++ #ifdef CONFIG_JFFS2_CMODE_NONE ++ jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; ++@@ -401,6 +404,9 @@ int __init jffs2_compressors_init(void) ++ int jffs2_compressors_exit(void) ++ { ++ /* Unregistering compressors */ +++#ifdef CONFIG_JFFS2_LZMA +++ jffs2_lzma_exit(); +++#endif ++ #ifdef CONFIG_JFFS2_LZO ++ jffs2_lzo_exit(); ++ #endif ++--- a/fs/jffs2/compr.h +++++ b/fs/jffs2/compr.h ++@@ -29,9 +29,9 @@ ++ #define JFFS2_DYNRUBIN_PRIORITY 20 ++ #define JFFS2_LZARI_PRIORITY 30 ++ #define JFFS2_RTIME_PRIORITY 50 ++-#define JFFS2_ZLIB_PRIORITY 60 ++-#define JFFS2_LZO_PRIORITY 80 ++- +++#define JFFS2_LZMA_PRIORITY 70 +++#define JFFS2_ZLIB_PRIORITY 80 +++#define JFFS2_LZO_PRIORITY 90 ++ ++ #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */ ++ #define JFFS2_DYNRUBIN_DISABLED /* for decompression */ ++@@ -101,5 +101,9 @@ void jffs2_zlib_exit(void); ++ int jffs2_lzo_init(void); ++ void jffs2_lzo_exit(void); ++ #endif +++#ifdef CONFIG_JFFS2_LZMA +++int jffs2_lzma_init(void); +++void jffs2_lzma_exit(void); +++#endif ++ ++ #endif /* __JFFS2_COMPR_H__ */ ++--- /dev/null +++++ b/fs/jffs2/compr_lzma.c ++@@ -0,0 +1,128 @@ +++/* +++ * JFFS2 -- Journalling Flash File System, Version 2. +++ * +++ * For licensing information, see the file 'LICENCE' in this directory. +++ * +++ * JFFS2 wrapper to the LZMA C SDK +++ * +++ */ +++ +++#include +++#include "compr.h" +++ +++#ifdef __KERNEL__ +++ static DEFINE_MUTEX(deflate_mutex); +++#endif +++ +++CLzmaEncHandle *p; +++Byte propsEncoded[LZMA_PROPS_SIZE]; +++SizeT propsSize = sizeof(propsEncoded); +++ +++STATIC void lzma_free_workspace(void) +++{ +++ LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc); +++} +++ +++STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props) +++{ +++ if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL) +++ { +++ PRINT_ERROR("Failed to allocate lzma deflate workspace\n"); +++ return -ENOMEM; +++ } +++ +++ if (LzmaEnc_SetProps(p, props) != SZ_OK) +++ { +++ lzma_free_workspace(); +++ return -1; +++ } +++ +++ if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK) +++ { +++ lzma_free_workspace(); +++ return -1; +++ } +++ +++ return 0; +++} +++ +++STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out, +++ uint32_t *sourcelen, uint32_t *dstlen) +++{ +++ SizeT compress_size = (SizeT)(*dstlen); +++ int ret; +++ +++ #ifdef __KERNEL__ +++ mutex_lock(&deflate_mutex); +++ #endif +++ +++ ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen, +++ 0, NULL, &lzma_alloc, &lzma_alloc); +++ +++ #ifdef __KERNEL__ +++ mutex_unlock(&deflate_mutex); +++ #endif +++ +++ if (ret != SZ_OK) +++ return -1; +++ +++ *dstlen = (uint32_t)compress_size; +++ +++ return 0; +++} +++ +++STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out, +++ uint32_t srclen, uint32_t destlen) +++{ +++ int ret; +++ SizeT dl = (SizeT)destlen; +++ SizeT sl = (SizeT)srclen; +++ ELzmaStatus status; +++ +++ ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded, +++ propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc); +++ +++ if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen) +++ return -1; +++ +++ return 0; +++} +++ +++static struct jffs2_compressor jffs2_lzma_comp = { +++ .priority = JFFS2_LZMA_PRIORITY, +++ .name = "lzma", +++ .compr = JFFS2_COMPR_LZMA, +++ .compress = &jffs2_lzma_compress, +++ .decompress = &jffs2_lzma_decompress, +++ .disabled = 0, +++}; +++ +++int INIT jffs2_lzma_init(void) +++{ +++ int ret; +++ CLzmaEncProps props; +++ LzmaEncProps_Init(&props); +++ +++ props.dictSize = LZMA_BEST_DICT(0x2000); +++ props.level = LZMA_BEST_LEVEL; +++ props.lc = LZMA_BEST_LC; +++ props.lp = LZMA_BEST_LP; +++ props.pb = LZMA_BEST_PB; +++ props.fb = LZMA_BEST_FB; +++ +++ ret = lzma_alloc_workspace(&props); +++ if (ret < 0) +++ return ret; +++ +++ ret = jffs2_register_compressor(&jffs2_lzma_comp); +++ if (ret) +++ lzma_free_workspace(); +++ +++ return ret; +++} +++ +++void jffs2_lzma_exit(void) +++{ +++ jffs2_unregister_compressor(&jffs2_lzma_comp); +++ lzma_free_workspace(); +++} ++--- a/fs/jffs2/super.c +++++ b/fs/jffs2/super.c ++@@ -374,14 +374,41 @@ static int __init init_jffs2_fs(void) ++ BUILD_BUG_ON(sizeof(struct jffs2_raw_inode) != 68); ++ BUILD_BUG_ON(sizeof(struct jffs2_raw_summary) != 32); ++ ++- pr_info("version 2.2." +++ pr_info("version 2.2" ++ #ifdef CONFIG_JFFS2_FS_WRITEBUFFER ++ " (NAND)" ++ #endif ++ #ifdef CONFIG_JFFS2_SUMMARY ++- " (SUMMARY) " +++ " (SUMMARY)" ++ #endif ++- " © 2001-2006 Red Hat, Inc.\n"); +++#ifdef CONFIG_JFFS2_ZLIB +++ " (ZLIB)" +++#endif +++#ifdef CONFIG_JFFS2_LZO +++ " (LZO)" +++#endif +++#ifdef CONFIG_JFFS2_LZMA +++ " (LZMA)" +++#endif +++#ifdef CONFIG_JFFS2_RTIME +++ " (RTIME)" +++#endif +++#ifdef CONFIG_JFFS2_RUBIN +++ " (RUBIN)" +++#endif +++#ifdef CONFIG_JFFS2_CMODE_NONE +++ " (CMODE_NONE)" +++#endif +++#ifdef CONFIG_JFFS2_CMODE_PRIORITY +++ " (CMODE_PRIORITY)" +++#endif +++#ifdef CONFIG_JFFS2_CMODE_SIZE +++ " (CMODE_SIZE)" +++#endif +++#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO +++ " (CMODE_FAVOURLZO)" +++#endif +++ " (c) 2001-2006 Red Hat, Inc.\n"); ++ ++ jffs2_inode_cachep = kmem_cache_create("jffs2_i", ++ sizeof(struct jffs2_inode_info), ++--- /dev/null +++++ b/include/linux/lzma.h ++@@ -0,0 +1,62 @@ +++#ifndef __LZMA_H__ +++#define __LZMA_H__ +++ +++#ifdef __KERNEL__ +++ #include +++ #include +++ #include +++ #include +++ #include +++ #define LZMA_MALLOC vmalloc +++ #define LZMA_FREE vfree +++ #define PRINT_ERROR(msg) printk(KERN_WARNING #msg) +++ #define INIT __init +++ #define STATIC static +++#else +++ #include +++ #include +++ #include +++ #include +++ #include +++ #include +++ #include +++ #include +++ #ifndef PAGE_SIZE +++ extern int page_size; +++ #define PAGE_SIZE page_size +++ #endif +++ #define LZMA_MALLOC malloc +++ #define LZMA_FREE free +++ #define PRINT_ERROR(msg) fprintf(stderr, msg) +++ #define INIT +++ #define STATIC +++#endif +++ +++#include "lzma/LzmaDec.h" +++#include "lzma/LzmaEnc.h" +++ +++#define LZMA_BEST_LEVEL (9) +++#define LZMA_BEST_LC (0) +++#define LZMA_BEST_LP (0) +++#define LZMA_BEST_PB (0) +++#define LZMA_BEST_FB (273) +++ +++#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2) +++ +++static void *p_lzma_malloc(void *p, size_t size) +++{ +++ if (size == 0) +++ return NULL; +++ +++ return LZMA_MALLOC(size); +++} +++ +++static void p_lzma_free(void *p, void *address) +++{ +++ if (address != NULL) +++ LZMA_FREE(address); +++} +++ +++static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free}; +++ +++#endif ++--- /dev/null +++++ b/include/linux/lzma/LzFind.h ++@@ -0,0 +1,115 @@ +++/* LzFind.h -- Match finder for LZ algorithms +++2009-04-22 : Igor Pavlov : Public domain */ +++ +++#ifndef __LZ_FIND_H +++#define __LZ_FIND_H +++ +++#include "Types.h" +++ +++#ifdef __cplusplus +++extern "C" { +++#endif +++ +++typedef UInt32 CLzRef; +++ +++typedef struct _CMatchFinder +++{ +++ Byte *buffer; +++ UInt32 pos; +++ UInt32 posLimit; +++ UInt32 streamPos; +++ UInt32 lenLimit; +++ +++ UInt32 cyclicBufferPos; +++ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ +++ +++ UInt32 matchMaxLen; +++ CLzRef *hash; +++ CLzRef *son; +++ UInt32 hashMask; +++ UInt32 cutValue; +++ +++ Byte *bufferBase; +++ ISeqInStream *stream; +++ int streamEndWasReached; +++ +++ UInt32 blockSize; +++ UInt32 keepSizeBefore; +++ UInt32 keepSizeAfter; +++ +++ UInt32 numHashBytes; +++ int directInput; +++ size_t directInputRem; +++ int btMode; +++ int bigHash; +++ UInt32 historySize; +++ UInt32 fixedHashSize; +++ UInt32 hashSizeSum; +++ UInt32 numSons; +++ SRes result; +++ UInt32 crc[256]; +++} CMatchFinder; +++ +++#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +++#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) +++ +++#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) +++ +++int MatchFinder_NeedMove(CMatchFinder *p); +++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +++void MatchFinder_MoveBlock(CMatchFinder *p); +++void MatchFinder_ReadIfRequired(CMatchFinder *p); +++ +++void MatchFinder_Construct(CMatchFinder *p); +++ +++/* Conditions: +++ historySize <= 3 GB +++ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +++*/ +++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, +++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, +++ ISzAlloc *alloc); +++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); +++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); +++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); +++ +++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, +++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, +++ UInt32 *distances, UInt32 maxLen); +++ +++/* +++Conditions: +++ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. +++ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +++*/ +++ +++typedef void (*Mf_Init_Func)(void *object); +++typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); +++typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +++typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +++typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +++typedef void (*Mf_Skip_Func)(void *object, UInt32); +++ +++typedef struct _IMatchFinder +++{ +++ Mf_Init_Func Init; +++ Mf_GetIndexByte_Func GetIndexByte; +++ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; +++ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; +++ Mf_GetMatches_Func GetMatches; +++ Mf_Skip_Func Skip; +++} IMatchFinder; +++ +++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); +++ +++void MatchFinder_Init(CMatchFinder *p); +++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +++ +++#ifdef __cplusplus +++} +++#endif +++ +++#endif ++--- /dev/null +++++ b/include/linux/lzma/LzHash.h ++@@ -0,0 +1,54 @@ +++/* LzHash.h -- HASH functions for LZ algorithms +++2009-02-07 : Igor Pavlov : Public domain */ +++ +++#ifndef __LZ_HASH_H +++#define __LZ_HASH_H +++ +++#define kHash2Size (1 << 10) +++#define kHash3Size (1 << 16) +++#define kHash4Size (1 << 20) +++ +++#define kFix3HashSize (kHash2Size) +++#define kFix4HashSize (kHash2Size + kHash3Size) +++#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) +++ +++#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); +++ +++#define HASH3_CALC { \ +++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ +++ hash2Value = temp & (kHash2Size - 1); \ +++ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } +++ +++#define HASH4_CALC { \ +++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ +++ hash2Value = temp & (kHash2Size - 1); \ +++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ +++ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } +++ +++#define HASH5_CALC { \ +++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ +++ hash2Value = temp & (kHash2Size - 1); \ +++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ +++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ +++ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ +++ hash4Value &= (kHash4Size - 1); } +++ +++/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +++#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; +++ +++ +++#define MT_HASH2_CALC \ +++ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); +++ +++#define MT_HASH3_CALC { \ +++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ +++ hash2Value = temp & (kHash2Size - 1); \ +++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } +++ +++#define MT_HASH4_CALC { \ +++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ +++ hash2Value = temp & (kHash2Size - 1); \ +++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ +++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } +++ +++#endif ++--- /dev/null +++++ b/include/linux/lzma/LzmaDec.h ++@@ -0,0 +1,231 @@ +++/* LzmaDec.h -- LZMA Decoder +++2009-02-07 : Igor Pavlov : Public domain */ +++ +++#ifndef __LZMA_DEC_H +++#define __LZMA_DEC_H +++ +++#include "Types.h" +++ +++#ifdef __cplusplus +++extern "C" { +++#endif +++ +++/* #define _LZMA_PROB32 */ +++/* _LZMA_PROB32 can increase the speed on some CPUs, +++ but memory usage for CLzmaDec::probs will be doubled in that case */ +++ +++#ifdef _LZMA_PROB32 +++#define CLzmaProb UInt32 +++#else +++#define CLzmaProb UInt16 +++#endif +++ +++ +++/* ---------- LZMA Properties ---------- */ +++ +++#define LZMA_PROPS_SIZE 5 +++ +++typedef struct _CLzmaProps +++{ +++ unsigned lc, lp, pb; +++ UInt32 dicSize; +++} CLzmaProps; +++ +++/* LzmaProps_Decode - decodes properties +++Returns: +++ SZ_OK +++ SZ_ERROR_UNSUPPORTED - Unsupported properties +++*/ +++ +++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); +++ +++ +++/* ---------- LZMA Decoder state ---------- */ +++ +++/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. +++ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ +++ +++#define LZMA_REQUIRED_INPUT_MAX 20 +++ +++typedef struct +++{ +++ CLzmaProps prop; +++ CLzmaProb *probs; +++ Byte *dic; +++ const Byte *buf; +++ UInt32 range, code; +++ SizeT dicPos; +++ SizeT dicBufSize; +++ UInt32 processedPos; +++ UInt32 checkDicSize; +++ unsigned state; +++ UInt32 reps[4]; +++ unsigned remainLen; +++ int needFlush; +++ int needInitState; +++ UInt32 numProbs; +++ unsigned tempBufSize; +++ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +++} CLzmaDec; +++ +++#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } +++ +++void LzmaDec_Init(CLzmaDec *p); +++ +++/* There are two types of LZMA streams: +++ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. +++ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ +++ +++typedef enum +++{ +++ LZMA_FINISH_ANY, /* finish at any point */ +++ LZMA_FINISH_END /* block must be finished at the end */ +++} ELzmaFinishMode; +++ +++/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! +++ +++ You must use LZMA_FINISH_END, when you know that current output buffer +++ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. +++ +++ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, +++ and output value of destLen will be less than output buffer size limit. +++ You can check status result also. +++ +++ You can use multiple checks to test data integrity after full decompression: +++ 1) Check Result and "status" variable. +++ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. +++ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. +++ You must use correct finish mode in that case. */ +++ +++typedef enum +++{ +++ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ +++ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ +++ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ +++ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ +++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +++} ELzmaStatus; +++ +++/* ELzmaStatus is used only as output value for function call */ +++ +++ +++/* ---------- Interfaces ---------- */ +++ +++/* There are 3 levels of interfaces: +++ 1) Dictionary Interface +++ 2) Buffer Interface +++ 3) One Call Interface +++ You can select any of these interfaces, but don't mix functions from different +++ groups for same object. */ +++ +++ +++/* There are two variants to allocate state for Dictionary Interface: +++ 1) LzmaDec_Allocate / LzmaDec_Free +++ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs +++ You can use variant 2, if you set dictionary buffer manually. +++ For Buffer Interface you must always use variant 1. +++ +++LzmaDec_Allocate* can return: +++ SZ_OK +++ SZ_ERROR_MEM - Memory allocation error +++ SZ_ERROR_UNSUPPORTED - Unsupported properties +++*/ +++ +++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); +++ +++SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +++void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); +++ +++/* ---------- Dictionary Interface ---------- */ +++ +++/* You can use it, if you want to eliminate the overhead for data copying from +++ dictionary to some other external buffer. +++ You must work with CLzmaDec variables directly in this interface. +++ +++ STEPS: +++ LzmaDec_Constr() +++ LzmaDec_Allocate() +++ for (each new stream) +++ { +++ LzmaDec_Init() +++ while (it needs more decompression) +++ { +++ LzmaDec_DecodeToDic() +++ use data from CLzmaDec::dic and update CLzmaDec::dicPos +++ } +++ } +++ LzmaDec_Free() +++*/ +++ +++/* LzmaDec_DecodeToDic +++ +++ The decoding to internal dictionary buffer (CLzmaDec::dic). +++ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! +++ +++finishMode: +++ It has meaning only if the decoding reaches output limit (dicLimit). +++ LZMA_FINISH_ANY - Decode just dicLimit bytes. +++ LZMA_FINISH_END - Stream must be finished after dicLimit. +++ +++Returns: +++ SZ_OK +++ status: +++ LZMA_STATUS_FINISHED_WITH_MARK +++ LZMA_STATUS_NOT_FINISHED +++ LZMA_STATUS_NEEDS_MORE_INPUT +++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK +++ SZ_ERROR_DATA - Data error +++*/ +++ +++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, +++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); +++ +++ +++/* ---------- Buffer Interface ---------- */ +++ +++/* It's zlib-like interface. +++ See LzmaDec_DecodeToDic description for information about STEPS and return results, +++ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need +++ to work with CLzmaDec variables manually. +++ +++finishMode: +++ It has meaning only if the decoding reaches output limit (*destLen). +++ LZMA_FINISH_ANY - Decode just destLen bytes. +++ LZMA_FINISH_END - Stream must be finished after (*destLen). +++*/ +++ +++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, +++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); +++ +++ +++/* ---------- One Call Interface ---------- */ +++ +++/* LzmaDecode +++ +++finishMode: +++ It has meaning only if the decoding reaches output limit (*destLen). +++ LZMA_FINISH_ANY - Decode just destLen bytes. +++ LZMA_FINISH_END - Stream must be finished after (*destLen). +++ +++Returns: +++ SZ_OK +++ status: +++ LZMA_STATUS_FINISHED_WITH_MARK +++ LZMA_STATUS_NOT_FINISHED +++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK +++ SZ_ERROR_DATA - Data error +++ SZ_ERROR_MEM - Memory allocation error +++ SZ_ERROR_UNSUPPORTED - Unsupported properties +++ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +++*/ +++ +++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, +++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, +++ ELzmaStatus *status, ISzAlloc *alloc); +++ +++#ifdef __cplusplus +++} +++#endif +++ +++#endif ++--- /dev/null +++++ b/include/linux/lzma/LzmaEnc.h ++@@ -0,0 +1,80 @@ +++/* LzmaEnc.h -- LZMA Encoder +++2009-02-07 : Igor Pavlov : Public domain */ +++ +++#ifndef __LZMA_ENC_H +++#define __LZMA_ENC_H +++ +++#include "Types.h" +++ +++#ifdef __cplusplus +++extern "C" { +++#endif +++ +++#define LZMA_PROPS_SIZE 5 +++ +++typedef struct _CLzmaEncProps +++{ +++ int level; /* 0 <= level <= 9 */ +++ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version +++ (1 << 12) <= dictSize <= (1 << 30) for 64-bit version +++ default = (1 << 24) */ +++ int lc; /* 0 <= lc <= 8, default = 3 */ +++ int lp; /* 0 <= lp <= 4, default = 0 */ +++ int pb; /* 0 <= pb <= 4, default = 2 */ +++ int algo; /* 0 - fast, 1 - normal, default = 1 */ +++ int fb; /* 5 <= fb <= 273, default = 32 */ +++ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ +++ int numHashBytes; /* 2, 3 or 4, default = 4 */ +++ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ +++ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ +++ int numThreads; /* 1 or 2, default = 2 */ +++} CLzmaEncProps; +++ +++void LzmaEncProps_Init(CLzmaEncProps *p); +++void LzmaEncProps_Normalize(CLzmaEncProps *p); +++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); +++ +++ +++/* ---------- CLzmaEncHandle Interface ---------- */ +++ +++/* LzmaEnc_* functions can return the following exit codes: +++Returns: +++ SZ_OK - OK +++ SZ_ERROR_MEM - Memory allocation error +++ SZ_ERROR_PARAM - Incorrect paramater in props +++ SZ_ERROR_WRITE - Write callback error. +++ SZ_ERROR_PROGRESS - some break from progress callback +++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +++*/ +++ +++typedef void * CLzmaEncHandle; +++ +++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); +++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); +++SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +++SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +++SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, +++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +++SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, +++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +++ +++/* ---------- One Call Interface ---------- */ +++ +++/* LzmaEncode +++Return code: +++ SZ_OK - OK +++ SZ_ERROR_MEM - Memory allocation error +++ SZ_ERROR_PARAM - Incorrect paramater +++ SZ_ERROR_OUTPUT_EOF - output buffer overflow +++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +++*/ +++ +++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, +++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, +++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +++ +++#ifdef __cplusplus +++} +++#endif +++ +++#endif ++--- /dev/null +++++ b/include/linux/lzma/Types.h ++@@ -0,0 +1,226 @@ +++/* Types.h -- Basic types +++2009-11-23 : Igor Pavlov : Public domain */ +++ +++#ifndef __7Z_TYPES_H +++#define __7Z_TYPES_H +++ +++#include +++ +++#ifdef _WIN32 +++#include +++#endif +++ +++#ifndef EXTERN_C_BEGIN +++#ifdef __cplusplus +++#define EXTERN_C_BEGIN extern "C" { +++#define EXTERN_C_END } +++#else +++#define EXTERN_C_BEGIN +++#define EXTERN_C_END +++#endif +++#endif +++ +++EXTERN_C_BEGIN +++ +++#define SZ_OK 0 +++ +++#define SZ_ERROR_DATA 1 +++#define SZ_ERROR_MEM 2 +++#define SZ_ERROR_CRC 3 +++#define SZ_ERROR_UNSUPPORTED 4 +++#define SZ_ERROR_PARAM 5 +++#define SZ_ERROR_INPUT_EOF 6 +++#define SZ_ERROR_OUTPUT_EOF 7 +++#define SZ_ERROR_READ 8 +++#define SZ_ERROR_WRITE 9 +++#define SZ_ERROR_PROGRESS 10 +++#define SZ_ERROR_FAIL 11 +++#define SZ_ERROR_THREAD 12 +++ +++#define SZ_ERROR_ARCHIVE 16 +++#define SZ_ERROR_NO_ARCHIVE 17 +++ +++typedef int SRes; +++ +++#ifdef _WIN32 +++typedef DWORD WRes; +++#else +++typedef int WRes; +++#endif +++ +++#ifndef RINOK +++#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +++#endif +++ +++typedef unsigned char Byte; +++typedef short Int16; +++typedef unsigned short UInt16; +++ +++#ifdef _LZMA_UINT32_IS_ULONG +++typedef long Int32; +++typedef unsigned long UInt32; +++#else +++typedef int Int32; +++typedef unsigned int UInt32; +++#endif +++ +++#ifdef _SZ_NO_INT_64 +++ +++/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. +++ NOTES: Some code will work incorrectly in that case! */ +++ +++typedef long Int64; +++typedef unsigned long UInt64; +++ +++#else +++ +++#if defined(_MSC_VER) || defined(__BORLANDC__) +++typedef __int64 Int64; +++typedef unsigned __int64 UInt64; +++#else +++typedef long long int Int64; +++typedef unsigned long long int UInt64; +++#endif +++ +++#endif +++ +++#ifdef _LZMA_NO_SYSTEM_SIZE_T +++typedef UInt32 SizeT; +++#else +++typedef size_t SizeT; +++#endif +++ +++typedef int Bool; +++#define True 1 +++#define False 0 +++ +++ +++#ifdef _WIN32 +++#define MY_STD_CALL __stdcall +++#else +++#define MY_STD_CALL +++#endif +++ +++#ifdef _MSC_VER +++ +++#if _MSC_VER >= 1300 +++#define MY_NO_INLINE __declspec(noinline) +++#else +++#define MY_NO_INLINE +++#endif +++ +++#define MY_CDECL __cdecl +++#define MY_FAST_CALL __fastcall +++ +++#else +++ +++#define MY_CDECL +++#define MY_FAST_CALL +++ +++#endif +++ +++ +++/* The following interfaces use first parameter as pointer to structure */ +++ +++typedef struct +++{ +++ SRes (*Read)(void *p, void *buf, size_t *size); +++ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. +++ (output(*size) < input(*size)) is allowed */ +++} ISeqInStream; +++ +++/* it can return SZ_ERROR_INPUT_EOF */ +++SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +++SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +++SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); +++ +++typedef struct +++{ +++ size_t (*Write)(void *p, const void *buf, size_t size); +++ /* Returns: result - the number of actually written bytes. +++ (result < size) means error */ +++} ISeqOutStream; +++ +++typedef enum +++{ +++ SZ_SEEK_SET = 0, +++ SZ_SEEK_CUR = 1, +++ SZ_SEEK_END = 2 +++} ESzSeek; +++ +++typedef struct +++{ +++ SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ +++ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +++} ISeekInStream; +++ +++typedef struct +++{ +++ SRes (*Look)(void *p, void **buf, size_t *size); +++ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. +++ (output(*size) > input(*size)) is not allowed +++ (output(*size) < input(*size)) is allowed */ +++ SRes (*Skip)(void *p, size_t offset); +++ /* offset must be <= output(*size) of Look */ +++ +++ SRes (*Read)(void *p, void *buf, size_t *size); +++ /* reads directly (without buffer). It's same as ISeqInStream::Read */ +++ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +++} ILookInStream; +++ +++SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +++SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); +++ +++/* reads via ILookInStream::Read */ +++SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +++SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); +++ +++#define LookToRead_BUF_SIZE (1 << 14) +++ +++typedef struct +++{ +++ ILookInStream s; +++ ISeekInStream *realStream; +++ size_t pos; +++ size_t size; +++ Byte buf[LookToRead_BUF_SIZE]; +++} CLookToRead; +++ +++void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +++void LookToRead_Init(CLookToRead *p); +++ +++typedef struct +++{ +++ ISeqInStream s; +++ ILookInStream *realStream; +++} CSecToLook; +++ +++void SecToLook_CreateVTable(CSecToLook *p); +++ +++typedef struct +++{ +++ ISeqInStream s; +++ ILookInStream *realStream; +++} CSecToRead; +++ +++void SecToRead_CreateVTable(CSecToRead *p); +++ +++typedef struct +++{ +++ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); +++ /* Returns: result. (result != SZ_OK) means break. +++ Value (UInt64)(Int64)-1 for size means unknown value. */ +++} ICompressProgress; +++ +++typedef struct +++{ +++ void *(*Alloc)(void *p, size_t size); +++ void (*Free)(void *p, void *address); /* address can be 0 */ +++} ISzAlloc; +++ +++#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +++#define IAlloc_Free(p, a) (p)->Free((p), a) +++ +++EXTERN_C_END +++ +++#endif ++--- a/include/uapi/linux/jffs2.h +++++ b/include/uapi/linux/jffs2.h ++@@ -46,6 +46,7 @@ ++ #define JFFS2_COMPR_DYNRUBIN 0x05 ++ #define JFFS2_COMPR_ZLIB 0x06 ++ #define JFFS2_COMPR_LZO 0x07 +++#define JFFS2_COMPR_LZMA 0x08 ++ /* Compatibility flags. */ ++ #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ ++ #define JFFS2_NODE_ACCURATE 0x2000 ++--- a/lib/Kconfig +++++ b/lib/Kconfig ++@@ -259,6 +259,12 @@ config ZSTD_DECOMPRESS ++ ++ source "lib/xz/Kconfig" ++ +++config LZMA_COMPRESS +++ tristate +++ +++config LZMA_DECOMPRESS +++ tristate +++ ++ # ++ # These all provide a common interface (hence the apparent duplication with ++ # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) ++--- a/lib/Makefile +++++ b/lib/Makefile ++@@ -3,6 +3,16 @@ ++ # Makefile for some libs needed in the kernel. ++ # ++ +++ifdef CONFIG_JFFS2_ZLIB +++ CONFIG_ZLIB_INFLATE:=y +++ CONFIG_ZLIB_DEFLATE:=y +++endif +++ +++ifdef CONFIG_JFFS2_LZMA +++ CONFIG_LZMA_DECOMPRESS:=y +++ CONFIG_LZMA_COMPRESS:=y +++endif +++ ++ ifdef CONFIG_FUNCTION_TRACER ++ ORIG_CFLAGS := $(KBUILD_CFLAGS) ++ KBUILD_CFLAGS = $(subst $(CC_FLAGS_FTRACE),,$(ORIG_CFLAGS)) ++@@ -134,6 +144,8 @@ obj-$(CONFIG_ZSTD_COMPRESS) += zstd/ ++ obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd/ ++ obj-$(CONFIG_XZ_DEC) += xz/ ++ obj-$(CONFIG_RAID6_PQ) += raid6/ +++obj-$(CONFIG_LZMA_COMPRESS) += lzma/ +++obj-$(CONFIG_LZMA_DECOMPRESS) += lzma/ ++ ++ lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o ++ lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o ++--- /dev/null +++++ b/lib/lzma/LzFind.c ++@@ -0,0 +1,761 @@ +++/* LzFind.c -- Match finder for LZ algorithms +++2009-04-22 : Igor Pavlov : Public domain */ +++ +++#include +++ +++#include "LzFind.h" +++#include "LzHash.h" +++ +++#define kEmptyHashValue 0 +++#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +++#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ +++#define kNormalizeMask (~(kNormalizeStepMin - 1)) +++#define kMaxHistorySize ((UInt32)3 << 30) +++ +++#define kStartMaxLen 3 +++ +++static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) +++{ +++ if (!p->directInput) +++ { +++ alloc->Free(alloc, p->bufferBase); +++ p->bufferBase = 0; +++ } +++} +++ +++/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ +++ +++static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) +++{ +++ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; +++ if (p->directInput) +++ { +++ p->blockSize = blockSize; +++ return 1; +++ } +++ if (p->bufferBase == 0 || p->blockSize != blockSize) +++ { +++ LzInWindow_Free(p, alloc); +++ p->blockSize = blockSize; +++ p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); +++ } +++ return (p->bufferBase != 0); +++} +++ +++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +++Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } +++ +++UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } +++ +++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +++{ +++ p->posLimit -= subValue; +++ p->pos -= subValue; +++ p->streamPos -= subValue; +++} +++ +++static void MatchFinder_ReadBlock(CMatchFinder *p) +++{ +++ if (p->streamEndWasReached || p->result != SZ_OK) +++ return; +++ if (p->directInput) +++ { +++ UInt32 curSize = 0xFFFFFFFF - p->streamPos; +++ if (curSize > p->directInputRem) +++ curSize = (UInt32)p->directInputRem; +++ p->directInputRem -= curSize; +++ p->streamPos += curSize; +++ if (p->directInputRem == 0) +++ p->streamEndWasReached = 1; +++ return; +++ } +++ for (;;) +++ { +++ Byte *dest = p->buffer + (p->streamPos - p->pos); +++ size_t size = (p->bufferBase + p->blockSize - dest); +++ if (size == 0) +++ return; +++ p->result = p->stream->Read(p->stream, dest, &size); +++ if (p->result != SZ_OK) +++ return; +++ if (size == 0) +++ { +++ p->streamEndWasReached = 1; +++ return; +++ } +++ p->streamPos += (UInt32)size; +++ if (p->streamPos - p->pos > p->keepSizeAfter) +++ return; +++ } +++} +++ +++void MatchFinder_MoveBlock(CMatchFinder *p) +++{ +++ memmove(p->bufferBase, +++ p->buffer - p->keepSizeBefore, +++ (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); +++ p->buffer = p->bufferBase + p->keepSizeBefore; +++} +++ +++int MatchFinder_NeedMove(CMatchFinder *p) +++{ +++ if (p->directInput) +++ return 0; +++ /* if (p->streamEndWasReached) return 0; */ +++ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +++} +++ +++void MatchFinder_ReadIfRequired(CMatchFinder *p) +++{ +++ if (p->streamEndWasReached) +++ return; +++ if (p->keepSizeAfter >= p->streamPos - p->pos) +++ MatchFinder_ReadBlock(p); +++} +++ +++static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +++{ +++ if (MatchFinder_NeedMove(p)) +++ MatchFinder_MoveBlock(p); +++ MatchFinder_ReadBlock(p); +++} +++ +++static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +++{ +++ p->cutValue = 32; +++ p->btMode = 1; +++ p->numHashBytes = 4; +++ p->bigHash = 0; +++} +++ +++#define kCrcPoly 0xEDB88320 +++ +++void MatchFinder_Construct(CMatchFinder *p) +++{ +++ UInt32 i; +++ p->bufferBase = 0; +++ p->directInput = 0; +++ p->hash = 0; +++ MatchFinder_SetDefaultSettings(p); +++ +++ for (i = 0; i < 256; i++) +++ { +++ UInt32 r = i; +++ int j; +++ for (j = 0; j < 8; j++) +++ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); +++ p->crc[i] = r; +++ } +++} +++ +++static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) +++{ +++ alloc->Free(alloc, p->hash); +++ p->hash = 0; +++} +++ +++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) +++{ +++ MatchFinder_FreeThisClassMemory(p, alloc); +++ LzInWindow_Free(p, alloc); +++} +++ +++static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) +++{ +++ size_t sizeInBytes = (size_t)num * sizeof(CLzRef); +++ if (sizeInBytes / sizeof(CLzRef) != num) +++ return 0; +++ return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); +++} +++ +++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, +++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, +++ ISzAlloc *alloc) +++{ +++ UInt32 sizeReserv; +++ if (historySize > kMaxHistorySize) +++ { +++ MatchFinder_Free(p, alloc); +++ return 0; +++ } +++ sizeReserv = historySize >> 1; +++ if (historySize > ((UInt32)2 << 30)) +++ sizeReserv = historySize >> 2; +++ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); +++ +++ p->keepSizeBefore = historySize + keepAddBufferBefore + 1; +++ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; +++ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ +++ if (LzInWindow_Create(p, sizeReserv, alloc)) +++ { +++ UInt32 newCyclicBufferSize = historySize + 1; +++ UInt32 hs; +++ p->matchMaxLen = matchMaxLen; +++ { +++ p->fixedHashSize = 0; +++ if (p->numHashBytes == 2) +++ hs = (1 << 16) - 1; +++ else +++ { +++ hs = historySize - 1; +++ hs |= (hs >> 1); +++ hs |= (hs >> 2); +++ hs |= (hs >> 4); +++ hs |= (hs >> 8); +++ hs >>= 1; +++ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ +++ if (hs > (1 << 24)) +++ { +++ if (p->numHashBytes == 3) +++ hs = (1 << 24) - 1; +++ else +++ hs >>= 1; +++ } +++ } +++ p->hashMask = hs; +++ hs++; +++ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; +++ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; +++ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; +++ hs += p->fixedHashSize; +++ } +++ +++ { +++ UInt32 prevSize = p->hashSizeSum + p->numSons; +++ UInt32 newSize; +++ p->historySize = historySize; +++ p->hashSizeSum = hs; +++ p->cyclicBufferSize = newCyclicBufferSize; +++ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); +++ newSize = p->hashSizeSum + p->numSons; +++ if (p->hash != 0 && prevSize == newSize) +++ return 1; +++ MatchFinder_FreeThisClassMemory(p, alloc); +++ p->hash = AllocRefs(newSize, alloc); +++ if (p->hash != 0) +++ { +++ p->son = p->hash + p->hashSizeSum; +++ return 1; +++ } +++ } +++ } +++ MatchFinder_Free(p, alloc); +++ return 0; +++} +++ +++static void MatchFinder_SetLimits(CMatchFinder *p) +++{ +++ UInt32 limit = kMaxValForNormalize - p->pos; +++ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; +++ if (limit2 < limit) +++ limit = limit2; +++ limit2 = p->streamPos - p->pos; +++ if (limit2 <= p->keepSizeAfter) +++ { +++ if (limit2 > 0) +++ limit2 = 1; +++ } +++ else +++ limit2 -= p->keepSizeAfter; +++ if (limit2 < limit) +++ limit = limit2; +++ { +++ UInt32 lenLimit = p->streamPos - p->pos; +++ if (lenLimit > p->matchMaxLen) +++ lenLimit = p->matchMaxLen; +++ p->lenLimit = lenLimit; +++ } +++ p->posLimit = p->pos + limit; +++} +++ +++void MatchFinder_Init(CMatchFinder *p) +++{ +++ UInt32 i; +++ for (i = 0; i < p->hashSizeSum; i++) +++ p->hash[i] = kEmptyHashValue; +++ p->cyclicBufferPos = 0; +++ p->buffer = p->bufferBase; +++ p->pos = p->streamPos = p->cyclicBufferSize; +++ p->result = SZ_OK; +++ p->streamEndWasReached = 0; +++ MatchFinder_ReadBlock(p); +++ MatchFinder_SetLimits(p); +++} +++ +++static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +++{ +++ return (p->pos - p->historySize - 1) & kNormalizeMask; +++} +++ +++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +++{ +++ UInt32 i; +++ for (i = 0; i < numItems; i++) +++ { +++ UInt32 value = items[i]; +++ if (value <= subValue) +++ value = kEmptyHashValue; +++ else +++ value -= subValue; +++ items[i] = value; +++ } +++} +++ +++static void MatchFinder_Normalize(CMatchFinder *p) +++{ +++ UInt32 subValue = MatchFinder_GetSubValue(p); +++ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); +++ MatchFinder_ReduceOffsets(p, subValue); +++} +++ +++static void MatchFinder_CheckLimits(CMatchFinder *p) +++{ +++ if (p->pos == kMaxValForNormalize) +++ MatchFinder_Normalize(p); +++ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) +++ MatchFinder_CheckAndMoveAndRead(p); +++ if (p->cyclicBufferPos == p->cyclicBufferSize) +++ p->cyclicBufferPos = 0; +++ MatchFinder_SetLimits(p); +++} +++ +++static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, +++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, +++ UInt32 *distances, UInt32 maxLen) +++{ +++ son[_cyclicBufferPos] = curMatch; +++ for (;;) +++ { +++ UInt32 delta = pos - curMatch; +++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) +++ return distances; +++ { +++ const Byte *pb = cur - delta; +++ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; +++ if (pb[maxLen] == cur[maxLen] && *pb == *cur) +++ { +++ UInt32 len = 0; +++ while (++len != lenLimit) +++ if (pb[len] != cur[len]) +++ break; +++ if (maxLen < len) +++ { +++ *distances++ = maxLen = len; +++ *distances++ = delta - 1; +++ if (len == lenLimit) +++ return distances; +++ } +++ } +++ } +++ } +++} +++ +++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, +++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, +++ UInt32 *distances, UInt32 maxLen) +++{ +++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; +++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1); +++ UInt32 len0 = 0, len1 = 0; +++ for (;;) +++ { +++ UInt32 delta = pos - curMatch; +++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) +++ { +++ *ptr0 = *ptr1 = kEmptyHashValue; +++ return distances; +++ } +++ { +++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); +++ const Byte *pb = cur - delta; +++ UInt32 len = (len0 < len1 ? len0 : len1); +++ if (pb[len] == cur[len]) +++ { +++ if (++len != lenLimit && pb[len] == cur[len]) +++ while (++len != lenLimit) +++ if (pb[len] != cur[len]) +++ break; +++ if (maxLen < len) +++ { +++ *distances++ = maxLen = len; +++ *distances++ = delta - 1; +++ if (len == lenLimit) +++ { +++ *ptr1 = pair[0]; +++ *ptr0 = pair[1]; +++ return distances; +++ } +++ } +++ } +++ if (pb[len] < cur[len]) +++ { +++ *ptr1 = curMatch; +++ ptr1 = pair + 1; +++ curMatch = *ptr1; +++ len1 = len; +++ } +++ else +++ { +++ *ptr0 = curMatch; +++ ptr0 = pair; +++ curMatch = *ptr0; +++ len0 = len; +++ } +++ } +++ } +++} +++ +++static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, +++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +++{ +++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; +++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1); +++ UInt32 len0 = 0, len1 = 0; +++ for (;;) +++ { +++ UInt32 delta = pos - curMatch; +++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) +++ { +++ *ptr0 = *ptr1 = kEmptyHashValue; +++ return; +++ } +++ { +++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); +++ const Byte *pb = cur - delta; +++ UInt32 len = (len0 < len1 ? len0 : len1); +++ if (pb[len] == cur[len]) +++ { +++ while (++len != lenLimit) +++ if (pb[len] != cur[len]) +++ break; +++ { +++ if (len == lenLimit) +++ { +++ *ptr1 = pair[0]; +++ *ptr0 = pair[1]; +++ return; +++ } +++ } +++ } +++ if (pb[len] < cur[len]) +++ { +++ *ptr1 = curMatch; +++ ptr1 = pair + 1; +++ curMatch = *ptr1; +++ len1 = len; +++ } +++ else +++ { +++ *ptr0 = curMatch; +++ ptr0 = pair; +++ curMatch = *ptr0; +++ len0 = len; +++ } +++ } +++ } +++} +++ +++#define MOVE_POS \ +++ ++p->cyclicBufferPos; \ +++ p->buffer++; \ +++ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); +++ +++#define MOVE_POS_RET MOVE_POS return offset; +++ +++static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } +++ +++#define GET_MATCHES_HEADER2(minLen, ret_op) \ +++ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ +++ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ +++ cur = p->buffer; +++ +++#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +++#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) +++ +++#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue +++ +++#define GET_MATCHES_FOOTER(offset, maxLen) \ +++ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ +++ distances + offset, maxLen) - distances); MOVE_POS_RET; +++ +++#define SKIP_FOOTER \ +++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; +++ +++static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +++{ +++ UInt32 offset; +++ GET_MATCHES_HEADER(2) +++ HASH2_CALC; +++ curMatch = p->hash[hashValue]; +++ p->hash[hashValue] = p->pos; +++ offset = 0; +++ GET_MATCHES_FOOTER(offset, 1) +++} +++ +++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +++{ +++ UInt32 offset; +++ GET_MATCHES_HEADER(3) +++ HASH_ZIP_CALC; +++ curMatch = p->hash[hashValue]; +++ p->hash[hashValue] = p->pos; +++ offset = 0; +++ GET_MATCHES_FOOTER(offset, 2) +++} +++ +++static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +++{ +++ UInt32 hash2Value, delta2, maxLen, offset; +++ GET_MATCHES_HEADER(3) +++ +++ HASH3_CALC; +++ +++ delta2 = p->pos - p->hash[hash2Value]; +++ curMatch = p->hash[kFix3HashSize + hashValue]; +++ +++ p->hash[hash2Value] = +++ p->hash[kFix3HashSize + hashValue] = p->pos; +++ +++ +++ maxLen = 2; +++ offset = 0; +++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) +++ { +++ for (; maxLen != lenLimit; maxLen++) +++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) +++ break; +++ distances[0] = maxLen; +++ distances[1] = delta2 - 1; +++ offset = 2; +++ if (maxLen == lenLimit) +++ { +++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); +++ MOVE_POS_RET; +++ } +++ } +++ GET_MATCHES_FOOTER(offset, maxLen) +++} +++ +++static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +++{ +++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; +++ GET_MATCHES_HEADER(4) +++ +++ HASH4_CALC; +++ +++ delta2 = p->pos - p->hash[ hash2Value]; +++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; +++ curMatch = p->hash[kFix4HashSize + hashValue]; +++ +++ p->hash[ hash2Value] = +++ p->hash[kFix3HashSize + hash3Value] = +++ p->hash[kFix4HashSize + hashValue] = p->pos; +++ +++ maxLen = 1; +++ offset = 0; +++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) +++ { +++ distances[0] = maxLen = 2; +++ distances[1] = delta2 - 1; +++ offset = 2; +++ } +++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) +++ { +++ maxLen = 3; +++ distances[offset + 1] = delta3 - 1; +++ offset += 2; +++ delta2 = delta3; +++ } +++ if (offset != 0) +++ { +++ for (; maxLen != lenLimit; maxLen++) +++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) +++ break; +++ distances[offset - 2] = maxLen; +++ if (maxLen == lenLimit) +++ { +++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); +++ MOVE_POS_RET; +++ } +++ } +++ if (maxLen < 3) +++ maxLen = 3; +++ GET_MATCHES_FOOTER(offset, maxLen) +++} +++ +++static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +++{ +++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; +++ GET_MATCHES_HEADER(4) +++ +++ HASH4_CALC; +++ +++ delta2 = p->pos - p->hash[ hash2Value]; +++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; +++ curMatch = p->hash[kFix4HashSize + hashValue]; +++ +++ p->hash[ hash2Value] = +++ p->hash[kFix3HashSize + hash3Value] = +++ p->hash[kFix4HashSize + hashValue] = p->pos; +++ +++ maxLen = 1; +++ offset = 0; +++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) +++ { +++ distances[0] = maxLen = 2; +++ distances[1] = delta2 - 1; +++ offset = 2; +++ } +++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) +++ { +++ maxLen = 3; +++ distances[offset + 1] = delta3 - 1; +++ offset += 2; +++ delta2 = delta3; +++ } +++ if (offset != 0) +++ { +++ for (; maxLen != lenLimit; maxLen++) +++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) +++ break; +++ distances[offset - 2] = maxLen; +++ if (maxLen == lenLimit) +++ { +++ p->son[p->cyclicBufferPos] = curMatch; +++ MOVE_POS_RET; +++ } +++ } +++ if (maxLen < 3) +++ maxLen = 3; +++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), +++ distances + offset, maxLen) - (distances)); +++ MOVE_POS_RET +++} +++ +++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +++{ +++ UInt32 offset; +++ GET_MATCHES_HEADER(3) +++ HASH_ZIP_CALC; +++ curMatch = p->hash[hashValue]; +++ p->hash[hashValue] = p->pos; +++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), +++ distances, 2) - (distances)); +++ MOVE_POS_RET +++} +++ +++static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +++{ +++ do +++ { +++ SKIP_HEADER(2) +++ HASH2_CALC; +++ curMatch = p->hash[hashValue]; +++ p->hash[hashValue] = p->pos; +++ SKIP_FOOTER +++ } +++ while (--num != 0); +++} +++ +++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +++{ +++ do +++ { +++ SKIP_HEADER(3) +++ HASH_ZIP_CALC; +++ curMatch = p->hash[hashValue]; +++ p->hash[hashValue] = p->pos; +++ SKIP_FOOTER +++ } +++ while (--num != 0); +++} +++ +++static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +++{ +++ do +++ { +++ UInt32 hash2Value; +++ SKIP_HEADER(3) +++ HASH3_CALC; +++ curMatch = p->hash[kFix3HashSize + hashValue]; +++ p->hash[hash2Value] = +++ p->hash[kFix3HashSize + hashValue] = p->pos; +++ SKIP_FOOTER +++ } +++ while (--num != 0); +++} +++ +++static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +++{ +++ do +++ { +++ UInt32 hash2Value, hash3Value; +++ SKIP_HEADER(4) +++ HASH4_CALC; +++ curMatch = p->hash[kFix4HashSize + hashValue]; +++ p->hash[ hash2Value] = +++ p->hash[kFix3HashSize + hash3Value] = p->pos; +++ p->hash[kFix4HashSize + hashValue] = p->pos; +++ SKIP_FOOTER +++ } +++ while (--num != 0); +++} +++ +++static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +++{ +++ do +++ { +++ UInt32 hash2Value, hash3Value; +++ SKIP_HEADER(4) +++ HASH4_CALC; +++ curMatch = p->hash[kFix4HashSize + hashValue]; +++ p->hash[ hash2Value] = +++ p->hash[kFix3HashSize + hash3Value] = +++ p->hash[kFix4HashSize + hashValue] = p->pos; +++ p->son[p->cyclicBufferPos] = curMatch; +++ MOVE_POS +++ } +++ while (--num != 0); +++} +++ +++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +++{ +++ do +++ { +++ SKIP_HEADER(3) +++ HASH_ZIP_CALC; +++ curMatch = p->hash[hashValue]; +++ p->hash[hashValue] = p->pos; +++ p->son[p->cyclicBufferPos] = curMatch; +++ MOVE_POS +++ } +++ while (--num != 0); +++} +++ +++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +++{ +++ vTable->Init = (Mf_Init_Func)MatchFinder_Init; +++ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; +++ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; +++ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; +++ if (!p->btMode) +++ { +++ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; +++ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; +++ } +++ else if (p->numHashBytes == 2) +++ { +++ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; +++ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; +++ } +++ else if (p->numHashBytes == 3) +++ { +++ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; +++ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; +++ } +++ else +++ { +++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; +++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; +++ } +++} ++--- /dev/null +++++ b/lib/lzma/LzmaDec.c ++@@ -0,0 +1,999 @@ +++/* LzmaDec.c -- LZMA Decoder +++2009-09-20 : Igor Pavlov : Public domain */ +++ +++#include "LzmaDec.h" +++ +++#include +++ +++#define kNumTopBits 24 +++#define kTopValue ((UInt32)1 << kNumTopBits) +++ +++#define kNumBitModelTotalBits 11 +++#define kBitModelTotal (1 << kNumBitModelTotalBits) +++#define kNumMoveBits 5 +++ +++#define RC_INIT_SIZE 5 +++ +++#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } +++ +++#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +++#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +++#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +++#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ +++ { UPDATE_0(p); i = (i + i); A0; } else \ +++ { UPDATE_1(p); i = (i + i) + 1; A1; } +++#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) +++ +++#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +++#define TREE_DECODE(probs, limit, i) \ +++ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } +++ +++/* #define _LZMA_SIZE_OPT */ +++ +++#ifdef _LZMA_SIZE_OPT +++#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +++#else +++#define TREE_6_DECODE(probs, i) \ +++ { i = 1; \ +++ TREE_GET_BIT(probs, i); \ +++ TREE_GET_BIT(probs, i); \ +++ TREE_GET_BIT(probs, i); \ +++ TREE_GET_BIT(probs, i); \ +++ TREE_GET_BIT(probs, i); \ +++ TREE_GET_BIT(probs, i); \ +++ i -= 0x40; } +++#endif +++ +++#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } +++ +++#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +++#define UPDATE_0_CHECK range = bound; +++#define UPDATE_1_CHECK range -= bound; code -= bound; +++#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ +++ { UPDATE_0_CHECK; i = (i + i); A0; } else \ +++ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +++#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +++#define TREE_DECODE_CHECK(probs, limit, i) \ +++ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } +++ +++ +++#define kNumPosBitsMax 4 +++#define kNumPosStatesMax (1 << kNumPosBitsMax) +++ +++#define kLenNumLowBits 3 +++#define kLenNumLowSymbols (1 << kLenNumLowBits) +++#define kLenNumMidBits 3 +++#define kLenNumMidSymbols (1 << kLenNumMidBits) +++#define kLenNumHighBits 8 +++#define kLenNumHighSymbols (1 << kLenNumHighBits) +++ +++#define LenChoice 0 +++#define LenChoice2 (LenChoice + 1) +++#define LenLow (LenChoice2 + 1) +++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) +++ +++ +++#define kNumStates 12 +++#define kNumLitStates 7 +++ +++#define kStartPosModelIndex 4 +++#define kEndPosModelIndex 14 +++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) +++ +++#define kNumPosSlotBits 6 +++#define kNumLenToPosStates 4 +++ +++#define kNumAlignBits 4 +++#define kAlignTableSize (1 << kNumAlignBits) +++ +++#define kMatchMinLen 2 +++#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) +++ +++#define IsMatch 0 +++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +++#define IsRepG0 (IsRep + kNumStates) +++#define IsRepG1 (IsRepG0 + kNumStates) +++#define IsRepG2 (IsRepG1 + kNumStates) +++#define IsRep0Long (IsRepG2 + kNumStates) +++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +++#define LenCoder (Align + kAlignTableSize) +++#define RepLenCoder (LenCoder + kNumLenProbs) +++#define Literal (RepLenCoder + kNumLenProbs) +++ +++#define LZMA_BASE_SIZE 1846 +++#define LZMA_LIT_SIZE 768 +++ +++#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) +++ +++#if Literal != LZMA_BASE_SIZE +++StopCompilingDueBUG +++#endif +++ +++#define LZMA_DIC_MIN (1 << 12) +++ +++/* First LZMA-symbol is always decoded. +++And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +++Out: +++ Result: +++ SZ_OK - OK +++ SZ_ERROR_DATA - Error +++ p->remainLen: +++ < kMatchSpecLenStart : normal remain +++ = kMatchSpecLenStart : finished +++ = kMatchSpecLenStart + 1 : Flush marker +++ = kMatchSpecLenStart + 2 : State Init Marker +++*/ +++ +++static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +++{ +++ CLzmaProb *probs = p->probs; +++ +++ unsigned state = p->state; +++ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; +++ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; +++ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; +++ unsigned lc = p->prop.lc; +++ +++ Byte *dic = p->dic; +++ SizeT dicBufSize = p->dicBufSize; +++ SizeT dicPos = p->dicPos; +++ +++ UInt32 processedPos = p->processedPos; +++ UInt32 checkDicSize = p->checkDicSize; +++ unsigned len = 0; +++ +++ const Byte *buf = p->buf; +++ UInt32 range = p->range; +++ UInt32 code = p->code; +++ +++ do +++ { +++ CLzmaProb *prob; +++ UInt32 bound; +++ unsigned ttt; +++ unsigned posState = processedPos & pbMask; +++ +++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; +++ IF_BIT_0(prob) +++ { +++ unsigned symbol; +++ UPDATE_0(prob); +++ prob = probs + Literal; +++ if (checkDicSize != 0 || processedPos != 0) +++ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + +++ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); +++ +++ if (state < kNumLitStates) +++ { +++ state -= (state < 4) ? state : 3; +++ symbol = 1; +++ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); +++ } +++ else +++ { +++ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; +++ unsigned offs = 0x100; +++ state -= (state < 10) ? 3 : 6; +++ symbol = 1; +++ do +++ { +++ unsigned bit; +++ CLzmaProb *probLit; +++ matchByte <<= 1; +++ bit = (matchByte & offs); +++ probLit = prob + offs + bit + symbol; +++ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) +++ } +++ while (symbol < 0x100); +++ } +++ dic[dicPos++] = (Byte)symbol; +++ processedPos++; +++ continue; +++ } +++ else +++ { +++ UPDATE_1(prob); +++ prob = probs + IsRep + state; +++ IF_BIT_0(prob) +++ { +++ UPDATE_0(prob); +++ state += kNumStates; +++ prob = probs + LenCoder; +++ } +++ else +++ { +++ UPDATE_1(prob); +++ if (checkDicSize == 0 && processedPos == 0) +++ return SZ_ERROR_DATA; +++ prob = probs + IsRepG0 + state; +++ IF_BIT_0(prob) +++ { +++ UPDATE_0(prob); +++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; +++ IF_BIT_0(prob) +++ { +++ UPDATE_0(prob); +++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; +++ dicPos++; +++ processedPos++; +++ state = state < kNumLitStates ? 9 : 11; +++ continue; +++ } +++ UPDATE_1(prob); +++ } +++ else +++ { +++ UInt32 distance; +++ UPDATE_1(prob); +++ prob = probs + IsRepG1 + state; +++ IF_BIT_0(prob) +++ { +++ UPDATE_0(prob); +++ distance = rep1; +++ } +++ else +++ { +++ UPDATE_1(prob); +++ prob = probs + IsRepG2 + state; +++ IF_BIT_0(prob) +++ { +++ UPDATE_0(prob); +++ distance = rep2; +++ } +++ else +++ { +++ UPDATE_1(prob); +++ distance = rep3; +++ rep3 = rep2; +++ } +++ rep2 = rep1; +++ } +++ rep1 = rep0; +++ rep0 = distance; +++ } +++ state = state < kNumLitStates ? 8 : 11; +++ prob = probs + RepLenCoder; +++ } +++ { +++ unsigned limit, offset; +++ CLzmaProb *probLen = prob + LenChoice; +++ IF_BIT_0(probLen) +++ { +++ UPDATE_0(probLen); +++ probLen = prob + LenLow + (posState << kLenNumLowBits); +++ offset = 0; +++ limit = (1 << kLenNumLowBits); +++ } +++ else +++ { +++ UPDATE_1(probLen); +++ probLen = prob + LenChoice2; +++ IF_BIT_0(probLen) +++ { +++ UPDATE_0(probLen); +++ probLen = prob + LenMid + (posState << kLenNumMidBits); +++ offset = kLenNumLowSymbols; +++ limit = (1 << kLenNumMidBits); +++ } +++ else +++ { +++ UPDATE_1(probLen); +++ probLen = prob + LenHigh; +++ offset = kLenNumLowSymbols + kLenNumMidSymbols; +++ limit = (1 << kLenNumHighBits); +++ } +++ } +++ TREE_DECODE(probLen, limit, len); +++ len += offset; +++ } +++ +++ if (state >= kNumStates) +++ { +++ UInt32 distance; +++ prob = probs + PosSlot + +++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); +++ TREE_6_DECODE(prob, distance); +++ if (distance >= kStartPosModelIndex) +++ { +++ unsigned posSlot = (unsigned)distance; +++ int numDirectBits = (int)(((distance >> 1) - 1)); +++ distance = (2 | (distance & 1)); +++ if (posSlot < kEndPosModelIndex) +++ { +++ distance <<= numDirectBits; +++ prob = probs + SpecPos + distance - posSlot - 1; +++ { +++ UInt32 mask = 1; +++ unsigned i = 1; +++ do +++ { +++ GET_BIT2(prob + i, i, ; , distance |= mask); +++ mask <<= 1; +++ } +++ while (--numDirectBits != 0); +++ } +++ } +++ else +++ { +++ numDirectBits -= kNumAlignBits; +++ do +++ { +++ NORMALIZE +++ range >>= 1; +++ +++ { +++ UInt32 t; +++ code -= range; +++ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ +++ distance = (distance << 1) + (t + 1); +++ code += range & t; +++ } +++ /* +++ distance <<= 1; +++ if (code >= range) +++ { +++ code -= range; +++ distance |= 1; +++ } +++ */ +++ } +++ while (--numDirectBits != 0); +++ prob = probs + Align; +++ distance <<= kNumAlignBits; +++ { +++ unsigned i = 1; +++ GET_BIT2(prob + i, i, ; , distance |= 1); +++ GET_BIT2(prob + i, i, ; , distance |= 2); +++ GET_BIT2(prob + i, i, ; , distance |= 4); +++ GET_BIT2(prob + i, i, ; , distance |= 8); +++ } +++ if (distance == (UInt32)0xFFFFFFFF) +++ { +++ len += kMatchSpecLenStart; +++ state -= kNumStates; +++ break; +++ } +++ } +++ } +++ rep3 = rep2; +++ rep2 = rep1; +++ rep1 = rep0; +++ rep0 = distance + 1; +++ if (checkDicSize == 0) +++ { +++ if (distance >= processedPos) +++ return SZ_ERROR_DATA; +++ } +++ else if (distance >= checkDicSize) +++ return SZ_ERROR_DATA; +++ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; +++ } +++ +++ len += kMatchMinLen; +++ +++ if (limit == dicPos) +++ return SZ_ERROR_DATA; +++ { +++ SizeT rem = limit - dicPos; +++ unsigned curLen = ((rem < len) ? (unsigned)rem : len); +++ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); +++ +++ processedPos += curLen; +++ +++ len -= curLen; +++ if (pos + curLen <= dicBufSize) +++ { +++ Byte *dest = dic + dicPos; +++ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; +++ const Byte *lim = dest + curLen; +++ dicPos += curLen; +++ do +++ *(dest) = (Byte)*(dest + src); +++ while (++dest != lim); +++ } +++ else +++ { +++ do +++ { +++ dic[dicPos++] = dic[pos]; +++ if (++pos == dicBufSize) +++ pos = 0; +++ } +++ while (--curLen != 0); +++ } +++ } +++ } +++ } +++ while (dicPos < limit && buf < bufLimit); +++ NORMALIZE; +++ p->buf = buf; +++ p->range = range; +++ p->code = code; +++ p->remainLen = len; +++ p->dicPos = dicPos; +++ p->processedPos = processedPos; +++ p->reps[0] = rep0; +++ p->reps[1] = rep1; +++ p->reps[2] = rep2; +++ p->reps[3] = rep3; +++ p->state = state; +++ +++ return SZ_OK; +++} +++ +++static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +++{ +++ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) +++ { +++ Byte *dic = p->dic; +++ SizeT dicPos = p->dicPos; +++ SizeT dicBufSize = p->dicBufSize; +++ unsigned len = p->remainLen; +++ UInt32 rep0 = p->reps[0]; +++ if (limit - dicPos < len) +++ len = (unsigned)(limit - dicPos); +++ +++ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) +++ p->checkDicSize = p->prop.dicSize; +++ +++ p->processedPos += len; +++ p->remainLen -= len; +++ while (len-- != 0) +++ { +++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; +++ dicPos++; +++ } +++ p->dicPos = dicPos; +++ } +++} +++ +++static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +++{ +++ do +++ { +++ SizeT limit2 = limit; +++ if (p->checkDicSize == 0) +++ { +++ UInt32 rem = p->prop.dicSize - p->processedPos; +++ if (limit - p->dicPos > rem) +++ limit2 = p->dicPos + rem; +++ } +++ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); +++ if (p->processedPos >= p->prop.dicSize) +++ p->checkDicSize = p->prop.dicSize; +++ LzmaDec_WriteRem(p, limit); +++ } +++ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); +++ +++ if (p->remainLen > kMatchSpecLenStart) +++ { +++ p->remainLen = kMatchSpecLenStart; +++ } +++ return 0; +++} +++ +++typedef enum +++{ +++ DUMMY_ERROR, /* unexpected end of input stream */ +++ DUMMY_LIT, +++ DUMMY_MATCH, +++ DUMMY_REP +++} ELzmaDummy; +++ +++static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +++{ +++ UInt32 range = p->range; +++ UInt32 code = p->code; +++ const Byte *bufLimit = buf + inSize; +++ CLzmaProb *probs = p->probs; +++ unsigned state = p->state; +++ ELzmaDummy res; +++ +++ { +++ CLzmaProb *prob; +++ UInt32 bound; +++ unsigned ttt; +++ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); +++ +++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; +++ IF_BIT_0_CHECK(prob) +++ { +++ UPDATE_0_CHECK +++ +++ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ +++ +++ prob = probs + Literal; +++ if (p->checkDicSize != 0 || p->processedPos != 0) +++ prob += (LZMA_LIT_SIZE * +++ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + +++ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); +++ +++ if (state < kNumLitStates) +++ { +++ unsigned symbol = 1; +++ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); +++ } +++ else +++ { +++ unsigned matchByte = p->dic[p->dicPos - p->reps[0] + +++ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; +++ unsigned offs = 0x100; +++ unsigned symbol = 1; +++ do +++ { +++ unsigned bit; +++ CLzmaProb *probLit; +++ matchByte <<= 1; +++ bit = (matchByte & offs); +++ probLit = prob + offs + bit + symbol; +++ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) +++ } +++ while (symbol < 0x100); +++ } +++ res = DUMMY_LIT; +++ } +++ else +++ { +++ unsigned len; +++ UPDATE_1_CHECK; +++ +++ prob = probs + IsRep + state; +++ IF_BIT_0_CHECK(prob) +++ { +++ UPDATE_0_CHECK; +++ state = 0; +++ prob = probs + LenCoder; +++ res = DUMMY_MATCH; +++ } +++ else +++ { +++ UPDATE_1_CHECK; +++ res = DUMMY_REP; +++ prob = probs + IsRepG0 + state; +++ IF_BIT_0_CHECK(prob) +++ { +++ UPDATE_0_CHECK; +++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; +++ IF_BIT_0_CHECK(prob) +++ { +++ UPDATE_0_CHECK; +++ NORMALIZE_CHECK; +++ return DUMMY_REP; +++ } +++ else +++ { +++ UPDATE_1_CHECK; +++ } +++ } +++ else +++ { +++ UPDATE_1_CHECK; +++ prob = probs + IsRepG1 + state; +++ IF_BIT_0_CHECK(prob) +++ { +++ UPDATE_0_CHECK; +++ } +++ else +++ { +++ UPDATE_1_CHECK; +++ prob = probs + IsRepG2 + state; +++ IF_BIT_0_CHECK(prob) +++ { +++ UPDATE_0_CHECK; +++ } +++ else +++ { +++ UPDATE_1_CHECK; +++ } +++ } +++ } +++ state = kNumStates; +++ prob = probs + RepLenCoder; +++ } +++ { +++ unsigned limit, offset; +++ CLzmaProb *probLen = prob + LenChoice; +++ IF_BIT_0_CHECK(probLen) +++ { +++ UPDATE_0_CHECK; +++ probLen = prob + LenLow + (posState << kLenNumLowBits); +++ offset = 0; +++ limit = 1 << kLenNumLowBits; +++ } +++ else +++ { +++ UPDATE_1_CHECK; +++ probLen = prob + LenChoice2; +++ IF_BIT_0_CHECK(probLen) +++ { +++ UPDATE_0_CHECK; +++ probLen = prob + LenMid + (posState << kLenNumMidBits); +++ offset = kLenNumLowSymbols; +++ limit = 1 << kLenNumMidBits; +++ } +++ else +++ { +++ UPDATE_1_CHECK; +++ probLen = prob + LenHigh; +++ offset = kLenNumLowSymbols + kLenNumMidSymbols; +++ limit = 1 << kLenNumHighBits; +++ } +++ } +++ TREE_DECODE_CHECK(probLen, limit, len); +++ len += offset; +++ } +++ +++ if (state < 4) +++ { +++ unsigned posSlot; +++ prob = probs + PosSlot + +++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << +++ kNumPosSlotBits); +++ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); +++ if (posSlot >= kStartPosModelIndex) +++ { +++ int numDirectBits = ((posSlot >> 1) - 1); +++ +++ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ +++ +++ if (posSlot < kEndPosModelIndex) +++ { +++ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; +++ } +++ else +++ { +++ numDirectBits -= kNumAlignBits; +++ do +++ { +++ NORMALIZE_CHECK +++ range >>= 1; +++ code -= range & (((code - range) >> 31) - 1); +++ /* if (code >= range) code -= range; */ +++ } +++ while (--numDirectBits != 0); +++ prob = probs + Align; +++ numDirectBits = kNumAlignBits; +++ } +++ { +++ unsigned i = 1; +++ do +++ { +++ GET_BIT_CHECK(prob + i, i); +++ } +++ while (--numDirectBits != 0); +++ } +++ } +++ } +++ } +++ } +++ NORMALIZE_CHECK; +++ return res; +++} +++ +++ +++static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +++{ +++ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); +++ p->range = 0xFFFFFFFF; +++ p->needFlush = 0; +++} +++ +++void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +++{ +++ p->needFlush = 1; +++ p->remainLen = 0; +++ p->tempBufSize = 0; +++ +++ if (initDic) +++ { +++ p->processedPos = 0; +++ p->checkDicSize = 0; +++ p->needInitState = 1; +++ } +++ if (initState) +++ p->needInitState = 1; +++} +++ +++void LzmaDec_Init(CLzmaDec *p) +++{ +++ p->dicPos = 0; +++ LzmaDec_InitDicAndState(p, True, True); +++} +++ +++static void LzmaDec_InitStateReal(CLzmaDec *p) +++{ +++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); +++ UInt32 i; +++ CLzmaProb *probs = p->probs; +++ for (i = 0; i < numProbs; i++) +++ probs[i] = kBitModelTotal >> 1; +++ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; +++ p->state = 0; +++ p->needInitState = 0; +++} +++ +++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, +++ ELzmaFinishMode finishMode, ELzmaStatus *status) +++{ +++ SizeT inSize = *srcLen; +++ (*srcLen) = 0; +++ LzmaDec_WriteRem(p, dicLimit); +++ +++ *status = LZMA_STATUS_NOT_SPECIFIED; +++ +++ while (p->remainLen != kMatchSpecLenStart) +++ { +++ int checkEndMarkNow; +++ +++ if (p->needFlush != 0) +++ { +++ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) +++ p->tempBuf[p->tempBufSize++] = *src++; +++ if (p->tempBufSize < RC_INIT_SIZE) +++ { +++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; +++ return SZ_OK; +++ } +++ if (p->tempBuf[0] != 0) +++ return SZ_ERROR_DATA; +++ +++ LzmaDec_InitRc(p, p->tempBuf); +++ p->tempBufSize = 0; +++ } +++ +++ checkEndMarkNow = 0; +++ if (p->dicPos >= dicLimit) +++ { +++ if (p->remainLen == 0 && p->code == 0) +++ { +++ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; +++ return SZ_OK; +++ } +++ if (finishMode == LZMA_FINISH_ANY) +++ { +++ *status = LZMA_STATUS_NOT_FINISHED; +++ return SZ_OK; +++ } +++ if (p->remainLen != 0) +++ { +++ *status = LZMA_STATUS_NOT_FINISHED; +++ return SZ_ERROR_DATA; +++ } +++ checkEndMarkNow = 1; +++ } +++ +++ if (p->needInitState) +++ LzmaDec_InitStateReal(p); +++ +++ if (p->tempBufSize == 0) +++ { +++ SizeT processed; +++ const Byte *bufLimit; +++ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) +++ { +++ int dummyRes = LzmaDec_TryDummy(p, src, inSize); +++ if (dummyRes == DUMMY_ERROR) +++ { +++ memcpy(p->tempBuf, src, inSize); +++ p->tempBufSize = (unsigned)inSize; +++ (*srcLen) += inSize; +++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; +++ return SZ_OK; +++ } +++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH) +++ { +++ *status = LZMA_STATUS_NOT_FINISHED; +++ return SZ_ERROR_DATA; +++ } +++ bufLimit = src; +++ } +++ else +++ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; +++ p->buf = src; +++ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) +++ return SZ_ERROR_DATA; +++ processed = (SizeT)(p->buf - src); +++ (*srcLen) += processed; +++ src += processed; +++ inSize -= processed; +++ } +++ else +++ { +++ unsigned rem = p->tempBufSize, lookAhead = 0; +++ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) +++ p->tempBuf[rem++] = src[lookAhead++]; +++ p->tempBufSize = rem; +++ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) +++ { +++ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); +++ if (dummyRes == DUMMY_ERROR) +++ { +++ (*srcLen) += lookAhead; +++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; +++ return SZ_OK; +++ } +++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH) +++ { +++ *status = LZMA_STATUS_NOT_FINISHED; +++ return SZ_ERROR_DATA; +++ } +++ } +++ p->buf = p->tempBuf; +++ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) +++ return SZ_ERROR_DATA; +++ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); +++ (*srcLen) += lookAhead; +++ src += lookAhead; +++ inSize -= lookAhead; +++ p->tempBufSize = 0; +++ } +++ } +++ if (p->code == 0) +++ *status = LZMA_STATUS_FINISHED_WITH_MARK; +++ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +++} +++ +++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +++{ +++ SizeT outSize = *destLen; +++ SizeT inSize = *srcLen; +++ *srcLen = *destLen = 0; +++ for (;;) +++ { +++ SizeT inSizeCur = inSize, outSizeCur, dicPos; +++ ELzmaFinishMode curFinishMode; +++ SRes res; +++ if (p->dicPos == p->dicBufSize) +++ p->dicPos = 0; +++ dicPos = p->dicPos; +++ if (outSize > p->dicBufSize - dicPos) +++ { +++ outSizeCur = p->dicBufSize; +++ curFinishMode = LZMA_FINISH_ANY; +++ } +++ else +++ { +++ outSizeCur = dicPos + outSize; +++ curFinishMode = finishMode; +++ } +++ +++ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); +++ src += inSizeCur; +++ inSize -= inSizeCur; +++ *srcLen += inSizeCur; +++ outSizeCur = p->dicPos - dicPos; +++ memcpy(dest, p->dic + dicPos, outSizeCur); +++ dest += outSizeCur; +++ outSize -= outSizeCur; +++ *destLen += outSizeCur; +++ if (res != 0) +++ return res; +++ if (outSizeCur == 0 || outSize == 0) +++ return SZ_OK; +++ } +++} +++ +++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +++{ +++ alloc->Free(alloc, p->probs); +++ p->probs = 0; +++} +++ +++static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +++{ +++ alloc->Free(alloc, p->dic); +++ p->dic = 0; +++} +++ +++void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +++{ +++ LzmaDec_FreeProbs(p, alloc); +++ LzmaDec_FreeDict(p, alloc); +++} +++ +++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +++{ +++ UInt32 dicSize; +++ Byte d; +++ +++ if (size < LZMA_PROPS_SIZE) +++ return SZ_ERROR_UNSUPPORTED; +++ else +++ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); +++ +++ if (dicSize < LZMA_DIC_MIN) +++ dicSize = LZMA_DIC_MIN; +++ p->dicSize = dicSize; +++ +++ d = data[0]; +++ if (d >= (9 * 5 * 5)) +++ return SZ_ERROR_UNSUPPORTED; +++ +++ p->lc = d % 9; +++ d /= 9; +++ p->pb = d / 5; +++ p->lp = d % 5; +++ +++ return SZ_OK; +++} +++ +++static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +++{ +++ UInt32 numProbs = LzmaProps_GetNumProbs(propNew); +++ if (p->probs == 0 || numProbs != p->numProbs) +++ { +++ LzmaDec_FreeProbs(p, alloc); +++ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); +++ p->numProbs = numProbs; +++ if (p->probs == 0) +++ return SZ_ERROR_MEM; +++ } +++ return SZ_OK; +++} +++ +++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +++{ +++ CLzmaProps propNew; +++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); +++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); +++ p->prop = propNew; +++ return SZ_OK; +++} +++ +++SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +++{ +++ CLzmaProps propNew; +++ SizeT dicBufSize; +++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); +++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); +++ dicBufSize = propNew.dicSize; +++ if (p->dic == 0 || dicBufSize != p->dicBufSize) +++ { +++ LzmaDec_FreeDict(p, alloc); +++ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); +++ if (p->dic == 0) +++ { +++ LzmaDec_FreeProbs(p, alloc); +++ return SZ_ERROR_MEM; +++ } +++ } +++ p->dicBufSize = dicBufSize; +++ p->prop = propNew; +++ return SZ_OK; +++} +++ +++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, +++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, +++ ELzmaStatus *status, ISzAlloc *alloc) +++{ +++ CLzmaDec p; +++ SRes res; +++ SizeT inSize = *srcLen; +++ SizeT outSize = *destLen; +++ *srcLen = *destLen = 0; +++ if (inSize < RC_INIT_SIZE) +++ return SZ_ERROR_INPUT_EOF; +++ +++ LzmaDec_Construct(&p); +++ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); +++ if (res != 0) +++ return res; +++ p.dic = dest; +++ p.dicBufSize = outSize; +++ +++ LzmaDec_Init(&p); +++ +++ *srcLen = inSize; +++ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); +++ +++ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) +++ res = SZ_ERROR_INPUT_EOF; +++ +++ (*destLen) = p.dicPos; +++ LzmaDec_FreeProbs(&p, alloc); +++ return res; +++} ++--- /dev/null +++++ b/lib/lzma/LzmaEnc.c ++@@ -0,0 +1,2271 @@ +++/* LzmaEnc.c -- LZMA Encoder +++2009-11-24 : Igor Pavlov : Public domain */ +++ +++#include +++ +++/* #define SHOW_STAT */ +++/* #define SHOW_STAT2 */ +++ +++#if defined(SHOW_STAT) || defined(SHOW_STAT2) +++#include +++#endif +++ +++#include "LzmaEnc.h" +++ +++/* disable MT */ +++#define _7ZIP_ST +++ +++#include "LzFind.h" +++#ifndef _7ZIP_ST +++#include "LzFindMt.h" +++#endif +++ +++#ifdef SHOW_STAT +++static int ttt = 0; +++#endif +++ +++#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) +++ +++#define kBlockSize (9 << 10) +++#define kUnpackBlockSize (1 << 18) +++#define kMatchArraySize (1 << 21) +++#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) +++ +++#define kNumMaxDirectBits (31) +++ +++#define kNumTopBits 24 +++#define kTopValue ((UInt32)1 << kNumTopBits) +++ +++#define kNumBitModelTotalBits 11 +++#define kBitModelTotal (1 << kNumBitModelTotalBits) +++#define kNumMoveBits 5 +++#define kProbInitValue (kBitModelTotal >> 1) +++ +++#define kNumMoveReducingBits 4 +++#define kNumBitPriceShiftBits 4 +++#define kBitPrice (1 << kNumBitPriceShiftBits) +++ +++void LzmaEncProps_Init(CLzmaEncProps *p) +++{ +++ p->level = 5; +++ p->dictSize = p->mc = 0; +++ p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; +++ p->writeEndMark = 0; +++} +++ +++void LzmaEncProps_Normalize(CLzmaEncProps *p) +++{ +++ int level = p->level; +++ if (level < 0) level = 5; +++ p->level = level; +++ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); +++ if (p->lc < 0) p->lc = 3; +++ if (p->lp < 0) p->lp = 0; +++ if (p->pb < 0) p->pb = 2; +++ if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); +++ if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); +++ if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); +++ if (p->numHashBytes < 0) p->numHashBytes = 4; +++ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); +++ if (p->numThreads < 0) +++ p->numThreads = +++ #ifndef _7ZIP_ST +++ ((p->btMode && p->algo) ? 2 : 1); +++ #else +++ 1; +++ #endif +++} +++ +++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +++{ +++ CLzmaEncProps props = *props2; +++ LzmaEncProps_Normalize(&props); +++ return props.dictSize; +++} +++ +++/* #define LZMA_LOG_BSR */ +++/* Define it for Intel's CPU */ +++ +++ +++#ifdef LZMA_LOG_BSR +++ +++#define kDicLogSizeMaxCompress 30 +++ +++#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } +++ +++UInt32 GetPosSlot1(UInt32 pos) +++{ +++ UInt32 res; +++ BSR2_RET(pos, res); +++ return res; +++} +++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +++#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } +++ +++#else +++ +++#define kNumLogBits (9 + (int)sizeof(size_t) / 2) +++#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) +++ +++void LzmaEnc_FastPosInit(Byte *g_FastPos) +++{ +++ int c = 2, slotFast; +++ g_FastPos[0] = 0; +++ g_FastPos[1] = 1; +++ +++ for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) +++ { +++ UInt32 k = (1 << ((slotFast >> 1) - 1)); +++ UInt32 j; +++ for (j = 0; j < k; j++, c++) +++ g_FastPos[c] = (Byte)slotFast; +++ } +++} +++ +++#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ +++ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ +++ res = p->g_FastPos[pos >> i] + (i * 2); } +++/* +++#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ +++ p->g_FastPos[pos >> 6] + 12 : \ +++ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +++*/ +++ +++#define GetPosSlot1(pos) p->g_FastPos[pos] +++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +++#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } +++ +++#endif +++ +++ +++#define LZMA_NUM_REPS 4 +++ +++typedef unsigned CState; +++ +++typedef struct +++{ +++ UInt32 price; +++ +++ CState state; +++ int prev1IsChar; +++ int prev2; +++ +++ UInt32 posPrev2; +++ UInt32 backPrev2; +++ +++ UInt32 posPrev; +++ UInt32 backPrev; +++ UInt32 backs[LZMA_NUM_REPS]; +++} COptimal; +++ +++#define kNumOpts (1 << 12) +++ +++#define kNumLenToPosStates 4 +++#define kNumPosSlotBits 6 +++#define kDicLogSizeMin 0 +++#define kDicLogSizeMax 32 +++#define kDistTableSizeMax (kDicLogSizeMax * 2) +++ +++ +++#define kNumAlignBits 4 +++#define kAlignTableSize (1 << kNumAlignBits) +++#define kAlignMask (kAlignTableSize - 1) +++ +++#define kStartPosModelIndex 4 +++#define kEndPosModelIndex 14 +++#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) +++ +++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) +++ +++#ifdef _LZMA_PROB32 +++#define CLzmaProb UInt32 +++#else +++#define CLzmaProb UInt16 +++#endif +++ +++#define LZMA_PB_MAX 4 +++#define LZMA_LC_MAX 8 +++#define LZMA_LP_MAX 4 +++ +++#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) +++ +++ +++#define kLenNumLowBits 3 +++#define kLenNumLowSymbols (1 << kLenNumLowBits) +++#define kLenNumMidBits 3 +++#define kLenNumMidSymbols (1 << kLenNumMidBits) +++#define kLenNumHighBits 8 +++#define kLenNumHighSymbols (1 << kLenNumHighBits) +++ +++#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) +++ +++#define LZMA_MATCH_LEN_MIN 2 +++#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) +++ +++#define kNumStates 12 +++ +++typedef struct +++{ +++ CLzmaProb choice; +++ CLzmaProb choice2; +++ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; +++ CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; +++ CLzmaProb high[kLenNumHighSymbols]; +++} CLenEnc; +++ +++typedef struct +++{ +++ CLenEnc p; +++ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; +++ UInt32 tableSize; +++ UInt32 counters[LZMA_NUM_PB_STATES_MAX]; +++} CLenPriceEnc; +++ +++typedef struct +++{ +++ UInt32 range; +++ Byte cache; +++ UInt64 low; +++ UInt64 cacheSize; +++ Byte *buf; +++ Byte *bufLim; +++ Byte *bufBase; +++ ISeqOutStream *outStream; +++ UInt64 processed; +++ SRes res; +++} CRangeEnc; +++ +++typedef struct +++{ +++ CLzmaProb *litProbs; +++ +++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; +++ CLzmaProb isRep[kNumStates]; +++ CLzmaProb isRepG0[kNumStates]; +++ CLzmaProb isRepG1[kNumStates]; +++ CLzmaProb isRepG2[kNumStates]; +++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; +++ +++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; +++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; +++ CLzmaProb posAlignEncoder[1 << kNumAlignBits]; +++ +++ CLenPriceEnc lenEnc; +++ CLenPriceEnc repLenEnc; +++ +++ UInt32 reps[LZMA_NUM_REPS]; +++ UInt32 state; +++} CSaveState; +++ +++typedef struct +++{ +++ IMatchFinder matchFinder; +++ void *matchFinderObj; +++ +++ #ifndef _7ZIP_ST +++ Bool mtMode; +++ CMatchFinderMt matchFinderMt; +++ #endif +++ +++ CMatchFinder matchFinderBase; +++ +++ #ifndef _7ZIP_ST +++ Byte pad[128]; +++ #endif +++ +++ UInt32 optimumEndIndex; +++ UInt32 optimumCurrentIndex; +++ +++ UInt32 longestMatchLength; +++ UInt32 numPairs; +++ UInt32 numAvail; +++ COptimal opt[kNumOpts]; +++ +++ #ifndef LZMA_LOG_BSR +++ Byte g_FastPos[1 << kNumLogBits]; +++ #endif +++ +++ UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; +++ UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; +++ UInt32 numFastBytes; +++ UInt32 additionalOffset; +++ UInt32 reps[LZMA_NUM_REPS]; +++ UInt32 state; +++ +++ UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; +++ UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; +++ UInt32 alignPrices[kAlignTableSize]; +++ UInt32 alignPriceCount; +++ +++ UInt32 distTableSize; +++ +++ unsigned lc, lp, pb; +++ unsigned lpMask, pbMask; +++ +++ CLzmaProb *litProbs; +++ +++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; +++ CLzmaProb isRep[kNumStates]; +++ CLzmaProb isRepG0[kNumStates]; +++ CLzmaProb isRepG1[kNumStates]; +++ CLzmaProb isRepG2[kNumStates]; +++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; +++ +++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; +++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; +++ CLzmaProb posAlignEncoder[1 << kNumAlignBits]; +++ +++ CLenPriceEnc lenEnc; +++ CLenPriceEnc repLenEnc; +++ +++ unsigned lclp; +++ +++ Bool fastMode; +++ +++ CRangeEnc rc; +++ +++ Bool writeEndMark; +++ UInt64 nowPos64; +++ UInt32 matchPriceCount; +++ Bool finished; +++ Bool multiThread; +++ +++ SRes result; +++ UInt32 dictSize; +++ UInt32 matchFinderCycles; +++ +++ int needInit; +++ +++ CSaveState saveState; +++} CLzmaEnc; +++ +++void LzmaEnc_SaveState(CLzmaEncHandle pp) +++{ +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ CSaveState *dest = &p->saveState; +++ int i; +++ dest->lenEnc = p->lenEnc; +++ dest->repLenEnc = p->repLenEnc; +++ dest->state = p->state; +++ +++ for (i = 0; i < kNumStates; i++) +++ { +++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); +++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); +++ } +++ for (i = 0; i < kNumLenToPosStates; i++) +++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); +++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); +++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); +++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); +++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); +++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); +++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); +++ memcpy(dest->reps, p->reps, sizeof(p->reps)); +++ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); +++} +++ +++void LzmaEnc_RestoreState(CLzmaEncHandle pp) +++{ +++ CLzmaEnc *dest = (CLzmaEnc *)pp; +++ const CSaveState *p = &dest->saveState; +++ int i; +++ dest->lenEnc = p->lenEnc; +++ dest->repLenEnc = p->repLenEnc; +++ dest->state = p->state; +++ +++ for (i = 0; i < kNumStates; i++) +++ { +++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); +++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); +++ } +++ for (i = 0; i < kNumLenToPosStates; i++) +++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); +++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); +++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); +++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); +++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); +++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); +++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); +++ memcpy(dest->reps, p->reps, sizeof(p->reps)); +++ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); +++} +++ +++SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +++{ +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ CLzmaEncProps props = *props2; +++ LzmaEncProps_Normalize(&props); +++ +++ if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || +++ props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) +++ return SZ_ERROR_PARAM; +++ p->dictSize = props.dictSize; +++ p->matchFinderCycles = props.mc; +++ { +++ unsigned fb = props.fb; +++ if (fb < 5) +++ fb = 5; +++ if (fb > LZMA_MATCH_LEN_MAX) +++ fb = LZMA_MATCH_LEN_MAX; +++ p->numFastBytes = fb; +++ } +++ p->lc = props.lc; +++ p->lp = props.lp; +++ p->pb = props.pb; +++ p->fastMode = (props.algo == 0); +++ p->matchFinderBase.btMode = props.btMode; +++ { +++ UInt32 numHashBytes = 4; +++ if (props.btMode) +++ { +++ if (props.numHashBytes < 2) +++ numHashBytes = 2; +++ else if (props.numHashBytes < 4) +++ numHashBytes = props.numHashBytes; +++ } +++ p->matchFinderBase.numHashBytes = numHashBytes; +++ } +++ +++ p->matchFinderBase.cutValue = props.mc; +++ +++ p->writeEndMark = props.writeEndMark; +++ +++ #ifndef _7ZIP_ST +++ /* +++ if (newMultiThread != _multiThread) +++ { +++ ReleaseMatchFinder(); +++ _multiThread = newMultiThread; +++ } +++ */ +++ p->multiThread = (props.numThreads > 1); +++ #endif +++ +++ return SZ_OK; +++} +++ +++static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +++static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +++static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +++static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; +++ +++#define IsCharState(s) ((s) < 7) +++ +++#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) +++ +++#define kInfinityPrice (1 << 30) +++ +++static void RangeEnc_Construct(CRangeEnc *p) +++{ +++ p->outStream = 0; +++ p->bufBase = 0; +++} +++ +++#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) +++ +++#define RC_BUF_SIZE (1 << 16) +++static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) +++{ +++ if (p->bufBase == 0) +++ { +++ p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); +++ if (p->bufBase == 0) +++ return 0; +++ p->bufLim = p->bufBase + RC_BUF_SIZE; +++ } +++ return 1; +++} +++ +++static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) +++{ +++ alloc->Free(alloc, p->bufBase); +++ p->bufBase = 0; +++} +++ +++static void RangeEnc_Init(CRangeEnc *p) +++{ +++ /* Stream.Init(); */ +++ p->low = 0; +++ p->range = 0xFFFFFFFF; +++ p->cacheSize = 1; +++ p->cache = 0; +++ +++ p->buf = p->bufBase; +++ +++ p->processed = 0; +++ p->res = SZ_OK; +++} +++ +++static void RangeEnc_FlushStream(CRangeEnc *p) +++{ +++ size_t num; +++ if (p->res != SZ_OK) +++ return; +++ num = p->buf - p->bufBase; +++ if (num != p->outStream->Write(p->outStream, p->bufBase, num)) +++ p->res = SZ_ERROR_WRITE; +++ p->processed += num; +++ p->buf = p->bufBase; +++} +++ +++static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +++{ +++ if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) +++ { +++ Byte temp = p->cache; +++ do +++ { +++ Byte *buf = p->buf; +++ *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); +++ p->buf = buf; +++ if (buf == p->bufLim) +++ RangeEnc_FlushStream(p); +++ temp = 0xFF; +++ } +++ while (--p->cacheSize != 0); +++ p->cache = (Byte)((UInt32)p->low >> 24); +++ } +++ p->cacheSize++; +++ p->low = (UInt32)p->low << 8; +++} +++ +++static void RangeEnc_FlushData(CRangeEnc *p) +++{ +++ int i; +++ for (i = 0; i < 5; i++) +++ RangeEnc_ShiftLow(p); +++} +++ +++static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) +++{ +++ do +++ { +++ p->range >>= 1; +++ p->low += p->range & (0 - ((value >> --numBits) & 1)); +++ if (p->range < kTopValue) +++ { +++ p->range <<= 8; +++ RangeEnc_ShiftLow(p); +++ } +++ } +++ while (numBits != 0); +++} +++ +++static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) +++{ +++ UInt32 ttt = *prob; +++ UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; +++ if (symbol == 0) +++ { +++ p->range = newBound; +++ ttt += (kBitModelTotal - ttt) >> kNumMoveBits; +++ } +++ else +++ { +++ p->low += newBound; +++ p->range -= newBound; +++ ttt -= ttt >> kNumMoveBits; +++ } +++ *prob = (CLzmaProb)ttt; +++ if (p->range < kTopValue) +++ { +++ p->range <<= 8; +++ RangeEnc_ShiftLow(p); +++ } +++} +++ +++static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) +++{ +++ symbol |= 0x100; +++ do +++ { +++ RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); +++ symbol <<= 1; +++ } +++ while (symbol < 0x10000); +++} +++ +++static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) +++{ +++ UInt32 offs = 0x100; +++ symbol |= 0x100; +++ do +++ { +++ matchByte <<= 1; +++ RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); +++ symbol <<= 1; +++ offs &= ~(matchByte ^ symbol); +++ } +++ while (symbol < 0x10000); +++} +++ +++void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +++{ +++ UInt32 i; +++ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) +++ { +++ const int kCyclesBits = kNumBitPriceShiftBits; +++ UInt32 w = i; +++ UInt32 bitCount = 0; +++ int j; +++ for (j = 0; j < kCyclesBits; j++) +++ { +++ w = w * w; +++ bitCount <<= 1; +++ while (w >= ((UInt32)1 << 16)) +++ { +++ w >>= 1; +++ bitCount++; +++ } +++ } +++ ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); +++ } +++} +++ +++ +++#define GET_PRICE(prob, symbol) \ +++ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; +++ +++#define GET_PRICEa(prob, symbol) \ +++ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; +++ +++#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +++#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] +++ +++#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +++#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] +++ +++static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) +++{ +++ UInt32 price = 0; +++ symbol |= 0x100; +++ do +++ { +++ price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); +++ symbol <<= 1; +++ } +++ while (symbol < 0x10000); +++ return price; +++} +++ +++static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) +++{ +++ UInt32 price = 0; +++ UInt32 offs = 0x100; +++ symbol |= 0x100; +++ do +++ { +++ matchByte <<= 1; +++ price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); +++ symbol <<= 1; +++ offs &= ~(matchByte ^ symbol); +++ } +++ while (symbol < 0x10000); +++ return price; +++} +++ +++ +++static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +++{ +++ UInt32 m = 1; +++ int i; +++ for (i = numBitLevels; i != 0;) +++ { +++ UInt32 bit; +++ i--; +++ bit = (symbol >> i) & 1; +++ RangeEnc_EncodeBit(rc, probs + m, bit); +++ m = (m << 1) | bit; +++ } +++} +++ +++static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +++{ +++ UInt32 m = 1; +++ int i; +++ for (i = 0; i < numBitLevels; i++) +++ { +++ UInt32 bit = symbol & 1; +++ RangeEnc_EncodeBit(rc, probs + m, bit); +++ m = (m << 1) | bit; +++ symbol >>= 1; +++ } +++} +++ +++static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +++{ +++ UInt32 price = 0; +++ symbol |= (1 << numBitLevels); +++ while (symbol != 1) +++ { +++ price += GET_PRICEa(probs[symbol >> 1], symbol & 1); +++ symbol >>= 1; +++ } +++ return price; +++} +++ +++static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +++{ +++ UInt32 price = 0; +++ UInt32 m = 1; +++ int i; +++ for (i = numBitLevels; i != 0; i--) +++ { +++ UInt32 bit = symbol & 1; +++ symbol >>= 1; +++ price += GET_PRICEa(probs[m], bit); +++ m = (m << 1) | bit; +++ } +++ return price; +++} +++ +++ +++static void LenEnc_Init(CLenEnc *p) +++{ +++ unsigned i; +++ p->choice = p->choice2 = kProbInitValue; +++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) +++ p->low[i] = kProbInitValue; +++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) +++ p->mid[i] = kProbInitValue; +++ for (i = 0; i < kLenNumHighSymbols; i++) +++ p->high[i] = kProbInitValue; +++} +++ +++static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) +++{ +++ if (symbol < kLenNumLowSymbols) +++ { +++ RangeEnc_EncodeBit(rc, &p->choice, 0); +++ RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); +++ } +++ else +++ { +++ RangeEnc_EncodeBit(rc, &p->choice, 1); +++ if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) +++ { +++ RangeEnc_EncodeBit(rc, &p->choice2, 0); +++ RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); +++ } +++ else +++ { +++ RangeEnc_EncodeBit(rc, &p->choice2, 1); +++ RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); +++ } +++ } +++} +++ +++static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) +++{ +++ UInt32 a0 = GET_PRICE_0a(p->choice); +++ UInt32 a1 = GET_PRICE_1a(p->choice); +++ UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); +++ UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); +++ UInt32 i = 0; +++ for (i = 0; i < kLenNumLowSymbols; i++) +++ { +++ if (i >= numSymbols) +++ return; +++ prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); +++ } +++ for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) +++ { +++ if (i >= numSymbols) +++ return; +++ prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); +++ } +++ for (; i < numSymbols; i++) +++ prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); +++} +++ +++static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) +++{ +++ LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); +++ p->counters[posState] = p->tableSize; +++} +++ +++static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) +++{ +++ UInt32 posState; +++ for (posState = 0; posState < numPosStates; posState++) +++ LenPriceEnc_UpdateTable(p, posState, ProbPrices); +++} +++ +++static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) +++{ +++ LenEnc_Encode(&p->p, rc, symbol, posState); +++ if (updatePrice) +++ if (--p->counters[posState] == 0) +++ LenPriceEnc_UpdateTable(p, posState, ProbPrices); +++} +++ +++ +++ +++ +++static void MovePos(CLzmaEnc *p, UInt32 num) +++{ +++ #ifdef SHOW_STAT +++ ttt += num; +++ printf("\n MovePos %d", num); +++ #endif +++ if (num != 0) +++ { +++ p->additionalOffset += num; +++ p->matchFinder.Skip(p->matchFinderObj, num); +++ } +++} +++ +++static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) +++{ +++ UInt32 lenRes = 0, numPairs; +++ p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +++ numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); +++ #ifdef SHOW_STAT +++ printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); +++ ttt++; +++ { +++ UInt32 i; +++ for (i = 0; i < numPairs; i += 2) +++ printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); +++ } +++ #endif +++ if (numPairs > 0) +++ { +++ lenRes = p->matches[numPairs - 2]; +++ if (lenRes == p->numFastBytes) +++ { +++ const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; +++ UInt32 distance = p->matches[numPairs - 1] + 1; +++ UInt32 numAvail = p->numAvail; +++ if (numAvail > LZMA_MATCH_LEN_MAX) +++ numAvail = LZMA_MATCH_LEN_MAX; +++ { +++ const Byte *pby2 = pby - distance; +++ for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); +++ } +++ } +++ } +++ p->additionalOffset++; +++ *numDistancePairsRes = numPairs; +++ return lenRes; +++} +++ +++ +++#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; +++#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; +++#define IsShortRep(p) ((p)->backPrev == 0) +++ +++static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) +++{ +++ return +++ GET_PRICE_0(p->isRepG0[state]) + +++ GET_PRICE_0(p->isRep0Long[state][posState]); +++} +++ +++static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) +++{ +++ UInt32 price; +++ if (repIndex == 0) +++ { +++ price = GET_PRICE_0(p->isRepG0[state]); +++ price += GET_PRICE_1(p->isRep0Long[state][posState]); +++ } +++ else +++ { +++ price = GET_PRICE_1(p->isRepG0[state]); +++ if (repIndex == 1) +++ price += GET_PRICE_0(p->isRepG1[state]); +++ else +++ { +++ price += GET_PRICE_1(p->isRepG1[state]); +++ price += GET_PRICE(p->isRepG2[state], repIndex - 2); +++ } +++ } +++ return price; +++} +++ +++static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) +++{ +++ return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + +++ GetPureRepPrice(p, repIndex, state, posState); +++} +++ +++static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) +++{ +++ UInt32 posMem = p->opt[cur].posPrev; +++ UInt32 backMem = p->opt[cur].backPrev; +++ p->optimumEndIndex = cur; +++ do +++ { +++ if (p->opt[cur].prev1IsChar) +++ { +++ MakeAsChar(&p->opt[posMem]) +++ p->opt[posMem].posPrev = posMem - 1; +++ if (p->opt[cur].prev2) +++ { +++ p->opt[posMem - 1].prev1IsChar = False; +++ p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; +++ p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; +++ } +++ } +++ { +++ UInt32 posPrev = posMem; +++ UInt32 backCur = backMem; +++ +++ backMem = p->opt[posPrev].backPrev; +++ posMem = p->opt[posPrev].posPrev; +++ +++ p->opt[posPrev].backPrev = backCur; +++ p->opt[posPrev].posPrev = cur; +++ cur = posPrev; +++ } +++ } +++ while (cur != 0); +++ *backRes = p->opt[0].backPrev; +++ p->optimumCurrentIndex = p->opt[0].posPrev; +++ return p->optimumCurrentIndex; +++} +++ +++#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) +++ +++static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) +++{ +++ UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; +++ UInt32 matchPrice, repMatchPrice, normalMatchPrice; +++ UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; +++ UInt32 *matches; +++ const Byte *data; +++ Byte curByte, matchByte; +++ if (p->optimumEndIndex != p->optimumCurrentIndex) +++ { +++ const COptimal *opt = &p->opt[p->optimumCurrentIndex]; +++ UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; +++ *backRes = opt->backPrev; +++ p->optimumCurrentIndex = opt->posPrev; +++ return lenRes; +++ } +++ p->optimumCurrentIndex = p->optimumEndIndex = 0; +++ +++ if (p->additionalOffset == 0) +++ mainLen = ReadMatchDistances(p, &numPairs); +++ else +++ { +++ mainLen = p->longestMatchLength; +++ numPairs = p->numPairs; +++ } +++ +++ numAvail = p->numAvail; +++ if (numAvail < 2) +++ { +++ *backRes = (UInt32)(-1); +++ return 1; +++ } +++ if (numAvail > LZMA_MATCH_LEN_MAX) +++ numAvail = LZMA_MATCH_LEN_MAX; +++ +++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; +++ repMaxIndex = 0; +++ for (i = 0; i < LZMA_NUM_REPS; i++) +++ { +++ UInt32 lenTest; +++ const Byte *data2; +++ reps[i] = p->reps[i]; +++ data2 = data - (reps[i] + 1); +++ if (data[0] != data2[0] || data[1] != data2[1]) +++ { +++ repLens[i] = 0; +++ continue; +++ } +++ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); +++ repLens[i] = lenTest; +++ if (lenTest > repLens[repMaxIndex]) +++ repMaxIndex = i; +++ } +++ if (repLens[repMaxIndex] >= p->numFastBytes) +++ { +++ UInt32 lenRes; +++ *backRes = repMaxIndex; +++ lenRes = repLens[repMaxIndex]; +++ MovePos(p, lenRes - 1); +++ return lenRes; +++ } +++ +++ matches = p->matches; +++ if (mainLen >= p->numFastBytes) +++ { +++ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; +++ MovePos(p, mainLen - 1); +++ return mainLen; +++ } +++ curByte = *data; +++ matchByte = *(data - (reps[0] + 1)); +++ +++ if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) +++ { +++ *backRes = (UInt32)-1; +++ return 1; +++ } +++ +++ p->opt[0].state = (CState)p->state; +++ +++ posState = (position & p->pbMask); +++ +++ { +++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); +++ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + +++ (!IsCharState(p->state) ? +++ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : +++ LitEnc_GetPrice(probs, curByte, p->ProbPrices)); +++ } +++ +++ MakeAsChar(&p->opt[1]); +++ +++ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); +++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); +++ +++ if (matchByte == curByte) +++ { +++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); +++ if (shortRepPrice < p->opt[1].price) +++ { +++ p->opt[1].price = shortRepPrice; +++ MakeAsShortRep(&p->opt[1]); +++ } +++ } +++ lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); +++ +++ if (lenEnd < 2) +++ { +++ *backRes = p->opt[1].backPrev; +++ return 1; +++ } +++ +++ p->opt[1].posPrev = 0; +++ for (i = 0; i < LZMA_NUM_REPS; i++) +++ p->opt[0].backs[i] = reps[i]; +++ +++ len = lenEnd; +++ do +++ p->opt[len--].price = kInfinityPrice; +++ while (len >= 2); +++ +++ for (i = 0; i < LZMA_NUM_REPS; i++) +++ { +++ UInt32 repLen = repLens[i]; +++ UInt32 price; +++ if (repLen < 2) +++ continue; +++ price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); +++ do +++ { +++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; +++ COptimal *opt = &p->opt[repLen]; +++ if (curAndLenPrice < opt->price) +++ { +++ opt->price = curAndLenPrice; +++ opt->posPrev = 0; +++ opt->backPrev = i; +++ opt->prev1IsChar = False; +++ } +++ } +++ while (--repLen >= 2); +++ } +++ +++ normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); +++ +++ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); +++ if (len <= mainLen) +++ { +++ UInt32 offs = 0; +++ while (len > matches[offs]) +++ offs += 2; +++ for (; ; len++) +++ { +++ COptimal *opt; +++ UInt32 distance = matches[offs + 1]; +++ +++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; +++ UInt32 lenToPosState = GetLenToPosState(len); +++ if (distance < kNumFullDistances) +++ curAndLenPrice += p->distancesPrices[lenToPosState][distance]; +++ else +++ { +++ UInt32 slot; +++ GetPosSlot2(distance, slot); +++ curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; +++ } +++ opt = &p->opt[len]; +++ if (curAndLenPrice < opt->price) +++ { +++ opt->price = curAndLenPrice; +++ opt->posPrev = 0; +++ opt->backPrev = distance + LZMA_NUM_REPS; +++ opt->prev1IsChar = False; +++ } +++ if (len == matches[offs]) +++ { +++ offs += 2; +++ if (offs == numPairs) +++ break; +++ } +++ } +++ } +++ +++ cur = 0; +++ +++ #ifdef SHOW_STAT2 +++ if (position >= 0) +++ { +++ unsigned i; +++ printf("\n pos = %4X", position); +++ for (i = cur; i <= lenEnd; i++) +++ printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); +++ } +++ #endif +++ +++ for (;;) +++ { +++ UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; +++ UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; +++ Bool nextIsChar; +++ Byte curByte, matchByte; +++ const Byte *data; +++ COptimal *curOpt; +++ COptimal *nextOpt; +++ +++ cur++; +++ if (cur == lenEnd) +++ return Backward(p, backRes, cur); +++ +++ newLen = ReadMatchDistances(p, &numPairs); +++ if (newLen >= p->numFastBytes) +++ { +++ p->numPairs = numPairs; +++ p->longestMatchLength = newLen; +++ return Backward(p, backRes, cur); +++ } +++ position++; +++ curOpt = &p->opt[cur]; +++ posPrev = curOpt->posPrev; +++ if (curOpt->prev1IsChar) +++ { +++ posPrev--; +++ if (curOpt->prev2) +++ { +++ state = p->opt[curOpt->posPrev2].state; +++ if (curOpt->backPrev2 < LZMA_NUM_REPS) +++ state = kRepNextStates[state]; +++ else +++ state = kMatchNextStates[state]; +++ } +++ else +++ state = p->opt[posPrev].state; +++ state = kLiteralNextStates[state]; +++ } +++ else +++ state = p->opt[posPrev].state; +++ if (posPrev == cur - 1) +++ { +++ if (IsShortRep(curOpt)) +++ state = kShortRepNextStates[state]; +++ else +++ state = kLiteralNextStates[state]; +++ } +++ else +++ { +++ UInt32 pos; +++ const COptimal *prevOpt; +++ if (curOpt->prev1IsChar && curOpt->prev2) +++ { +++ posPrev = curOpt->posPrev2; +++ pos = curOpt->backPrev2; +++ state = kRepNextStates[state]; +++ } +++ else +++ { +++ pos = curOpt->backPrev; +++ if (pos < LZMA_NUM_REPS) +++ state = kRepNextStates[state]; +++ else +++ state = kMatchNextStates[state]; +++ } +++ prevOpt = &p->opt[posPrev]; +++ if (pos < LZMA_NUM_REPS) +++ { +++ UInt32 i; +++ reps[0] = prevOpt->backs[pos]; +++ for (i = 1; i <= pos; i++) +++ reps[i] = prevOpt->backs[i - 1]; +++ for (; i < LZMA_NUM_REPS; i++) +++ reps[i] = prevOpt->backs[i]; +++ } +++ else +++ { +++ UInt32 i; +++ reps[0] = (pos - LZMA_NUM_REPS); +++ for (i = 1; i < LZMA_NUM_REPS; i++) +++ reps[i] = prevOpt->backs[i - 1]; +++ } +++ } +++ curOpt->state = (CState)state; +++ +++ curOpt->backs[0] = reps[0]; +++ curOpt->backs[1] = reps[1]; +++ curOpt->backs[2] = reps[2]; +++ curOpt->backs[3] = reps[3]; +++ +++ curPrice = curOpt->price; +++ nextIsChar = False; +++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; +++ curByte = *data; +++ matchByte = *(data - (reps[0] + 1)); +++ +++ posState = (position & p->pbMask); +++ +++ curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); +++ { +++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); +++ curAnd1Price += +++ (!IsCharState(state) ? +++ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : +++ LitEnc_GetPrice(probs, curByte, p->ProbPrices)); +++ } +++ +++ nextOpt = &p->opt[cur + 1]; +++ +++ if (curAnd1Price < nextOpt->price) +++ { +++ nextOpt->price = curAnd1Price; +++ nextOpt->posPrev = cur; +++ MakeAsChar(nextOpt); +++ nextIsChar = True; +++ } +++ +++ matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); +++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); +++ +++ if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) +++ { +++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); +++ if (shortRepPrice <= nextOpt->price) +++ { +++ nextOpt->price = shortRepPrice; +++ nextOpt->posPrev = cur; +++ MakeAsShortRep(nextOpt); +++ nextIsChar = True; +++ } +++ } +++ numAvailFull = p->numAvail; +++ { +++ UInt32 temp = kNumOpts - 1 - cur; +++ if (temp < numAvailFull) +++ numAvailFull = temp; +++ } +++ +++ if (numAvailFull < 2) +++ continue; +++ numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); +++ +++ if (!nextIsChar && matchByte != curByte) /* speed optimization */ +++ { +++ /* try Literal + rep0 */ +++ UInt32 temp; +++ UInt32 lenTest2; +++ const Byte *data2 = data - (reps[0] + 1); +++ UInt32 limit = p->numFastBytes + 1; +++ if (limit > numAvailFull) +++ limit = numAvailFull; +++ +++ for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); +++ lenTest2 = temp - 1; +++ if (lenTest2 >= 2) +++ { +++ UInt32 state2 = kLiteralNextStates[state]; +++ UInt32 posStateNext = (position + 1) & p->pbMask; +++ UInt32 nextRepMatchPrice = curAnd1Price + +++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + +++ GET_PRICE_1(p->isRep[state2]); +++ /* for (; lenTest2 >= 2; lenTest2--) */ +++ { +++ UInt32 curAndLenPrice; +++ COptimal *opt; +++ UInt32 offset = cur + 1 + lenTest2; +++ while (lenEnd < offset) +++ p->opt[++lenEnd].price = kInfinityPrice; +++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); +++ opt = &p->opt[offset]; +++ if (curAndLenPrice < opt->price) +++ { +++ opt->price = curAndLenPrice; +++ opt->posPrev = cur + 1; +++ opt->backPrev = 0; +++ opt->prev1IsChar = True; +++ opt->prev2 = False; +++ } +++ } +++ } +++ } +++ +++ startLen = 2; /* speed optimization */ +++ { +++ UInt32 repIndex; +++ for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) +++ { +++ UInt32 lenTest; +++ UInt32 lenTestTemp; +++ UInt32 price; +++ const Byte *data2 = data - (reps[repIndex] + 1); +++ if (data[0] != data2[0] || data[1] != data2[1]) +++ continue; +++ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); +++ while (lenEnd < cur + lenTest) +++ p->opt[++lenEnd].price = kInfinityPrice; +++ lenTestTemp = lenTest; +++ price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); +++ do +++ { +++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; +++ COptimal *opt = &p->opt[cur + lenTest]; +++ if (curAndLenPrice < opt->price) +++ { +++ opt->price = curAndLenPrice; +++ opt->posPrev = cur; +++ opt->backPrev = repIndex; +++ opt->prev1IsChar = False; +++ } +++ } +++ while (--lenTest >= 2); +++ lenTest = lenTestTemp; +++ +++ if (repIndex == 0) +++ startLen = lenTest + 1; +++ +++ /* if (_maxMode) */ +++ { +++ UInt32 lenTest2 = lenTest + 1; +++ UInt32 limit = lenTest2 + p->numFastBytes; +++ UInt32 nextRepMatchPrice; +++ if (limit > numAvailFull) +++ limit = numAvailFull; +++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); +++ lenTest2 -= lenTest + 1; +++ if (lenTest2 >= 2) +++ { +++ UInt32 state2 = kRepNextStates[state]; +++ UInt32 posStateNext = (position + lenTest) & p->pbMask; +++ UInt32 curAndLenCharPrice = +++ price + p->repLenEnc.prices[posState][lenTest - 2] + +++ GET_PRICE_0(p->isMatch[state2][posStateNext]) + +++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), +++ data[lenTest], data2[lenTest], p->ProbPrices); +++ state2 = kLiteralNextStates[state2]; +++ posStateNext = (position + lenTest + 1) & p->pbMask; +++ nextRepMatchPrice = curAndLenCharPrice + +++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + +++ GET_PRICE_1(p->isRep[state2]); +++ +++ /* for (; lenTest2 >= 2; lenTest2--) */ +++ { +++ UInt32 curAndLenPrice; +++ COptimal *opt; +++ UInt32 offset = cur + lenTest + 1 + lenTest2; +++ while (lenEnd < offset) +++ p->opt[++lenEnd].price = kInfinityPrice; +++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); +++ opt = &p->opt[offset]; +++ if (curAndLenPrice < opt->price) +++ { +++ opt->price = curAndLenPrice; +++ opt->posPrev = cur + lenTest + 1; +++ opt->backPrev = 0; +++ opt->prev1IsChar = True; +++ opt->prev2 = True; +++ opt->posPrev2 = cur; +++ opt->backPrev2 = repIndex; +++ } +++ } +++ } +++ } +++ } +++ } +++ /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ +++ if (newLen > numAvail) +++ { +++ newLen = numAvail; +++ for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); +++ matches[numPairs] = newLen; +++ numPairs += 2; +++ } +++ if (newLen >= startLen) +++ { +++ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); +++ UInt32 offs, curBack, posSlot; +++ UInt32 lenTest; +++ while (lenEnd < cur + newLen) +++ p->opt[++lenEnd].price = kInfinityPrice; +++ +++ offs = 0; +++ while (startLen > matches[offs]) +++ offs += 2; +++ curBack = matches[offs + 1]; +++ GetPosSlot2(curBack, posSlot); +++ for (lenTest = /*2*/ startLen; ; lenTest++) +++ { +++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; +++ UInt32 lenToPosState = GetLenToPosState(lenTest); +++ COptimal *opt; +++ if (curBack < kNumFullDistances) +++ curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; +++ else +++ curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; +++ +++ opt = &p->opt[cur + lenTest]; +++ if (curAndLenPrice < opt->price) +++ { +++ opt->price = curAndLenPrice; +++ opt->posPrev = cur; +++ opt->backPrev = curBack + LZMA_NUM_REPS; +++ opt->prev1IsChar = False; +++ } +++ +++ if (/*_maxMode && */lenTest == matches[offs]) +++ { +++ /* Try Match + Literal + Rep0 */ +++ const Byte *data2 = data - (curBack + 1); +++ UInt32 lenTest2 = lenTest + 1; +++ UInt32 limit = lenTest2 + p->numFastBytes; +++ UInt32 nextRepMatchPrice; +++ if (limit > numAvailFull) +++ limit = numAvailFull; +++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); +++ lenTest2 -= lenTest + 1; +++ if (lenTest2 >= 2) +++ { +++ UInt32 state2 = kMatchNextStates[state]; +++ UInt32 posStateNext = (position + lenTest) & p->pbMask; +++ UInt32 curAndLenCharPrice = curAndLenPrice + +++ GET_PRICE_0(p->isMatch[state2][posStateNext]) + +++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), +++ data[lenTest], data2[lenTest], p->ProbPrices); +++ state2 = kLiteralNextStates[state2]; +++ posStateNext = (posStateNext + 1) & p->pbMask; +++ nextRepMatchPrice = curAndLenCharPrice + +++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + +++ GET_PRICE_1(p->isRep[state2]); +++ +++ /* for (; lenTest2 >= 2; lenTest2--) */ +++ { +++ UInt32 offset = cur + lenTest + 1 + lenTest2; +++ UInt32 curAndLenPrice; +++ COptimal *opt; +++ while (lenEnd < offset) +++ p->opt[++lenEnd].price = kInfinityPrice; +++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); +++ opt = &p->opt[offset]; +++ if (curAndLenPrice < opt->price) +++ { +++ opt->price = curAndLenPrice; +++ opt->posPrev = cur + lenTest + 1; +++ opt->backPrev = 0; +++ opt->prev1IsChar = True; +++ opt->prev2 = True; +++ opt->posPrev2 = cur; +++ opt->backPrev2 = curBack + LZMA_NUM_REPS; +++ } +++ } +++ } +++ offs += 2; +++ if (offs == numPairs) +++ break; +++ curBack = matches[offs + 1]; +++ if (curBack >= kNumFullDistances) +++ GetPosSlot2(curBack, posSlot); +++ } +++ } +++ } +++ } +++} +++ +++#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) +++ +++static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) +++{ +++ UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; +++ const Byte *data; +++ const UInt32 *matches; +++ +++ if (p->additionalOffset == 0) +++ mainLen = ReadMatchDistances(p, &numPairs); +++ else +++ { +++ mainLen = p->longestMatchLength; +++ numPairs = p->numPairs; +++ } +++ +++ numAvail = p->numAvail; +++ *backRes = (UInt32)-1; +++ if (numAvail < 2) +++ return 1; +++ if (numAvail > LZMA_MATCH_LEN_MAX) +++ numAvail = LZMA_MATCH_LEN_MAX; +++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; +++ +++ repLen = repIndex = 0; +++ for (i = 0; i < LZMA_NUM_REPS; i++) +++ { +++ UInt32 len; +++ const Byte *data2 = data - (p->reps[i] + 1); +++ if (data[0] != data2[0] || data[1] != data2[1]) +++ continue; +++ for (len = 2; len < numAvail && data[len] == data2[len]; len++); +++ if (len >= p->numFastBytes) +++ { +++ *backRes = i; +++ MovePos(p, len - 1); +++ return len; +++ } +++ if (len > repLen) +++ { +++ repIndex = i; +++ repLen = len; +++ } +++ } +++ +++ matches = p->matches; +++ if (mainLen >= p->numFastBytes) +++ { +++ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; +++ MovePos(p, mainLen - 1); +++ return mainLen; +++ } +++ +++ mainDist = 0; /* for GCC */ +++ if (mainLen >= 2) +++ { +++ mainDist = matches[numPairs - 1]; +++ while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) +++ { +++ if (!ChangePair(matches[numPairs - 3], mainDist)) +++ break; +++ numPairs -= 2; +++ mainLen = matches[numPairs - 2]; +++ mainDist = matches[numPairs - 1]; +++ } +++ if (mainLen == 2 && mainDist >= 0x80) +++ mainLen = 1; +++ } +++ +++ if (repLen >= 2 && ( +++ (repLen + 1 >= mainLen) || +++ (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || +++ (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) +++ { +++ *backRes = repIndex; +++ MovePos(p, repLen - 1); +++ return repLen; +++ } +++ +++ if (mainLen < 2 || numAvail <= 2) +++ return 1; +++ +++ p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); +++ if (p->longestMatchLength >= 2) +++ { +++ UInt32 newDistance = matches[p->numPairs - 1]; +++ if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || +++ (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || +++ (p->longestMatchLength > mainLen + 1) || +++ (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) +++ return 1; +++ } +++ +++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; +++ for (i = 0; i < LZMA_NUM_REPS; i++) +++ { +++ UInt32 len, limit; +++ const Byte *data2 = data - (p->reps[i] + 1); +++ if (data[0] != data2[0] || data[1] != data2[1]) +++ continue; +++ limit = mainLen - 1; +++ for (len = 2; len < limit && data[len] == data2[len]; len++); +++ if (len >= limit) +++ return 1; +++ } +++ *backRes = mainDist + LZMA_NUM_REPS; +++ MovePos(p, mainLen - 2); +++ return mainLen; +++} +++ +++static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) +++{ +++ UInt32 len; +++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); +++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); +++ p->state = kMatchNextStates[p->state]; +++ len = LZMA_MATCH_LEN_MIN; +++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); +++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); +++ RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); +++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); +++} +++ +++static SRes CheckErrors(CLzmaEnc *p) +++{ +++ if (p->result != SZ_OK) +++ return p->result; +++ if (p->rc.res != SZ_OK) +++ p->result = SZ_ERROR_WRITE; +++ if (p->matchFinderBase.result != SZ_OK) +++ p->result = SZ_ERROR_READ; +++ if (p->result != SZ_OK) +++ p->finished = True; +++ return p->result; +++} +++ +++static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +++{ +++ /* ReleaseMFStream(); */ +++ p->finished = True; +++ if (p->writeEndMark) +++ WriteEndMarker(p, nowPos & p->pbMask); +++ RangeEnc_FlushData(&p->rc); +++ RangeEnc_FlushStream(&p->rc); +++ return CheckErrors(p); +++} +++ +++static void FillAlignPrices(CLzmaEnc *p) +++{ +++ UInt32 i; +++ for (i = 0; i < kAlignTableSize; i++) +++ p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); +++ p->alignPriceCount = 0; +++} +++ +++static void FillDistancesPrices(CLzmaEnc *p) +++{ +++ UInt32 tempPrices[kNumFullDistances]; +++ UInt32 i, lenToPosState; +++ for (i = kStartPosModelIndex; i < kNumFullDistances; i++) +++ { +++ UInt32 posSlot = GetPosSlot1(i); +++ UInt32 footerBits = ((posSlot >> 1) - 1); +++ UInt32 base = ((2 | (posSlot & 1)) << footerBits); +++ tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); +++ } +++ +++ for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) +++ { +++ UInt32 posSlot; +++ const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; +++ UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; +++ for (posSlot = 0; posSlot < p->distTableSize; posSlot++) +++ posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); +++ for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) +++ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); +++ +++ { +++ UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; +++ UInt32 i; +++ for (i = 0; i < kStartPosModelIndex; i++) +++ distancesPrices[i] = posSlotPrices[i]; +++ for (; i < kNumFullDistances; i++) +++ distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; +++ } +++ } +++ p->matchPriceCount = 0; +++} +++ +++void LzmaEnc_Construct(CLzmaEnc *p) +++{ +++ RangeEnc_Construct(&p->rc); +++ MatchFinder_Construct(&p->matchFinderBase); +++ #ifndef _7ZIP_ST +++ MatchFinderMt_Construct(&p->matchFinderMt); +++ p->matchFinderMt.MatchFinder = &p->matchFinderBase; +++ #endif +++ +++ { +++ CLzmaEncProps props; +++ LzmaEncProps_Init(&props); +++ LzmaEnc_SetProps(p, &props); +++ } +++ +++ #ifndef LZMA_LOG_BSR +++ LzmaEnc_FastPosInit(p->g_FastPos); +++ #endif +++ +++ LzmaEnc_InitPriceTables(p->ProbPrices); +++ p->litProbs = 0; +++ p->saveState.litProbs = 0; +++} +++ +++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) +++{ +++ void *p; +++ p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); +++ if (p != 0) +++ LzmaEnc_Construct((CLzmaEnc *)p); +++ return p; +++} +++ +++void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +++{ +++ alloc->Free(alloc, p->litProbs); +++ alloc->Free(alloc, p->saveState.litProbs); +++ p->litProbs = 0; +++ p->saveState.litProbs = 0; +++} +++ +++void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ #ifndef _7ZIP_ST +++ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); +++ #endif +++ MatchFinder_Free(&p->matchFinderBase, allocBig); +++ LzmaEnc_FreeLits(p, alloc); +++ RangeEnc_Free(&p->rc, alloc); +++} +++ +++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); +++ alloc->Free(alloc, p); +++} +++ +++static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) +++{ +++ UInt32 nowPos32, startPos32; +++ if (p->needInit) +++ { +++ p->matchFinder.Init(p->matchFinderObj); +++ p->needInit = 0; +++ } +++ +++ if (p->finished) +++ return p->result; +++ RINOK(CheckErrors(p)); +++ +++ nowPos32 = (UInt32)p->nowPos64; +++ startPos32 = nowPos32; +++ +++ if (p->nowPos64 == 0) +++ { +++ UInt32 numPairs; +++ Byte curByte; +++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) +++ return Flush(p, nowPos32); +++ ReadMatchDistances(p, &numPairs); +++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); +++ p->state = kLiteralNextStates[p->state]; +++ curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); +++ LitEnc_Encode(&p->rc, p->litProbs, curByte); +++ p->additionalOffset--; +++ nowPos32++; +++ } +++ +++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) +++ for (;;) +++ { +++ UInt32 pos, len, posState; +++ +++ if (p->fastMode) +++ len = GetOptimumFast(p, &pos); +++ else +++ len = GetOptimum(p, nowPos32, &pos); +++ +++ #ifdef SHOW_STAT2 +++ printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); +++ #endif +++ +++ posState = nowPos32 & p->pbMask; +++ if (len == 1 && pos == (UInt32)-1) +++ { +++ Byte curByte; +++ CLzmaProb *probs; +++ const Byte *data; +++ +++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); +++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +++ curByte = *data; +++ probs = LIT_PROBS(nowPos32, *(data - 1)); +++ if (IsCharState(p->state)) +++ LitEnc_Encode(&p->rc, probs, curByte); +++ else +++ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); +++ p->state = kLiteralNextStates[p->state]; +++ } +++ else +++ { +++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); +++ if (pos < LZMA_NUM_REPS) +++ { +++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); +++ if (pos == 0) +++ { +++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); +++ RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); +++ } +++ else +++ { +++ UInt32 distance = p->reps[pos]; +++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); +++ if (pos == 1) +++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); +++ else +++ { +++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); +++ RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); +++ if (pos == 3) +++ p->reps[3] = p->reps[2]; +++ p->reps[2] = p->reps[1]; +++ } +++ p->reps[1] = p->reps[0]; +++ p->reps[0] = distance; +++ } +++ if (len == 1) +++ p->state = kShortRepNextStates[p->state]; +++ else +++ { +++ LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); +++ p->state = kRepNextStates[p->state]; +++ } +++ } +++ else +++ { +++ UInt32 posSlot; +++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); +++ p->state = kMatchNextStates[p->state]; +++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); +++ pos -= LZMA_NUM_REPS; +++ GetPosSlot(pos, posSlot); +++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); +++ +++ if (posSlot >= kStartPosModelIndex) +++ { +++ UInt32 footerBits = ((posSlot >> 1) - 1); +++ UInt32 base = ((2 | (posSlot & 1)) << footerBits); +++ UInt32 posReduced = pos - base; +++ +++ if (posSlot < kEndPosModelIndex) +++ RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); +++ else +++ { +++ RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); +++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); +++ p->alignPriceCount++; +++ } +++ } +++ p->reps[3] = p->reps[2]; +++ p->reps[2] = p->reps[1]; +++ p->reps[1] = p->reps[0]; +++ p->reps[0] = pos; +++ p->matchPriceCount++; +++ } +++ } +++ p->additionalOffset -= len; +++ nowPos32 += len; +++ if (p->additionalOffset == 0) +++ { +++ UInt32 processed; +++ if (!p->fastMode) +++ { +++ if (p->matchPriceCount >= (1 << 7)) +++ FillDistancesPrices(p); +++ if (p->alignPriceCount >= kAlignTableSize) +++ FillAlignPrices(p); +++ } +++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) +++ break; +++ processed = nowPos32 - startPos32; +++ if (useLimits) +++ { +++ if (processed + kNumOpts + 300 >= maxUnpackSize || +++ RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) +++ break; +++ } +++ else if (processed >= (1 << 15)) +++ { +++ p->nowPos64 += nowPos32 - startPos32; +++ return CheckErrors(p); +++ } +++ } +++ } +++ p->nowPos64 += nowPos32 - startPos32; +++ return Flush(p, nowPos32); +++} +++ +++#define kBigHashDicLimit ((UInt32)1 << 24) +++ +++static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ UInt32 beforeSize = kNumOpts; +++ Bool btMode; +++ if (!RangeEnc_Alloc(&p->rc, alloc)) +++ return SZ_ERROR_MEM; +++ btMode = (p->matchFinderBase.btMode != 0); +++ #ifndef _7ZIP_ST +++ p->mtMode = (p->multiThread && !p->fastMode && btMode); +++ #endif +++ +++ { +++ unsigned lclp = p->lc + p->lp; +++ if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) +++ { +++ LzmaEnc_FreeLits(p, alloc); +++ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); +++ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); +++ if (p->litProbs == 0 || p->saveState.litProbs == 0) +++ { +++ LzmaEnc_FreeLits(p, alloc); +++ return SZ_ERROR_MEM; +++ } +++ p->lclp = lclp; +++ } +++ } +++ +++ p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); +++ +++ if (beforeSize + p->dictSize < keepWindowSize) +++ beforeSize = keepWindowSize - p->dictSize; +++ +++ #ifndef _7ZIP_ST +++ if (p->mtMode) +++ { +++ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); +++ p->matchFinderObj = &p->matchFinderMt; +++ MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); +++ } +++ else +++ #endif +++ { +++ if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) +++ return SZ_ERROR_MEM; +++ p->matchFinderObj = &p->matchFinderBase; +++ MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); +++ } +++ return SZ_OK; +++} +++ +++void LzmaEnc_Init(CLzmaEnc *p) +++{ +++ UInt32 i; +++ p->state = 0; +++ for (i = 0 ; i < LZMA_NUM_REPS; i++) +++ p->reps[i] = 0; +++ +++ RangeEnc_Init(&p->rc); +++ +++ +++ for (i = 0; i < kNumStates; i++) +++ { +++ UInt32 j; +++ for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) +++ { +++ p->isMatch[i][j] = kProbInitValue; +++ p->isRep0Long[i][j] = kProbInitValue; +++ } +++ p->isRep[i] = kProbInitValue; +++ p->isRepG0[i] = kProbInitValue; +++ p->isRepG1[i] = kProbInitValue; +++ p->isRepG2[i] = kProbInitValue; +++ } +++ +++ { +++ UInt32 num = 0x300 << (p->lp + p->lc); +++ for (i = 0; i < num; i++) +++ p->litProbs[i] = kProbInitValue; +++ } +++ +++ { +++ for (i = 0; i < kNumLenToPosStates; i++) +++ { +++ CLzmaProb *probs = p->posSlotEncoder[i]; +++ UInt32 j; +++ for (j = 0; j < (1 << kNumPosSlotBits); j++) +++ probs[j] = kProbInitValue; +++ } +++ } +++ { +++ for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) +++ p->posEncoders[i] = kProbInitValue; +++ } +++ +++ LenEnc_Init(&p->lenEnc.p); +++ LenEnc_Init(&p->repLenEnc.p); +++ +++ for (i = 0; i < (1 << kNumAlignBits); i++) +++ p->posAlignEncoder[i] = kProbInitValue; +++ +++ p->optimumEndIndex = 0; +++ p->optimumCurrentIndex = 0; +++ p->additionalOffset = 0; +++ +++ p->pbMask = (1 << p->pb) - 1; +++ p->lpMask = (1 << p->lp) - 1; +++} +++ +++void LzmaEnc_InitPrices(CLzmaEnc *p) +++{ +++ if (!p->fastMode) +++ { +++ FillDistancesPrices(p); +++ FillAlignPrices(p); +++ } +++ +++ p->lenEnc.tableSize = +++ p->repLenEnc.tableSize = +++ p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; +++ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); +++ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); +++} +++ +++static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ UInt32 i; +++ for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) +++ if (p->dictSize <= ((UInt32)1 << i)) +++ break; +++ p->distTableSize = i * 2; +++ +++ p->finished = False; +++ p->result = SZ_OK; +++ RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); +++ LzmaEnc_Init(p); +++ LzmaEnc_InitPrices(p); +++ p->nowPos64 = 0; +++ return SZ_OK; +++} +++ +++static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, +++ ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ p->matchFinderBase.stream = inStream; +++ p->needInit = 1; +++ p->rc.outStream = outStream; +++ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +++} +++ +++SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, +++ ISeqInStream *inStream, UInt32 keepWindowSize, +++ ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ p->matchFinderBase.stream = inStream; +++ p->needInit = 1; +++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +++} +++ +++static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +++{ +++ p->matchFinderBase.directInput = 1; +++ p->matchFinderBase.bufferBase = (Byte *)src; +++ p->matchFinderBase.directInputRem = srcLen; +++} +++ +++SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, +++ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ LzmaEnc_SetInputBuf(p, src, srcLen); +++ p->needInit = 1; +++ +++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +++} +++ +++void LzmaEnc_Finish(CLzmaEncHandle pp) +++{ +++ #ifndef _7ZIP_ST +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ if (p->mtMode) +++ MatchFinderMt_ReleaseStream(&p->matchFinderMt); +++ #else +++ pp = pp; +++ #endif +++} +++ +++typedef struct +++{ +++ ISeqOutStream funcTable; +++ Byte *data; +++ SizeT rem; +++ Bool overflow; +++} CSeqOutStreamBuf; +++ +++static size_t MyWrite(void *pp, const void *data, size_t size) +++{ +++ CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; +++ if (p->rem < size) +++ { +++ size = p->rem; +++ p->overflow = True; +++ } +++ memcpy(p->data, data, size); +++ p->rem -= size; +++ p->data += size; +++ return size; +++} +++ +++ +++UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +++{ +++ const CLzmaEnc *p = (CLzmaEnc *)pp; +++ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +++} +++ +++const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +++{ +++ const CLzmaEnc *p = (CLzmaEnc *)pp; +++ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +++} +++ +++SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, +++ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +++{ +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ UInt64 nowPos64; +++ SRes res; +++ CSeqOutStreamBuf outStream; +++ +++ outStream.funcTable.Write = MyWrite; +++ outStream.data = dest; +++ outStream.rem = *destLen; +++ outStream.overflow = False; +++ +++ p->writeEndMark = False; +++ p->finished = False; +++ p->result = SZ_OK; +++ +++ if (reInit) +++ LzmaEnc_Init(p); +++ LzmaEnc_InitPrices(p); +++ nowPos64 = p->nowPos64; +++ RangeEnc_Init(&p->rc); +++ p->rc.outStream = &outStream.funcTable; +++ +++ res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); +++ +++ *unpackSize = (UInt32)(p->nowPos64 - nowPos64); +++ *destLen -= outStream.rem; +++ if (outStream.overflow) +++ return SZ_ERROR_OUTPUT_EOF; +++ +++ return res; +++} +++ +++static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) +++{ +++ SRes res = SZ_OK; +++ +++ #ifndef _7ZIP_ST +++ Byte allocaDummy[0x300]; +++ int i = 0; +++ for (i = 0; i < 16; i++) +++ allocaDummy[i] = (Byte)i; +++ #endif +++ +++ for (;;) +++ { +++ res = LzmaEnc_CodeOneBlock(p, False, 0, 0); +++ if (res != SZ_OK || p->finished != 0) +++ break; +++ if (progress != 0) +++ { +++ res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); +++ if (res != SZ_OK) +++ { +++ res = SZ_ERROR_PROGRESS; +++ break; +++ } +++ } +++ } +++ LzmaEnc_Finish(p); +++ return res; +++} +++ +++SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, +++ ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); +++ return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); +++} +++ +++SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +++{ +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ int i; +++ UInt32 dictSize = p->dictSize; +++ if (*size < LZMA_PROPS_SIZE) +++ return SZ_ERROR_PARAM; +++ *size = LZMA_PROPS_SIZE; +++ props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); +++ +++ for (i = 11; i <= 30; i++) +++ { +++ if (dictSize <= ((UInt32)2 << i)) +++ { +++ dictSize = (2 << i); +++ break; +++ } +++ if (dictSize <= ((UInt32)3 << i)) +++ { +++ dictSize = (3 << i); +++ break; +++ } +++ } +++ +++ for (i = 0; i < 4; i++) +++ props[1 + i] = (Byte)(dictSize >> (8 * i)); +++ return SZ_OK; +++} +++ +++SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, +++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ SRes res; +++ CLzmaEnc *p = (CLzmaEnc *)pp; +++ +++ CSeqOutStreamBuf outStream; +++ +++ LzmaEnc_SetInputBuf(p, src, srcLen); +++ +++ outStream.funcTable.Write = MyWrite; +++ outStream.data = dest; +++ outStream.rem = *destLen; +++ outStream.overflow = False; +++ +++ p->writeEndMark = writeEndMark; +++ +++ p->rc.outStream = &outStream.funcTable; +++ res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); +++ if (res == SZ_OK) +++ res = LzmaEnc_Encode2(p, progress); +++ +++ *destLen -= outStream.rem; +++ if (outStream.overflow) +++ return SZ_ERROR_OUTPUT_EOF; +++ return res; +++} +++ +++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, +++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, +++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +++{ +++ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); +++ SRes res; +++ if (p == 0) +++ return SZ_ERROR_MEM; +++ +++ res = LzmaEnc_SetProps(p, props); +++ if (res == SZ_OK) +++ { +++ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); +++ if (res == SZ_OK) +++ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, +++ writeEndMark, progress, alloc, allocBig); +++ } +++ +++ LzmaEnc_Destroy(p, alloc, allocBig); +++ return res; +++} ++--- /dev/null +++++ b/lib/lzma/Makefile ++@@ -0,0 +1,7 @@ +++lzma_compress-objs := LzFind.o LzmaEnc.o +++lzma_decompress-objs := LzmaDec.o +++ +++obj-$(CONFIG_LZMA_COMPRESS) += lzma_compress.o +++obj-$(CONFIG_LZMA_DECOMPRESS) += lzma_decompress.o +++ +++EXTRA_CFLAGS += -Iinclude/linux -Iinclude/linux/lzma -include types.h +diff --git a/target/linux/generic/pending-4.14/532-jffs2_eofdetect.patch b/target/linux/generic/pending-4.14/532-jffs2_eofdetect.patch +new file mode 100644 +index 0000000000..e9952c6d84 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/532-jffs2_eofdetect.patch +@@ -0,0 +1,65 @@ ++From: Felix Fietkau ++Subject: fs: jffs2: EOF marker ++ ++Signed-off-by: Felix Fietkau ++--- ++ fs/jffs2/build.c | 10 ++++++++++ ++ fs/jffs2/scan.c | 21 +++++++++++++++++++-- ++ 2 files changed, 29 insertions(+), 2 deletions(-) ++ ++--- a/fs/jffs2/build.c +++++ b/fs/jffs2/build.c ++@@ -117,6 +117,16 @@ static int jffs2_build_filesystem(struct ++ dbg_fsbuild("scanned flash completely\n"); ++ jffs2_dbg_dump_block_lists_nolock(c); ++ +++ if (c->flags & (1 << 7)) { +++ printk("%s(): unlocking the mtd device... ", __func__); +++ mtd_unlock(c->mtd, 0, c->mtd->size); +++ printk("done.\n"); +++ +++ printk("%s(): erasing all blocks after the end marker... ", __func__); +++ jffs2_erase_pending_blocks(c, -1); +++ printk("done.\n"); +++ } +++ ++ dbg_fsbuild("pass 1 starting\n"); ++ c->flags |= JFFS2_SB_FLAG_BUILDING; ++ /* Now scan the directory tree, increasing nlink according to every dirent found. */ ++--- a/fs/jffs2/scan.c +++++ b/fs/jffs2/scan.c ++@@ -148,8 +148,14 @@ int jffs2_scan_medium(struct jffs2_sb_in ++ /* reset summary info for next eraseblock scan */ ++ jffs2_sum_reset_collected(s); ++ ++- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), ++- buf_size, s); +++ if (c->flags & (1 << 7)) { +++ if (mtd_block_isbad(c->mtd, jeb->offset)) +++ ret = BLK_STATE_BADBLOCK; +++ else +++ ret = BLK_STATE_ALLFF; +++ } else +++ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), +++ buf_size, s); ++ ++ if (ret < 0) ++ goto out; ++@@ -561,6 +567,17 @@ full_scan: ++ return err; ++ } ++ +++ if ((buf[0] == 0xde) && +++ (buf[1] == 0xad) && +++ (buf[2] == 0xc0) && +++ (buf[3] == 0xde)) { +++ /* end of filesystem. erase everything after this point */ +++ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset); +++ c->flags |= (1 << 7); +++ +++ return BLK_STATE_ALLFF; +++ } +++ ++ /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ ++ ofs = 0; ++ max_ofs = EMPTY_SCAN_SIZE(c->sector_size); +diff --git a/target/linux/generic/pending-4.14/600-netfilter_conntrack_flush.patch b/target/linux/generic/pending-4.14/600-netfilter_conntrack_flush.patch +new file mode 100644 +index 0000000000..10da96b7ed +--- /dev/null ++++ b/target/linux/generic/pending-4.14/600-netfilter_conntrack_flush.patch +@@ -0,0 +1,95 @@ ++From: Felix Fietkau ++Subject: netfilter: add support for flushing conntrack via /proc ++ ++lede-commit 8193bbe59a74d34d6a26d4a8cb857b1952905314 ++Signed-off-by: Felix Fietkau ++--- ++ net/netfilter/nf_conntrack_standalone.c | 59 ++++++++++++++++++++++++++++++++- ++ 1 file changed, 58 insertions(+), 1 deletion(-) ++ ++--- a/net/netfilter/nf_conntrack_standalone.c +++++ b/net/netfilter/nf_conntrack_standalone.c ++@@ -17,6 +17,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #ifdef CONFIG_SYSCTL ++ #include ++@@ -381,10 +382,66 @@ static int ct_open(struct inode *inode, ++ sizeof(struct ct_iter_state)); ++ } ++ +++struct kill_request { +++ u16 family; +++ union nf_inet_addr addr; +++}; +++ +++static int kill_matching(struct nf_conn *i, void *data) +++{ +++ struct kill_request *kr = data; +++ struct nf_conntrack_tuple *t1 = &i->tuplehash[IP_CT_DIR_ORIGINAL].tuple; +++ struct nf_conntrack_tuple *t2 = &i->tuplehash[IP_CT_DIR_REPLY].tuple; +++ +++ if (!kr->family) +++ return 1; +++ +++ if (t1->src.l3num != kr->family) +++ return 0; +++ +++ return (nf_inet_addr_cmp(&kr->addr, &t1->src.u3) || +++ nf_inet_addr_cmp(&kr->addr, &t1->dst.u3) || +++ nf_inet_addr_cmp(&kr->addr, &t2->src.u3) || +++ nf_inet_addr_cmp(&kr->addr, &t2->dst.u3)); +++} +++ +++static ssize_t ct_file_write(struct file *file, const char __user *buf, +++ size_t count, loff_t *ppos) +++{ +++ struct seq_file *seq = file->private_data; +++ struct net *net = seq_file_net(seq); +++ struct kill_request kr = { }; +++ char req[INET6_ADDRSTRLEN] = { }; +++ +++ if (count == 0) +++ return 0; +++ +++ if (count >= INET6_ADDRSTRLEN) +++ count = INET6_ADDRSTRLEN - 1; +++ +++ if (copy_from_user(req, buf, count)) +++ return -EFAULT; +++ +++ if (strnchr(req, count, ':')) { +++ kr.family = AF_INET6; +++ if (!in6_pton(req, count, (void *)&kr.addr, '\n', NULL)) +++ return -EINVAL; +++ } else if (strnchr(req, count, '.')) { +++ kr.family = AF_INET; +++ if (!in4_pton(req, count, (void *)&kr.addr, '\n', NULL)) +++ return -EINVAL; +++ } +++ +++ nf_ct_iterate_cleanup_net(net, kill_matching, &kr, 0, 0); +++ +++ return count; +++} +++ ++ static const struct file_operations ct_file_ops = { ++ .owner = THIS_MODULE, ++ .open = ct_open, ++ .read = seq_read, +++ .write = ct_file_write, ++ .llseek = seq_lseek, ++ .release = seq_release_net, ++ }; ++@@ -488,7 +545,7 @@ static int nf_conntrack_standalone_init_ ++ kuid_t root_uid; ++ kgid_t root_gid; ++ ++- pde = proc_create("nf_conntrack", 0440, net->proc_net, &ct_file_ops); +++ pde = proc_create("nf_conntrack", 0660, net->proc_net, &ct_file_ops); ++ if (!pde) ++ goto out_nf_conntrack; ++ +diff --git a/target/linux/generic/pending-4.14/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-4.14/610-netfilter_match_bypass_default_checks.patch +new file mode 100644 +index 0000000000..2541230ff5 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/610-netfilter_match_bypass_default_checks.patch +@@ -0,0 +1,110 @@ ++From: Felix Fietkau ++Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0 ++ ++Signed-off-by: Felix Fietkau ++--- ++ include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 + ++ net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++ ++ 2 files changed, 38 insertions(+) ++ ++--- a/include/uapi/linux/netfilter_ipv4/ip_tables.h +++++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h ++@@ -89,6 +89,7 @@ struct ipt_ip { ++ #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ ++ #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ ++ #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ +++#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ ++ ++ /* Values for "inv" field in struct ipt_ip. */ ++ #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ ++--- a/net/ipv4/netfilter/ip_tables.c +++++ b/net/ipv4/netfilter/ip_tables.c ++@@ -52,6 +52,9 @@ ip_packet_match(const struct iphdr *ip, ++ { ++ unsigned long ret; ++ +++ if (ipinfo->flags & IPT_F_NO_DEF_MATCH) +++ return true; +++ ++ if (NF_INVF(ipinfo, IPT_INV_SRCIP, ++ (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || ++ NF_INVF(ipinfo, IPT_INV_DSTIP, ++@@ -82,6 +85,29 @@ ip_packet_match(const struct iphdr *ip, ++ return true; ++ } ++ +++static void +++ip_checkdefault(struct ipt_ip *ip) +++{ +++ static const char iface_mask[IFNAMSIZ] = {}; +++ +++ if (ip->invflags || ip->flags & IPT_F_FRAG) +++ return; +++ +++ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) +++ return; +++ +++ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) +++ return; +++ +++ if (ip->smsk.s_addr || ip->dmsk.s_addr) +++ return; +++ +++ if (ip->proto) +++ return; +++ +++ ip->flags |= IPT_F_NO_DEF_MATCH; +++} +++ ++ static bool ++ ip_checkentry(const struct ipt_ip *ip) ++ { ++@@ -537,6 +563,8 @@ find_check_entry(struct ipt_entry *e, st ++ struct xt_mtchk_param mtpar; ++ struct xt_entry_match *ematch; ++ +++ ip_checkdefault(&e->ip); +++ ++ if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) ++ return -ENOMEM; ++ ++@@ -818,6 +846,7 @@ copy_entries_to_user(unsigned int total_ ++ const struct xt_table_info *private = table->private; ++ int ret = 0; ++ const void *loc_cpu_entry; +++ u8 flags; ++ ++ counters = alloc_counters(table); ++ if (IS_ERR(counters)) ++@@ -845,6 +874,14 @@ copy_entries_to_user(unsigned int total_ ++ goto free_counters; ++ } ++ +++ flags = e->ip.flags & IPT_F_MASK; +++ if (copy_to_user(userptr + off +++ + offsetof(struct ipt_entry, ip.flags), +++ &flags, sizeof(flags)) != 0) { +++ ret = -EFAULT; +++ goto free_counters; +++ } +++ ++ for (i = sizeof(struct ipt_entry); ++ i < e->target_offset; ++ i += m->u.match_size) { ++@@ -1227,12 +1264,15 @@ compat_copy_entry_to_user(struct ipt_ent ++ compat_uint_t origsize; ++ const struct xt_entry_match *ematch; ++ int ret = 0; +++ u8 flags = e->ip.flags & IPT_F_MASK; ++ ++ origsize = *size; ++ ce = *dstptr; ++ if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 || ++ copy_to_user(&ce->counters, &counters[i], ++- sizeof(counters[i])) != 0) +++ sizeof(counters[i])) != 0 || +++ copy_to_user(&ce->ip.flags, &flags, +++ sizeof(flags)) != 0) ++ return -EFAULT; ++ ++ *dstptr += sizeof(struct compat_ipt_entry); +diff --git a/target/linux/generic/pending-4.14/611-netfilter_match_bypass_default_table.patch b/target/linux/generic/pending-4.14/611-netfilter_match_bypass_default_table.patch +new file mode 100644 +index 0000000000..11f07e12b3 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/611-netfilter_match_bypass_default_table.patch +@@ -0,0 +1,111 @@ ++From: Felix Fietkau ++Subject: netfilter: match bypass default table ++ ++Signed-off-by: Felix Fietkau ++--- ++ net/ipv4/netfilter/ip_tables.c | 79 +++++++++++++++++++++++++++++++----------- ++ 1 file changed, 58 insertions(+), 21 deletions(-) ++ ++--- a/net/ipv4/netfilter/ip_tables.c +++++ b/net/ipv4/netfilter/ip_tables.c ++@@ -248,6 +248,33 @@ struct ipt_entry *ipt_next_entry(const s ++ return (void *)entry + entry->next_offset; ++ } ++ +++static bool +++ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict) +++{ +++ struct xt_entry_target *t; +++ struct xt_standard_target *st; +++ +++ if (e->target_offset != sizeof(struct ipt_entry)) +++ return false; +++ +++ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH)) +++ return false; +++ +++ t = ipt_get_target(e); +++ if (t->u.kernel.target->target) +++ return false; +++ +++ st = (struct xt_standard_target *) t; +++ if (st->verdict == XT_RETURN) +++ return false; +++ +++ if (st->verdict >= 0) +++ return false; +++ +++ *verdict = (unsigned)(-st->verdict) - 1; +++ return true; +++} +++ ++ /* Returns one of the generic firewall policies, like NF_ACCEPT. */ ++ unsigned int ++ ipt_do_table(struct sk_buff *skb, ++@@ -268,24 +295,8 @@ ipt_do_table(struct sk_buff *skb, ++ unsigned int addend; ++ ++ /* Initialization */ ++- stackidx = 0; ++- ip = ip_hdr(skb); ++- indev = state->in ? state->in->name : nulldevname; ++- outdev = state->out ? state->out->name : nulldevname; ++- /* We handle fragments by dealing with the first fragment as ++- * if it was a normal packet. All other fragments are treated ++- * normally, except that they will NEVER match rules that ask ++- * things we don't know, ie. tcp syn flag or ports). If the ++- * rule is also a fragment-specific rule, non-fragments won't ++- * match it. */ ++- acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; ++- acpar.thoff = ip_hdrlen(skb); ++- acpar.hotdrop = false; ++- acpar.state = state; ++- ++ WARN_ON(!(table->valid_hooks & (1 << hook))); ++ local_bh_disable(); ++- addend = xt_write_recseq_begin(); ++ private = table->private; ++ cpu = smp_processor_id(); ++ /* ++@@ -294,6 +305,23 @@ ipt_do_table(struct sk_buff *skb, ++ */ ++ smp_read_barrier_depends(); ++ table_base = private->entries; +++ +++ e = get_entry(table_base, private->hook_entry[hook]); +++ if (ipt_handle_default_rule(e, &verdict)) { +++ struct xt_counters *counter; +++ +++ counter = xt_get_this_cpu_counter(&e->counters); +++ ADD_COUNTER(*counter, skb->len, 1); +++ local_bh_enable(); +++ return verdict; +++ } +++ +++ stackidx = 0; +++ ip = ip_hdr(skb); +++ indev = state->in ? state->in->name : nulldevname; +++ outdev = state->out ? state->out->name : nulldevname; +++ +++ addend = xt_write_recseq_begin(); ++ jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; ++ ++ /* Switch to alternate jumpstack if we're being invoked via TEE. ++@@ -306,7 +334,16 @@ ipt_do_table(struct sk_buff *skb, ++ if (static_key_false(&xt_tee_enabled)) ++ jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated); ++ ++- e = get_entry(table_base, private->hook_entry[hook]); +++ /* We handle fragments by dealing with the first fragment as +++ * if it was a normal packet. All other fragments are treated +++ * normally, except that they will NEVER match rules that ask +++ * things we don't know, ie. tcp syn flag or ports). If the +++ * rule is also a fragment-specific rule, non-fragments won't +++ * match it. */ +++ acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; +++ acpar.thoff = ip_hdrlen(skb); +++ acpar.hotdrop = false; +++ acpar.state = state; ++ ++ do { ++ const struct xt_entry_target *t; +diff --git a/target/linux/generic/pending-4.14/612-netfilter_match_reduce_memory_access.patch b/target/linux/generic/pending-4.14/612-netfilter_match_reduce_memory_access.patch +new file mode 100644 +index 0000000000..183c74c1c7 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/612-netfilter_match_reduce_memory_access.patch +@@ -0,0 +1,22 @@ ++From: Felix Fietkau ++Subject: netfilter: reduce match memory access ++ ++Signed-off-by: Felix Fietkau ++--- ++ net/ipv4/netfilter/ip_tables.c | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++--- a/net/ipv4/netfilter/ip_tables.c +++++ b/net/ipv4/netfilter/ip_tables.c ++@@ -55,9 +55,9 @@ ip_packet_match(const struct iphdr *ip, ++ if (ipinfo->flags & IPT_F_NO_DEF_MATCH) ++ return true; ++ ++- if (NF_INVF(ipinfo, IPT_INV_SRCIP, +++ if (NF_INVF(ipinfo, IPT_INV_SRCIP, ipinfo->smsk.s_addr && ++ (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || ++- NF_INVF(ipinfo, IPT_INV_DSTIP, +++ NF_INVF(ipinfo, IPT_INV_DSTIP, ipinfo->dmsk.s_addr && ++ (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr)) ++ return false; ++ +diff --git a/target/linux/generic/pending-4.14/613-netfilter_optional_tcp_window_check.patch b/target/linux/generic/pending-4.14/613-netfilter_optional_tcp_window_check.patch +new file mode 100644 +index 0000000000..69c165bb41 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/613-netfilter_optional_tcp_window_check.patch +@@ -0,0 +1,44 @@ ++From: Felix Fietkau ++Subject: netfilter: optional tcp window check ++ ++Signed-off-by: Felix Fietkau ++--- ++ net/netfilter/nf_conntrack_proto_tcp.c | 13 +++++++++++++ ++ 1 file changed, 13 insertions(+) ++ ++--- a/net/netfilter/nf_conntrack_proto_tcp.c +++++ b/net/netfilter/nf_conntrack_proto_tcp.c ++@@ -33,6 +33,9 @@ ++ #include ++ #include ++ +++/* Do not check the TCP window for incoming packets */ +++static int nf_ct_tcp_no_window_check __read_mostly = 1; +++ ++ /* "Be conservative in what you do, ++ be liberal in what you accept from others." ++ If it's non-zero, we mark only out of window RST segments as INVALID. */ ++@@ -508,6 +511,9 @@ static bool tcp_in_window(const struct n ++ s32 receiver_offset; ++ bool res, in_recv_win; ++ +++ if (nf_ct_tcp_no_window_check) +++ return true; +++ ++ /* ++ * Get the required data from the packet. ++ */ ++@@ -1489,6 +1495,13 @@ static struct ctl_table tcp_sysctl_table ++ .mode = 0644, ++ .proc_handler = proc_dointvec, ++ }, +++ { +++ .procname = "nf_conntrack_tcp_no_window_check", +++ .data = &nf_ct_tcp_no_window_check, +++ .maxlen = sizeof(unsigned int), +++ .mode = 0644, +++ .proc_handler = proc_dointvec, +++ }, ++ { } ++ }; ++ #endif /* CONFIG_SYSCTL */ +diff --git a/target/linux/generic/pending-4.14/620-net_sched-codel-do-not-defer-queue-length-update.patch b/target/linux/generic/pending-4.14/620-net_sched-codel-do-not-defer-queue-length-update.patch +new file mode 100644 +index 0000000000..b3c35ee350 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/620-net_sched-codel-do-not-defer-queue-length-update.patch +@@ -0,0 +1,86 @@ ++From: Konstantin Khlebnikov ++Date: Mon, 21 Aug 2017 11:14:14 +0300 ++Subject: [PATCH] net_sched/codel: do not defer queue length update ++ ++When codel wants to drop last packet in ->dequeue() it cannot call ++qdisc_tree_reduce_backlog() right away - it will notify parent qdisc ++about zero qlen and HTB/HFSC will deactivate class. The same class will ++be deactivated second time by caller of ->dequeue(). Currently codel and ++fq_codel defer update. This triggers warning in HFSC when it's qlen != 0 ++but there is no active classes. ++ ++This patch update parent queue length immediately: just temporary increase ++qlen around qdisc_tree_reduce_backlog() to prevent first class deactivation ++if we have skb to return. ++ ++This might open another problem in HFSC - now operation peek could fail and ++deactivate parent class. ++ ++Signed-off-by: Konstantin Khlebnikov ++Link: https://bugzilla.kernel.org/show_bug.cgi?id=109581 ++--- ++ ++--- a/net/sched/sch_codel.c +++++ b/net/sched/sch_codel.c ++@@ -95,11 +95,17 @@ static struct sk_buff *codel_qdisc_deque ++ &q->stats, qdisc_pkt_len, codel_get_enqueue_time, ++ drop_func, dequeue_func); ++ ++- /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, ++- * or HTB crashes. Defer it for next round. +++ /* If our qlen is 0 qdisc_tree_reduce_backlog() will deactivate +++ * parent class, dequeue in parent qdisc will do the same if we +++ * return skb. Temporary increment qlen if we have skb. ++ */ ++- if (q->stats.drop_count && sch->q.qlen) { ++- qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len); +++ if (q->stats.drop_count) { +++ if (skb) +++ sch->q.qlen++; +++ qdisc_tree_reduce_backlog(sch, q->stats.drop_count, +++ q->stats.drop_len); +++ if (skb) +++ sch->q.qlen--; ++ q->stats.drop_count = 0; ++ q->stats.drop_len = 0; ++ } ++--- a/net/sched/sch_fq_codel.c +++++ b/net/sched/sch_fq_codel.c ++@@ -316,6 +316,21 @@ begin: ++ flow->dropped += q->cstats.drop_count - prev_drop_count; ++ flow->dropped += q->cstats.ecn_mark - prev_ecn_mark; ++ +++ /* If our qlen is 0 qdisc_tree_reduce_backlog() will deactivate +++ * parent class, dequeue in parent qdisc will do the same if we +++ * return skb. Temporary increment qlen if we have skb. +++ */ +++ if (q->cstats.drop_count) { +++ if (skb) +++ sch->q.qlen++; +++ qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, +++ q->cstats.drop_len); +++ if (skb) +++ sch->q.qlen--; +++ q->cstats.drop_count = 0; +++ q->cstats.drop_len = 0; +++ } +++ ++ if (!skb) { ++ /* force a pass through old_flows to prevent starvation */ ++ if ((head == &q->new_flows) && !list_empty(&q->old_flows)) ++@@ -326,15 +341,6 @@ begin: ++ } ++ qdisc_bstats_update(sch, skb); ++ flow->deficit -= qdisc_pkt_len(skb); ++- /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, ++- * or HTB crashes. Defer it for next round. ++- */ ++- if (q->cstats.drop_count && sch->q.qlen) { ++- qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, ++- q->cstats.drop_len); ++- q->cstats.drop_count = 0; ++- q->cstats.drop_len = 0; ++- } ++ return skb; ++ } ++ +diff --git a/target/linux/generic/pending-4.14/630-packet_socket_type.patch b/target/linux/generic/pending-4.14/630-packet_socket_type.patch +new file mode 100644 +index 0000000000..c4bd5fdaba +--- /dev/null ++++ b/target/linux/generic/pending-4.14/630-packet_socket_type.patch +@@ -0,0 +1,138 @@ ++From: Felix Fietkau ++Subject: net: add an optimization for dealing with raw sockets ++ ++lede-commit: 4898039703d7315f0f3431c860123338ec3be0f6 ++Signed-off-by: Felix Fietkau ++--- ++ include/uapi/linux/if_packet.h | 3 +++ ++ net/packet/af_packet.c | 34 +++++++++++++++++++++++++++------- ++ net/packet/internal.h | 1 + ++ 3 files changed, 31 insertions(+), 7 deletions(-) ++ ++--- a/include/uapi/linux/if_packet.h +++++ b/include/uapi/linux/if_packet.h ++@@ -32,6 +32,8 @@ struct sockaddr_ll { ++ #define PACKET_KERNEL 7 /* To kernel space */ ++ /* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */ ++ #define PACKET_FASTROUTE 6 /* Fastrouted frame */ +++#define PACKET_MASK_ANY 0xffffffff /* mask for packet type bits */ +++ ++ ++ /* Packet socket options */ ++ ++@@ -57,6 +59,7 @@ struct sockaddr_ll { ++ #define PACKET_QDISC_BYPASS 20 ++ #define PACKET_ROLLOVER_STATS 21 ++ #define PACKET_FANOUT_DATA 22 +++#define PACKET_RECV_TYPE 23 ++ ++ #define PACKET_FANOUT_HASH 0 ++ #define PACKET_FANOUT_LB 1 ++--- a/net/packet/af_packet.c +++++ b/net/packet/af_packet.c ++@@ -1836,6 +1836,7 @@ static int packet_rcv_spkt(struct sk_buf ++ { ++ struct sock *sk; ++ struct sockaddr_pkt *spkt; +++ struct packet_sock *po; ++ ++ /* ++ * When we registered the protocol we saved the socket in the data ++@@ -1843,6 +1844,7 @@ static int packet_rcv_spkt(struct sk_buf ++ */ ++ ++ sk = pt->af_packet_priv; +++ po = pkt_sk(sk); ++ ++ /* ++ * Yank back the headers [hope the device set this ++@@ -1855,7 +1857,7 @@ static int packet_rcv_spkt(struct sk_buf ++ * so that this procedure is noop. ++ */ ++ ++- if (skb->pkt_type == PACKET_LOOPBACK) +++ if (!(po->pkt_type & (1 << skb->pkt_type))) ++ goto out; ++ ++ if (!net_eq(dev_net(dev), sock_net(sk))) ++@@ -2082,12 +2084,12 @@ static int packet_rcv(struct sk_buff *sk ++ unsigned int snaplen, res; ++ bool is_drop_n_account = false; ++ ++- if (skb->pkt_type == PACKET_LOOPBACK) ++- goto drop; ++- ++ sk = pt->af_packet_priv; ++ po = pkt_sk(sk); ++ +++ if (!(po->pkt_type & (1 << skb->pkt_type))) +++ goto drop; +++ ++ if (!net_eq(dev_net(dev), sock_net(sk))) ++ goto drop; ++ ++@@ -2214,12 +2216,12 @@ static int tpacket_rcv(struct sk_buff *s ++ BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32); ++ BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48); ++ ++- if (skb->pkt_type == PACKET_LOOPBACK) ++- goto drop; ++- ++ sk = pt->af_packet_priv; ++ po = pkt_sk(sk); ++ +++ if (!(po->pkt_type & (1 << skb->pkt_type))) +++ goto drop; +++ ++ if (!net_eq(dev_net(dev), sock_net(sk))) ++ goto drop; ++ ++@@ -3313,6 +3315,7 @@ static int packet_create(struct net *net ++ mutex_init(&po->pg_vec_lock); ++ po->rollover = NULL; ++ po->prot_hook.func = packet_rcv; +++ po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK); ++ ++ if (sock->type == SOCK_PACKET) ++ po->prot_hook.func = packet_rcv_spkt; ++@@ -3935,6 +3938,16 @@ packet_setsockopt(struct socket *sock, i ++ po->xmit = val ? packet_direct_xmit : dev_queue_xmit; ++ return 0; ++ } +++ case PACKET_RECV_TYPE: +++ { +++ unsigned int val; +++ if (optlen != sizeof(val)) +++ return -EINVAL; +++ if (copy_from_user(&val, optval, sizeof(val))) +++ return -EFAULT; +++ po->pkt_type = val & ~BIT(PACKET_LOOPBACK); +++ return 0; +++ } ++ default: ++ return -ENOPROTOOPT; ++ } ++@@ -3987,6 +4000,13 @@ static int packet_getsockopt(struct sock ++ case PACKET_VNET_HDR: ++ val = po->has_vnet_hdr; ++ break; +++ case PACKET_RECV_TYPE: +++ if (len > sizeof(unsigned int)) +++ len = sizeof(unsigned int); +++ val = po->pkt_type; +++ +++ data = &val; +++ break; ++ case PACKET_VERSION: ++ val = po->tp_version; ++ break; ++--- a/net/packet/internal.h +++++ b/net/packet/internal.h ++@@ -135,6 +135,7 @@ struct packet_sock { ++ struct net_device __rcu *cached_dev; ++ int (*xmit)(struct sk_buff *skb); ++ struct packet_type prot_hook ____cacheline_aligned_in_smp; +++ unsigned int pkt_type; ++ }; ++ ++ static struct packet_sock *pkt_sk(struct sock *sk) +diff --git a/target/linux/generic/pending-4.14/640-netfilter-nf_flow_table-add-hardware-offload-support.patch b/target/linux/generic/pending-4.14/640-netfilter-nf_flow_table-add-hardware-offload-support.patch +new file mode 100644 +index 0000000000..f2aa14c238 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/640-netfilter-nf_flow_table-add-hardware-offload-support.patch +@@ -0,0 +1,565 @@ ++From: Pablo Neira Ayuso ++Date: Thu, 11 Jan 2018 16:32:00 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: add hardware offload support ++ ++This patch adds the infrastructure to offload flows to hardware, in case ++the nic/switch comes with built-in flow tables capabilities. ++ ++If the hardware comes with no hardware flow tables or they have ++limitations in terms of features, the existing infrastructure falls back ++to the software flow table implementation. ++ ++The software flow table garbage collector skips entries that resides in ++the hardware, so the hardware will be responsible for releasing this ++flow table entry too via flow_offload_dead(). ++ ++Hardware configuration, either to add or to delete entries, is done from ++the hardware offload workqueue, to ensure this is done from user context ++given that we may sleep when grabbing the mdio mutex. ++ ++Signed-off-by: Pablo Neira Ayuso ++--- ++ create mode 100644 net/netfilter/nf_flow_table_hw.c ++ ++--- a/include/linux/netdevice.h +++++ b/include/linux/netdevice.h ++@@ -826,6 +826,13 @@ struct xfrmdev_ops { ++ }; ++ #endif ++ +++struct flow_offload; +++ +++enum flow_offload_type { +++ FLOW_OFFLOAD_ADD = 0, +++ FLOW_OFFLOAD_DEL, +++}; +++ ++ /* ++ * This structure defines the management hooks for network devices. ++ * The following hooks can be defined; unless noted otherwise, they are ++@@ -1057,6 +1064,10 @@ struct xfrmdev_ops { ++ * int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh, ++ * u16 flags); ++ * +++ * int (*ndo_flow_offload)(enum flow_offload_type type, +++ * struct flow_offload *flow); +++ * Adds/deletes flow entry to/from net device flowtable. +++ * ++ * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier); ++ * Called to change device carrier. Soft-devices (like dummy, team, etc) ++ * which do not represent real hardware may define this to allow their ++@@ -1281,6 +1292,8 @@ struct net_device_ops { ++ int (*ndo_bridge_dellink)(struct net_device *dev, ++ struct nlmsghdr *nlh, ++ u16 flags); +++ int (*ndo_flow_offload)(enum flow_offload_type type, +++ struct flow_offload *flow); ++ int (*ndo_change_carrier)(struct net_device *dev, ++ bool new_carrier); ++ int (*ndo_get_phys_port_id)(struct net_device *dev, ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -20,11 +20,17 @@ struct nf_flowtable_type { ++ struct module *owner; ++ }; ++ +++enum nf_flowtable_flags { +++ NF_FLOWTABLE_F_HW = 0x1, +++}; +++ ++ struct nf_flowtable { ++ struct list_head list; ++ struct rhashtable rhashtable; ++ const struct nf_flowtable_type *type; +++ u32 flags; ++ struct delayed_work gc_work; +++ possible_net_t ft_net; ++ }; ++ ++ enum flow_offload_tuple_dir { ++@@ -69,6 +75,7 @@ struct flow_offload_tuple_rhash { ++ #define FLOW_OFFLOAD_DNAT 0x2 ++ #define FLOW_OFFLOAD_DYING 0x4 ++ #define FLOW_OFFLOAD_TEARDOWN 0x8 +++#define FLOW_OFFLOAD_HW 0x10 ++ ++ struct flow_offload { ++ struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; ++@@ -125,6 +132,22 @@ unsigned int nf_flow_offload_ip_hook(voi ++ unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state); ++ +++void nf_flow_offload_hw_add(struct net *net, struct flow_offload *flow, +++ struct nf_conn *ct); +++void nf_flow_offload_hw_del(struct net *net, struct flow_offload *flow); +++ +++struct nf_flow_table_hw { +++ struct module *owner; +++ void (*add)(struct net *net, struct flow_offload *flow, +++ struct nf_conn *ct); +++ void (*del)(struct net *net, struct flow_offload *flow); +++}; +++ +++int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload); +++void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload); +++ +++extern struct work_struct nf_flow_offload_hw_work; +++ ++ #define MODULE_ALIAS_NF_FLOWTABLE(family) \ ++ MODULE_ALIAS("nf-flowtable-" __stringify(family)) ++ ++--- a/include/uapi/linux/netfilter/nf_tables.h +++++ b/include/uapi/linux/netfilter/nf_tables.h ++@@ -1341,6 +1341,7 @@ enum nft_object_attributes { ++ * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) ++ * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) ++ * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) +++ * @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32) ++ */ ++ enum nft_flowtable_attributes { ++ NFTA_FLOWTABLE_UNSPEC, ++@@ -1350,6 +1351,7 @@ enum nft_flowtable_attributes { ++ NFTA_FLOWTABLE_USE, ++ NFTA_FLOWTABLE_HANDLE, ++ NFTA_FLOWTABLE_PAD, +++ NFTA_FLOWTABLE_FLAGS, ++ __NFTA_FLOWTABLE_MAX ++ }; ++ #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) ++--- a/net/netfilter/Kconfig +++++ b/net/netfilter/Kconfig ++@@ -692,6 +692,15 @@ config NF_FLOW_TABLE ++ ++ To compile it as a module, choose M here. ++ +++config NF_FLOW_TABLE_HW +++ tristate "Netfilter flow table hardware offload module" +++ depends on NF_FLOW_TABLE +++ help +++ This option adds hardware offload support for the flow table core +++ infrastructure. +++ +++ To compile it as a module, choose M here. +++ ++ config NETFILTER_XTABLES ++ tristate "Netfilter Xtables support (required for ip_tables)" ++ default m if NETFILTER_ADVANCED=n ++--- a/net/netfilter/Makefile +++++ b/net/netfilter/Makefile ++@@ -116,6 +116,7 @@ obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_t ++ nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o ++ ++ obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o +++obj-$(CONFIG_NF_FLOW_TABLE_HW) += nf_flow_table_hw.o ++ ++ # generic X tables ++ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -219,10 +219,16 @@ int flow_offload_add(struct nf_flowtable ++ } ++ EXPORT_SYMBOL_GPL(flow_offload_add); ++ +++static inline bool nf_flow_in_hw(const struct flow_offload *flow) +++{ +++ return flow->flags & FLOW_OFFLOAD_HW; +++} +++ ++ static void flow_offload_del(struct nf_flowtable *flow_table, ++ struct flow_offload *flow) ++ { ++ struct flow_offload_entry *e; +++ struct net *net = read_pnet(&flow_table->ft_net); ++ ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++@@ -237,6 +243,9 @@ static void flow_offload_del(struct nf_f ++ if (!(flow->flags & FLOW_OFFLOAD_TEARDOWN)) ++ flow_offload_fixup_ct_state(e->ct); ++ +++ if (nf_flow_in_hw(flow)) +++ nf_flow_offload_hw_del(net, flow); +++ ++ flow_offload_free(flow); ++ } ++ ++@@ -350,6 +359,9 @@ static int nf_flow_offload_gc_step(struc ++ if (!teardown) ++ nf_ct_offload_timeout(flow); ++ +++ if (nf_flow_in_hw(flow) && !teardown) +++ continue; +++ ++ if (nf_flow_has_expired(flow) || teardown) ++ flow_offload_del(flow_table, flow); ++ } ++@@ -485,10 +497,43 @@ int nf_flow_dnat_port(const struct flow_ ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_dnat_port); ++ +++static const struct nf_flow_table_hw __rcu *nf_flow_table_hw_hook __read_mostly; +++ +++static int nf_flow_offload_hw_init(struct nf_flowtable *flow_table) +++{ +++ const struct nf_flow_table_hw *offload; +++ +++ if (!rcu_access_pointer(nf_flow_table_hw_hook)) +++ request_module("nf-flow-table-hw"); +++ +++ rcu_read_lock(); +++ offload = rcu_dereference(nf_flow_table_hw_hook); +++ if (!offload) +++ goto err_no_hw_offload; +++ +++ if (!try_module_get(offload->owner)) +++ goto err_no_hw_offload; +++ +++ rcu_read_unlock(); +++ +++ return 0; +++ +++err_no_hw_offload: +++ rcu_read_unlock(); +++ +++ return -EOPNOTSUPP; +++} +++ ++ int nf_flow_table_init(struct nf_flowtable *flowtable) ++ { ++ int err; ++ +++ if (flowtable->flags & NF_FLOWTABLE_F_HW) { +++ err = nf_flow_offload_hw_init(flowtable); +++ if (err) +++ return err; +++ } +++ ++ INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc); ++ ++ err = rhashtable_init(&flowtable->rhashtable, ++@@ -526,6 +571,8 @@ static void nf_flow_table_iterate_cleanu ++ { ++ nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev); ++ flush_delayed_work(&flowtable->gc_work); +++ if (flowtable->flags & NF_FLOWTABLE_F_HW) +++ flush_work(&nf_flow_offload_hw_work); ++ } ++ ++ void nf_flow_table_cleanup(struct net *net, struct net_device *dev) ++@@ -539,6 +586,26 @@ void nf_flow_table_cleanup(struct net *n ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); ++ +++struct work_struct nf_flow_offload_hw_work; +++EXPORT_SYMBOL_GPL(nf_flow_offload_hw_work); +++ +++/* Give the hardware workqueue the chance to remove entries from hardware.*/ +++static void nf_flow_offload_hw_free(struct nf_flowtable *flowtable) +++{ +++ const struct nf_flow_table_hw *offload; +++ +++ flush_work(&nf_flow_offload_hw_work); +++ +++ rcu_read_lock(); +++ offload = rcu_dereference(nf_flow_table_hw_hook); +++ if (!offload) { +++ rcu_read_unlock(); +++ return; +++ } +++ module_put(offload->owner); +++ rcu_read_unlock(); +++} +++ ++ void nf_flow_table_free(struct nf_flowtable *flow_table) ++ { ++ mutex_lock(&flowtable_lock); ++@@ -548,9 +615,58 @@ void nf_flow_table_free(struct nf_flowta ++ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); ++ WARN_ON(!nf_flow_offload_gc_step(flow_table)); ++ rhashtable_destroy(&flow_table->rhashtable); +++ if (flow_table->flags & NF_FLOWTABLE_F_HW) +++ nf_flow_offload_hw_free(flow_table); ++ } ++ EXPORT_SYMBOL_GPL(nf_flow_table_free); ++ +++/* Must be called from user context. */ +++void nf_flow_offload_hw_add(struct net *net, struct flow_offload *flow, +++ struct nf_conn *ct) +++{ +++ const struct nf_flow_table_hw *offload; +++ +++ rcu_read_lock(); +++ offload = rcu_dereference(nf_flow_table_hw_hook); +++ if (offload) +++ offload->add(net, flow, ct); +++ rcu_read_unlock(); +++} +++EXPORT_SYMBOL_GPL(nf_flow_offload_hw_add); +++ +++/* Must be called from user context. */ +++void nf_flow_offload_hw_del(struct net *net, struct flow_offload *flow) +++{ +++ const struct nf_flow_table_hw *offload; +++ +++ rcu_read_lock(); +++ offload = rcu_dereference(nf_flow_table_hw_hook); +++ if (offload) +++ offload->del(net, flow); +++ rcu_read_unlock(); +++} +++EXPORT_SYMBOL_GPL(nf_flow_offload_hw_del); +++ +++int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload) +++{ +++ if (rcu_access_pointer(nf_flow_table_hw_hook)) +++ return -EBUSY; +++ +++ rcu_assign_pointer(nf_flow_table_hw_hook, offload); +++ +++ return 0; +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_hw_register); +++ +++void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload) +++{ +++ WARN_ON(rcu_access_pointer(nf_flow_table_hw_hook) != offload); +++ rcu_assign_pointer(nf_flow_table_hw_hook, NULL); +++ +++ synchronize_rcu(); +++} +++EXPORT_SYMBOL_GPL(nf_flow_table_hw_unregister); +++ ++ static int nf_flow_table_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++ { ++--- /dev/null +++++ b/net/netfilter/nf_flow_table_hw.c ++@@ -0,0 +1,169 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++static DEFINE_SPINLOCK(flow_offload_hw_pending_list_lock); +++static LIST_HEAD(flow_offload_hw_pending_list); +++ +++static DEFINE_MUTEX(nf_flow_offload_hw_mutex); +++ +++struct flow_offload_hw { +++ struct list_head list; +++ enum flow_offload_type type; +++ struct flow_offload *flow; +++ struct nf_conn *ct; +++ possible_net_t flow_hw_net; +++}; +++ +++static int do_flow_offload_hw(struct net *net, struct flow_offload *flow, +++ int type) +++{ +++ struct net_device *indev; +++ int ret, ifindex; +++ +++ ifindex = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.iifidx; +++ indev = dev_get_by_index(net, ifindex); +++ if (WARN_ON(!indev)) +++ return 0; +++ +++ mutex_lock(&nf_flow_offload_hw_mutex); +++ ret = indev->netdev_ops->ndo_flow_offload(type, flow); +++ mutex_unlock(&nf_flow_offload_hw_mutex); +++ +++ dev_put(indev); +++ +++ return ret; +++} +++ +++static void flow_offload_hw_work_add(struct flow_offload_hw *offload) +++{ +++ struct net *net; +++ int ret; +++ +++ if (nf_ct_is_dying(offload->ct)) +++ return; +++ +++ net = read_pnet(&offload->flow_hw_net); +++ ret = do_flow_offload_hw(net, offload->flow, FLOW_OFFLOAD_ADD); +++ if (ret >= 0) +++ offload->flow->flags |= FLOW_OFFLOAD_HW; +++} +++ +++static void flow_offload_hw_work_del(struct flow_offload_hw *offload) +++{ +++ struct net *net = read_pnet(&offload->flow_hw_net); +++ +++ do_flow_offload_hw(net, offload->flow, FLOW_OFFLOAD_DEL); +++} +++ +++static void flow_offload_hw_work(struct work_struct *work) +++{ +++ struct flow_offload_hw *offload, *next; +++ LIST_HEAD(hw_offload_pending); +++ +++ spin_lock_bh(&flow_offload_hw_pending_list_lock); +++ list_replace_init(&flow_offload_hw_pending_list, &hw_offload_pending); +++ spin_unlock_bh(&flow_offload_hw_pending_list_lock); +++ +++ list_for_each_entry_safe(offload, next, &hw_offload_pending, list) { +++ switch (offload->type) { +++ case FLOW_OFFLOAD_ADD: +++ flow_offload_hw_work_add(offload); +++ break; +++ case FLOW_OFFLOAD_DEL: +++ flow_offload_hw_work_del(offload); +++ break; +++ } +++ if (offload->ct) +++ nf_conntrack_put(&offload->ct->ct_general); +++ list_del(&offload->list); +++ kfree(offload); +++ } +++} +++ +++static void flow_offload_queue_work(struct flow_offload_hw *offload) +++{ +++ spin_lock_bh(&flow_offload_hw_pending_list_lock); +++ list_add_tail(&offload->list, &flow_offload_hw_pending_list); +++ spin_unlock_bh(&flow_offload_hw_pending_list_lock); +++ +++ schedule_work(&nf_flow_offload_hw_work); +++} +++ +++static void flow_offload_hw_add(struct net *net, struct flow_offload *flow, +++ struct nf_conn *ct) +++{ +++ struct flow_offload_hw *offload; +++ +++ offload = kmalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); +++ if (!offload) +++ return; +++ +++ nf_conntrack_get(&ct->ct_general); +++ offload->type = FLOW_OFFLOAD_ADD; +++ offload->ct = ct; +++ offload->flow = flow; +++ write_pnet(&offload->flow_hw_net, net); +++ +++ flow_offload_queue_work(offload); +++} +++ +++static void flow_offload_hw_del(struct net *net, struct flow_offload *flow) +++{ +++ struct flow_offload_hw *offload; +++ +++ offload = kmalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); +++ if (!offload) +++ return; +++ +++ offload->type = FLOW_OFFLOAD_DEL; +++ offload->ct = NULL; +++ offload->flow = flow; +++ write_pnet(&offload->flow_hw_net, net); +++ +++ flow_offload_queue_work(offload); +++} +++ +++static const struct nf_flow_table_hw flow_offload_hw = { +++ .add = flow_offload_hw_add, +++ .del = flow_offload_hw_del, +++ .owner = THIS_MODULE, +++}; +++ +++static int __init nf_flow_table_hw_module_init(void) +++{ +++ INIT_WORK(&nf_flow_offload_hw_work, flow_offload_hw_work); +++ nf_flow_table_hw_register(&flow_offload_hw); +++ +++ return 0; +++} +++ +++static void __exit nf_flow_table_hw_module_exit(void) +++{ +++ struct flow_offload_hw *offload, *next; +++ LIST_HEAD(hw_offload_pending); +++ +++ nf_flow_table_hw_unregister(&flow_offload_hw); +++ cancel_work_sync(&nf_flow_offload_hw_work); +++ +++ list_for_each_entry_safe(offload, next, &hw_offload_pending, list) { +++ if (offload->ct) +++ nf_conntrack_put(&offload->ct->ct_general); +++ list_del(&offload->list); +++ kfree(offload); +++ } +++} +++ +++module_init(nf_flow_table_hw_module_init); +++module_exit(nf_flow_table_hw_module_exit); +++ +++MODULE_LICENSE("GPL"); +++MODULE_AUTHOR("Pablo Neira Ayuso "); +++MODULE_ALIAS("nf-flow-table-hw"); ++--- a/net/netfilter/nf_tables_api.c +++++ b/net/netfilter/nf_tables_api.c ++@@ -4961,6 +4961,14 @@ static int nf_tables_flowtable_parse_hoo ++ if (err < 0) ++ goto err1; ++ +++ for (i = 0; i < n; i++) { +++ if (flowtable->data.flags & NF_FLOWTABLE_F_HW && +++ !dev_array[i]->netdev_ops->ndo_flow_offload) { +++ err = -EOPNOTSUPP; +++ goto err1; +++ } +++ } +++ ++ ops = kzalloc(sizeof(struct nf_hook_ops) * n, GFP_KERNEL); ++ if (!ops) { ++ err = -ENOMEM; ++@@ -5091,10 +5099,19 @@ static int nf_tables_newflowtable(struct ++ } ++ ++ flowtable->data.type = type; +++ write_pnet(&flowtable->data.ft_net, net); +++ ++ err = type->init(&flowtable->data); ++ if (err < 0) ++ goto err3; ++ +++ if (nla[NFTA_FLOWTABLE_FLAGS]) { +++ flowtable->data.flags = +++ ntohl(nla_get_be32(nla[NFTA_FLOWTABLE_FLAGS])); +++ if (flowtable->data.flags & ~NF_FLOWTABLE_F_HW) +++ goto err4; +++ } +++ ++ err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK], ++ flowtable); ++ if (err < 0) ++@@ -5192,7 +5209,8 @@ static int nf_tables_fill_flowtable_info ++ nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || ++ nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || ++ nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), ++- NFTA_FLOWTABLE_PAD)) +++ NFTA_FLOWTABLE_PAD) || +++ nla_put_be32(skb, NFTA_FLOWTABLE_FLAGS, htonl(flowtable->data.flags))) ++ goto nla_put_failure; ++ ++ nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); ++--- a/net/netfilter/nft_flow_offload.c +++++ b/net/netfilter/nft_flow_offload.c ++@@ -110,6 +110,9 @@ static void nft_flow_offload_eval(const ++ if (ret < 0) ++ goto err_flow_add; ++ +++ if (flowtable->flags & NF_FLOWTABLE_F_HW) +++ nf_flow_offload_hw_add(nft_net(pkt), flow, ct); +++ ++ return; ++ ++ err_flow_add: +diff --git a/target/linux/generic/pending-4.14/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch b/target/linux/generic/pending-4.14/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch +new file mode 100644 +index 0000000000..e1b13a1ad4 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch +@@ -0,0 +1,306 @@ ++From: Felix Fietkau ++Date: Thu, 15 Mar 2018 20:46:31 +0100 ++Subject: [PATCH] netfilter: nf_flow_table: support hw offload through ++ virtual interfaces ++ ++There are hardware offload devices that support offloading VLANs and ++PPPoE devices. Additionally, it is useful to be able to offload packets ++routed through bridge interfaces as well. ++Add support for finding the path to the offload device through these ++virtual interfaces, while collecting useful parameters for the offload ++device, like VLAN ID/protocol, PPPoE session and Ethernet MAC address. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/linux/netdevice.h +++++ b/include/linux/netdevice.h ++@@ -827,6 +827,7 @@ struct xfrmdev_ops { ++ #endif ++ ++ struct flow_offload; +++struct flow_offload_hw_path; ++ ++ enum flow_offload_type { ++ FLOW_OFFLOAD_ADD = 0, ++@@ -1064,8 +1065,15 @@ enum flow_offload_type { ++ * int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh, ++ * u16 flags); ++ * +++ * int (*ndo_flow_offload_check)(struct flow_offload_hw_path *path); +++ * For virtual devices like bridges, vlan, and pppoe, fill in the +++ * underlying network device that can be used for offloading connections. +++ * Return an error if offloading is not supported. +++ * ++ * int (*ndo_flow_offload)(enum flow_offload_type type, ++- * struct flow_offload *flow); +++ * struct flow_offload *flow, +++ * struct flow_offload_hw_path *src, +++ * struct flow_offload_hw_path *dest); ++ * Adds/deletes flow entry to/from net device flowtable. ++ * ++ * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier); ++@@ -1292,8 +1300,11 @@ struct net_device_ops { ++ int (*ndo_bridge_dellink)(struct net_device *dev, ++ struct nlmsghdr *nlh, ++ u16 flags); +++ int (*ndo_flow_offload_check)(struct flow_offload_hw_path *path); ++ int (*ndo_flow_offload)(enum flow_offload_type type, ++- struct flow_offload *flow); +++ struct flow_offload *flow, +++ struct flow_offload_hw_path *src, +++ struct flow_offload_hw_path *dest); ++ int (*ndo_change_carrier)(struct net_device *dev, ++ bool new_carrier); ++ int (*ndo_get_phys_port_id)(struct net_device *dev, ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -86,6 +86,21 @@ struct flow_offload { ++ }; ++ }; ++ +++#define FLOW_OFFLOAD_PATH_ETHERNET BIT(0) +++#define FLOW_OFFLOAD_PATH_VLAN BIT(1) +++#define FLOW_OFFLOAD_PATH_PPPOE BIT(2) +++ +++struct flow_offload_hw_path { +++ struct net_device *dev; +++ u32 flags; +++ +++ u8 eth_src[ETH_ALEN]; +++ u8 eth_dest[ETH_ALEN]; +++ u16 vlan_proto; +++ u16 vlan_id; +++ u16 pppoe_sid; +++}; +++ ++ #define NF_FLOW_TIMEOUT (30 * HZ) ++ ++ struct nf_flow_route { ++--- a/net/netfilter/nf_flow_table_hw.c +++++ b/net/netfilter/nf_flow_table_hw.c ++@@ -19,48 +19,77 @@ struct flow_offload_hw { ++ enum flow_offload_type type; ++ struct flow_offload *flow; ++ struct nf_conn *ct; ++- possible_net_t flow_hw_net; +++ +++ struct flow_offload_hw_path src; +++ struct flow_offload_hw_path dest; ++ }; ++ ++-static int do_flow_offload_hw(struct net *net, struct flow_offload *flow, ++- int type) +++static void flow_offload_check_ethernet(struct flow_offload_tuple *tuple, +++ struct dst_entry *dst, +++ struct flow_offload_hw_path *path) ++ { ++- struct net_device *indev; ++- int ret, ifindex; +++ struct net_device *dev = path->dev; +++ struct neighbour *n; ++ ++- ifindex = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.iifidx; ++- indev = dev_get_by_index(net, ifindex); ++- if (WARN_ON(!indev)) ++- return 0; ++- ++- mutex_lock(&nf_flow_offload_hw_mutex); ++- ret = indev->netdev_ops->ndo_flow_offload(type, flow); ++- mutex_unlock(&nf_flow_offload_hw_mutex); +++ if (dev->type != ARPHRD_ETHER) +++ return; ++ ++- dev_put(indev); +++ memcpy(path->eth_src, path->dev->dev_addr, ETH_ALEN); +++ n = dst_neigh_lookup(dst, &tuple->src_v4); +++ if (!n) +++ return; ++ ++- return ret; +++ memcpy(path->eth_dest, n->ha, ETH_ALEN); +++ path->flags |= FLOW_OFFLOAD_PATH_ETHERNET; +++ neigh_release(n); ++ } ++ ++-static void flow_offload_hw_work_add(struct flow_offload_hw *offload) +++static int flow_offload_check_path(struct net *net, +++ struct flow_offload_tuple *tuple, +++ struct dst_entry *dst, +++ struct flow_offload_hw_path *path) ++ { ++- struct net *net; ++- int ret; +++ struct net_device *dev; ++ ++- if (nf_ct_is_dying(offload->ct)) ++- return; +++ dev = dev_get_by_index_rcu(net, tuple->iifidx); +++ if (!dev) +++ return -ENOENT; +++ +++ path->dev = dev; +++ flow_offload_check_ethernet(tuple, dst, path); ++ ++- net = read_pnet(&offload->flow_hw_net); ++- ret = do_flow_offload_hw(net, offload->flow, FLOW_OFFLOAD_ADD); ++- if (ret >= 0) ++- offload->flow->flags |= FLOW_OFFLOAD_HW; +++ if (dev->netdev_ops->ndo_flow_offload_check) +++ return dev->netdev_ops->ndo_flow_offload_check(path); +++ +++ return 0; ++ } ++ ++-static void flow_offload_hw_work_del(struct flow_offload_hw *offload) +++static int do_flow_offload_hw(struct flow_offload_hw *offload) ++ { ++- struct net *net = read_pnet(&offload->flow_hw_net); +++ struct net_device *src_dev = offload->src.dev; +++ struct net_device *dest_dev = offload->dest.dev; +++ int ret; +++ +++ ret = src_dev->netdev_ops->ndo_flow_offload(offload->type, +++ offload->flow, +++ &offload->src, +++ &offload->dest); +++ +++ /* restore devices in case the driver mangled them */ +++ offload->src.dev = src_dev; +++ offload->dest.dev = dest_dev; ++ ++- do_flow_offload_hw(net, offload->flow, FLOW_OFFLOAD_DEL); +++ return ret; +++} +++ +++static void flow_offload_hw_free(struct flow_offload_hw *offload) +++{ +++ dev_put(offload->src.dev); +++ dev_put(offload->dest.dev); +++ if (offload->ct) +++ nf_conntrack_put(&offload->ct->ct_general); +++ list_del(&offload->list); +++ kfree(offload); ++ } ++ ++ static void flow_offload_hw_work(struct work_struct *work) ++@@ -73,18 +102,22 @@ static void flow_offload_hw_work(struct ++ spin_unlock_bh(&flow_offload_hw_pending_list_lock); ++ ++ list_for_each_entry_safe(offload, next, &hw_offload_pending, list) { +++ mutex_lock(&nf_flow_offload_hw_mutex); ++ switch (offload->type) { ++ case FLOW_OFFLOAD_ADD: ++- flow_offload_hw_work_add(offload); +++ if (nf_ct_is_dying(offload->ct)) +++ break; +++ +++ if (do_flow_offload_hw(offload) >= 0) +++ offload->flow->flags |= FLOW_OFFLOAD_HW; ++ break; ++ case FLOW_OFFLOAD_DEL: ++- flow_offload_hw_work_del(offload); +++ do_flow_offload_hw(offload); ++ break; ++ } ++- if (offload->ct) ++- nf_conntrack_put(&offload->ct->ct_general); ++- list_del(&offload->list); ++- kfree(offload); +++ mutex_unlock(&nf_flow_offload_hw_mutex); +++ +++ flow_offload_hw_free(offload); ++ } ++ } ++ ++@@ -97,20 +130,56 @@ static void flow_offload_queue_work(stru ++ schedule_work(&nf_flow_offload_hw_work); ++ } ++ +++static struct flow_offload_hw * +++flow_offload_hw_prepare(struct net *net, struct flow_offload *flow) +++{ +++ struct flow_offload_hw_path src = {}; +++ struct flow_offload_hw_path dest = {}; +++ struct flow_offload_tuple *tuple_s, *tuple_d; +++ struct flow_offload_hw *offload = NULL; +++ +++ rcu_read_lock_bh(); +++ +++ tuple_s = &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple; +++ tuple_d = &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple; +++ +++ if (flow_offload_check_path(net, tuple_s, tuple_d->dst_cache, &src)) +++ goto out; +++ +++ if (flow_offload_check_path(net, tuple_d, tuple_s->dst_cache, &dest)) +++ goto out; +++ +++ if (!src.dev->netdev_ops->ndo_flow_offload) +++ goto out; +++ +++ offload = kzalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); +++ if (!offload) +++ goto out; +++ +++ dev_hold(src.dev); +++ dev_hold(dest.dev); +++ offload->src = src; +++ offload->dest = dest; +++ offload->flow = flow; +++ +++out: +++ rcu_read_unlock_bh(); +++ +++ return offload; +++} +++ ++ static void flow_offload_hw_add(struct net *net, struct flow_offload *flow, ++ struct nf_conn *ct) ++ { ++ struct flow_offload_hw *offload; ++ ++- offload = kmalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); +++ offload = flow_offload_hw_prepare(net, flow); ++ if (!offload) ++ return; ++ ++ nf_conntrack_get(&ct->ct_general); ++ offload->type = FLOW_OFFLOAD_ADD; ++ offload->ct = ct; ++- offload->flow = flow; ++- write_pnet(&offload->flow_hw_net, net); ++ ++ flow_offload_queue_work(offload); ++ } ++@@ -119,14 +188,11 @@ static void flow_offload_hw_del(struct n ++ { ++ struct flow_offload_hw *offload; ++ ++- offload = kmalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); +++ offload = flow_offload_hw_prepare(net, flow); ++ if (!offload) ++ return; ++ ++ offload->type = FLOW_OFFLOAD_DEL; ++- offload->ct = NULL; ++- offload->flow = flow; ++- write_pnet(&offload->flow_hw_net, net); ++ ++ flow_offload_queue_work(offload); ++ } ++@@ -153,12 +219,8 @@ static void __exit nf_flow_table_hw_modu ++ nf_flow_table_hw_unregister(&flow_offload_hw); ++ cancel_work_sync(&nf_flow_offload_hw_work); ++ ++- list_for_each_entry_safe(offload, next, &hw_offload_pending, list) { ++- if (offload->ct) ++- nf_conntrack_put(&offload->ct->ct_general); ++- list_del(&offload->list); ++- kfree(offload); ++- } +++ list_for_each_entry_safe(offload, next, &hw_offload_pending, list) +++ flow_offload_hw_free(offload); ++ } ++ ++ module_init(nf_flow_table_hw_module_init); +diff --git a/target/linux/generic/pending-4.14/642-net-8021q-support-hardware-flow-table-offload.patch b/target/linux/generic/pending-4.14/642-net-8021q-support-hardware-flow-table-offload.patch +new file mode 100644 +index 0000000000..4adad67d54 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/642-net-8021q-support-hardware-flow-table-offload.patch +@@ -0,0 +1,60 @@ ++From: Felix Fietkau ++Date: Thu, 15 Mar 2018 20:49:58 +0100 ++Subject: [PATCH] net: 8021q: support hardware flow table offload ++ ++Add the VLAN ID and protocol information ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/8021q/vlan_dev.c +++++ b/net/8021q/vlan_dev.c ++@@ -32,6 +32,10 @@ ++ #include ++ #include ++ #include +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++#include +++#include +++#endif ++ ++ #include "vlan.h" ++ #include "vlanproc.h" ++@@ -769,6 +773,27 @@ static int vlan_dev_get_iflink(const str ++ return real_dev->ifindex; ++ } ++ +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++static int vlan_dev_flow_offload_check(struct flow_offload_hw_path *path) +++{ +++ struct net_device *dev = path->dev; +++ struct vlan_dev_priv *vlan = vlan_dev_priv(dev); +++ +++ if (path->flags & FLOW_OFFLOAD_PATH_VLAN) +++ return -EEXIST; +++ +++ path->flags |= FLOW_OFFLOAD_PATH_VLAN; +++ path->vlan_proto = vlan->vlan_proto; +++ path->vlan_id = vlan->vlan_id; +++ path->dev = vlan->real_dev; +++ +++ if (vlan->real_dev->netdev_ops->ndo_flow_offload_check) +++ return vlan->real_dev->netdev_ops->ndo_flow_offload_check(path); +++ +++ return 0; +++} +++#endif /* CONFIG_NF_FLOW_TABLE */ +++ ++ static const struct ethtool_ops vlan_ethtool_ops = { ++ .get_link_ksettings = vlan_ethtool_get_link_ksettings, ++ .get_drvinfo = vlan_ethtool_get_drvinfo, ++@@ -806,6 +831,9 @@ static const struct net_device_ops vlan_ ++ .ndo_fix_features = vlan_dev_fix_features, ++ .ndo_get_lock_subclass = vlan_dev_get_lock_subclass, ++ .ndo_get_iflink = vlan_dev_get_iflink, +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++ .ndo_flow_offload_check = vlan_dev_flow_offload_check, +++#endif ++ }; ++ ++ static void vlan_dev_free(struct net_device *dev) +diff --git a/target/linux/generic/pending-4.14/643-net-bridge-support-hardware-flow-table-offload.patch b/target/linux/generic/pending-4.14/643-net-bridge-support-hardware-flow-table-offload.patch +new file mode 100644 +index 0000000000..b54d3cb48f +--- /dev/null ++++ b/target/linux/generic/pending-4.14/643-net-bridge-support-hardware-flow-table-offload.patch +@@ -0,0 +1,61 @@ ++From: Felix Fietkau ++Date: Thu, 15 Mar 2018 20:50:37 +0100 ++Subject: [PATCH] net: bridge: support hardware flow table offload ++ ++Look up the real device and pass it on ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/bridge/br_device.c +++++ b/net/bridge/br_device.c ++@@ -18,6 +18,10 @@ ++ #include ++ #include ++ #include +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++#include +++#include +++#endif ++ ++ #include ++ #include "br_private.h" ++@@ -346,6 +350,28 @@ static const struct ethtool_ops br_ethto ++ .get_link = ethtool_op_get_link, ++ }; ++ +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++static int br_flow_offload_check(struct flow_offload_hw_path *path) +++{ +++ struct net_device *dev = path->dev; +++ struct net_bridge *br = netdev_priv(dev); +++ struct net_bridge_fdb_entry *dst; +++ +++ if (!(path->flags & FLOW_OFFLOAD_PATH_ETHERNET)) +++ return -EINVAL; +++ +++ dst = br_fdb_find_rcu(br, path->eth_dest, path->vlan_id); +++ if (!dst || !dst->dst) +++ return -ENOENT; +++ +++ path->dev = dst->dst->dev; +++ if (path->dev->netdev_ops->ndo_flow_offload_check) +++ return path->dev->netdev_ops->ndo_flow_offload_check(path); +++ +++ return 0; +++} +++#endif /* CONFIG_NF_FLOW_TABLE */ +++ ++ static const struct net_device_ops br_netdev_ops = { ++ .ndo_open = br_dev_open, ++ .ndo_stop = br_dev_stop, ++@@ -373,6 +399,9 @@ static const struct net_device_ops br_ne ++ .ndo_bridge_setlink = br_setlink, ++ .ndo_bridge_dellink = br_dellink, ++ .ndo_features_check = passthru_features_check, +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++ .ndo_flow_offload_check = br_flow_offload_check, +++#endif ++ }; ++ ++ static struct device_type br_type = { +diff --git a/target/linux/generic/pending-4.14/644-net-pppoe-support-hardware-flow-table-offload.patch b/target/linux/generic/pending-4.14/644-net-pppoe-support-hardware-flow-table-offload.patch +new file mode 100644 +index 0000000000..191cbcfb82 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/644-net-pppoe-support-hardware-flow-table-offload.patch +@@ -0,0 +1,125 @@ ++From: Felix Fietkau ++Date: Thu, 15 Mar 2018 21:15:00 +0100 ++Subject: [PATCH] net: pppoe: support hardware flow table offload ++ ++Pass on the PPPoE session ID and the remote MAC address ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/ppp/ppp_generic.c +++++ b/drivers/net/ppp/ppp_generic.c ++@@ -56,6 +56,11 @@ ++ #include ++ #include ++ +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++#include +++#include +++#endif +++ ++ #define PPP_VERSION "2.4.2" ++ ++ /* ++@@ -1382,12 +1387,37 @@ static void ppp_dev_priv_destructor(stru ++ ppp_destroy_interface(ppp); ++ } ++ +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++static int ppp_flow_offload_check(struct flow_offload_hw_path *path) +++{ +++ struct ppp *ppp = netdev_priv(path->dev); +++ struct ppp_channel *chan; +++ struct channel *pch; +++ +++ if (ppp->flags & SC_MULTILINK) +++ return -EOPNOTSUPP; +++ +++ if (list_empty(&ppp->channels)) +++ return -ENODEV; +++ +++ pch = list_first_entry(&ppp->channels, struct channel, clist); +++ chan = pch->chan; +++ if (!chan->ops->flow_offload_check) +++ return -EOPNOTSUPP; +++ +++ return chan->ops->flow_offload_check(chan, path); +++} +++#endif /* CONFIG_NF_FLOW_TABLE */ +++ ++ static const struct net_device_ops ppp_netdev_ops = { ++ .ndo_init = ppp_dev_init, ++ .ndo_uninit = ppp_dev_uninit, ++ .ndo_start_xmit = ppp_start_xmit, ++ .ndo_do_ioctl = ppp_net_ioctl, ++ .ndo_get_stats64 = ppp_get_stats64, +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++ .ndo_flow_offload_check = ppp_flow_offload_check, +++#endif ++ }; ++ ++ static struct device_type ppp_type = { ++--- a/drivers/net/ppp/pppoe.c +++++ b/drivers/net/ppp/pppoe.c ++@@ -78,6 +78,11 @@ ++ #include ++ #include ++ +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++#include +++#include +++#endif +++ ++ #include ++ #include ++ #include ++@@ -981,8 +986,36 @@ static int pppoe_xmit(struct ppp_channel ++ return __pppoe_xmit(sk, skb); ++ } ++ +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++static int pppoe_flow_offload_check(struct ppp_channel *chan, +++ struct flow_offload_hw_path *path) +++{ +++ struct sock *sk = (struct sock *)chan->private; +++ struct pppox_sock *po = pppox_sk(sk); +++ struct net_device *dev = po->pppoe_dev; +++ +++ if (sock_flag(sk, SOCK_DEAD) || +++ !(sk->sk_state & PPPOX_CONNECTED) || !dev) +++ return -ENODEV; +++ +++ path->dev = po->pppoe_dev; +++ path->flags |= FLOW_OFFLOAD_PATH_PPPOE; +++ memcpy(path->eth_src, po->pppoe_dev->dev_addr, ETH_ALEN); +++ memcpy(path->eth_dest, po->pppoe_pa.remote, ETH_ALEN); +++ path->pppoe_sid = be16_to_cpu(po->num); +++ +++ if (path->dev->netdev_ops->ndo_flow_offload_check) +++ return path->dev->netdev_ops->ndo_flow_offload_check(path); +++ +++ return 0; +++} +++#endif /* CONFIG_NF_FLOW_TABLE */ +++ ++ static const struct ppp_channel_ops pppoe_chan_ops = { ++ .start_xmit = pppoe_xmit, +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++ .flow_offload_check = pppoe_flow_offload_check, +++#endif ++ }; ++ ++ static int pppoe_recvmsg(struct socket *sock, struct msghdr *m, ++--- a/include/linux/ppp_channel.h +++++ b/include/linux/ppp_channel.h ++@@ -32,6 +32,10 @@ struct ppp_channel_ops { ++ int (*start_xmit)(struct ppp_channel *, struct sk_buff *); ++ /* Handle an ioctl call that has come in via /dev/ppp. */ ++ int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long); +++ +++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) +++ int (*flow_offload_check)(struct ppp_channel *, struct flow_offload_hw_path *); +++#endif ++ }; ++ ++ struct ppp_channel { +diff --git a/target/linux/generic/pending-4.14/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch b/target/linux/generic/pending-4.14/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch +new file mode 100644 +index 0000000000..ad6f42bb4e +--- /dev/null ++++ b/target/linux/generic/pending-4.14/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch +@@ -0,0 +1,37 @@ ++From: Felix Fietkau ++Date: Sun, 25 Mar 2018 21:10:55 +0200 ++Subject: [PATCH] netfilter: nf_flow_table: rework hardware offload timeout ++ handling ++ ++Some offload implementations send keepalive packets + explicit ++notifications of TCP FIN/RST packets. In this case it is more convenient ++to simply let the driver update flow->timeout handling and use the ++regular flow offload gc step. ++ ++For drivers that manage their own lifetime, a separate flag can be set ++to avoid gc timeouts. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -76,6 +76,7 @@ struct flow_offload_tuple_rhash { ++ #define FLOW_OFFLOAD_DYING 0x4 ++ #define FLOW_OFFLOAD_TEARDOWN 0x8 ++ #define FLOW_OFFLOAD_HW 0x10 +++#define FLOW_OFFLOAD_KEEP 0x20 ++ ++ struct flow_offload { ++ struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; ++--- a/net/netfilter/nf_flow_table_core.c +++++ b/net/netfilter/nf_flow_table_core.c ++@@ -359,7 +359,7 @@ static int nf_flow_offload_gc_step(struc ++ if (!teardown) ++ nf_ct_offload_timeout(flow); ++ ++- if (nf_flow_in_hw(flow) && !teardown) +++ if ((flow->flags & FLOW_OFFLOAD_KEEP) && !teardown) ++ continue; ++ ++ if (nf_flow_has_expired(flow) || teardown) +diff --git a/target/linux/generic/pending-4.14/646-netfilter-nf_flow_table-rework-private-driver-data.patch b/target/linux/generic/pending-4.14/646-netfilter-nf_flow_table-rework-private-driver-data.patch +new file mode 100644 +index 0000000000..f94d7ad301 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/646-netfilter-nf_flow_table-rework-private-driver-data.patch +@@ -0,0 +1,25 @@ ++From: Felix Fietkau ++Date: Fri, 27 Apr 2018 14:42:14 +0200 ++Subject: [PATCH] netfilter: nf_flow_table: rework private driver data ++ ++Move the timeout out of the union, since it can be shared between the ++driver and the stack. Add a private pointer that the driver can use to ++point to its own data structures ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/netfilter/nf_flow_table.h +++++ b/include/net/netfilter/nf_flow_table.h ++@@ -81,9 +81,10 @@ struct flow_offload_tuple_rhash { ++ struct flow_offload { ++ struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; ++ u32 flags; +++ u32 timeout; ++ union { ++ /* Your private driver data here. */ ++- u32 timeout; +++ void *priv; ++ }; ++ }; ++ +diff --git a/target/linux/generic/pending-4.14/655-increase_skb_pad.patch b/target/linux/generic/pending-4.14/655-increase_skb_pad.patch +new file mode 100644 +index 0000000000..fa47fe62a8 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/655-increase_skb_pad.patch +@@ -0,0 +1,20 @@ ++From: Felix Fietkau ++Subject: kernel: add a few patches for avoiding unnecessary skb reallocations - significantly improves ethernet<->wireless performance ++ ++lede-commit: 6f89cffc9add6939d44a6b54cf9a5e77849aa7fd ++Signed-off-by: Felix Fietkau ++--- ++ include/linux/skbuff.h | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/include/linux/skbuff.h +++++ b/include/linux/skbuff.h ++@@ -2496,7 +2496,7 @@ static inline int pskb_network_may_pull( ++ * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) ++ */ ++ #ifndef NET_SKB_PAD ++-#define NET_SKB_PAD max(32, L1_CACHE_BYTES) +++#define NET_SKB_PAD max(64, L1_CACHE_BYTES) ++ #endif ++ ++ int ___pskb_trim(struct sk_buff *skb, unsigned int len); +diff --git a/target/linux/generic/pending-4.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-4.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +new file mode 100644 +index 0000000000..96c8ae9c12 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +@@ -0,0 +1,500 @@ ++From: Steven Barth ++Subject: Add support for MAP-E FMRs (mesh mode) ++ ++MAP-E FMRs (draft-ietf-softwire-map-10) are rules for IPv4-communication ++between MAP CEs (mesh mode) without the need to forward such data to a ++border relay. This is similar to how 6rd works but for IPv4 over IPv6. ++ ++Signed-off-by: Steven Barth ++--- ++ include/net/ip6_tunnel.h | 13 ++ ++ include/uapi/linux/if_tunnel.h | 13 ++ ++ net/ipv6/ip6_tunnel.c | 276 +++++++++++++++++++++++++++++++++++++++-- ++ 3 files changed, 291 insertions(+), 11 deletions(-) ++ ++--- a/include/net/ip6_tunnel.h +++++ b/include/net/ip6_tunnel.h ++@@ -18,6 +18,18 @@ ++ /* determine capability on a per-packet basis */ ++ #define IP6_TNL_F_CAP_PER_PACKET 0x40000 ++ +++/* IPv6 tunnel FMR */ +++struct __ip6_tnl_fmr { +++ struct __ip6_tnl_fmr *next; /* next fmr in list */ +++ struct in6_addr ip6_prefix; +++ struct in_addr ip4_prefix; +++ +++ __u8 ip6_prefix_len; +++ __u8 ip4_prefix_len; +++ __u8 ea_len; +++ __u8 offset; +++}; +++ ++ struct __ip6_tnl_parm { ++ char name[IFNAMSIZ]; /* name of tunnel device */ ++ int link; /* ifindex of underlying L2 interface */ ++@@ -29,6 +41,7 @@ struct __ip6_tnl_parm { ++ __u32 flags; /* tunnel flags */ ++ struct in6_addr laddr; /* local tunnel end-point address */ ++ struct in6_addr raddr; /* remote tunnel end-point address */ +++ struct __ip6_tnl_fmr *fmrs; /* FMRs */ ++ ++ __be16 i_flags; ++ __be16 o_flags; ++--- a/include/uapi/linux/if_tunnel.h +++++ b/include/uapi/linux/if_tunnel.h ++@@ -77,10 +77,23 @@ enum { ++ IFLA_IPTUN_ENCAP_DPORT, ++ IFLA_IPTUN_COLLECT_METADATA, ++ IFLA_IPTUN_FWMARK, +++ IFLA_IPTUN_FMRS, ++ __IFLA_IPTUN_MAX, ++ }; ++ #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) ++ +++enum { +++ IFLA_IPTUN_FMR_UNSPEC, +++ IFLA_IPTUN_FMR_IP6_PREFIX, +++ IFLA_IPTUN_FMR_IP4_PREFIX, +++ IFLA_IPTUN_FMR_IP6_PREFIX_LEN, +++ IFLA_IPTUN_FMR_IP4_PREFIX_LEN, +++ IFLA_IPTUN_FMR_EA_LEN, +++ IFLA_IPTUN_FMR_OFFSET, +++ __IFLA_IPTUN_FMR_MAX, +++}; +++#define IFLA_IPTUN_FMR_MAX (__IFLA_IPTUN_FMR_MAX - 1) +++ ++ enum tunnel_encap_types { ++ TUNNEL_ENCAP_NONE, ++ TUNNEL_ENCAP_FOU, ++--- a/net/ipv6/ip6_tunnel.c +++++ b/net/ipv6/ip6_tunnel.c ++@@ -16,6 +16,8 @@ ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * +++ * Changes: +++ * Steven Barth : MAP-E FMR support ++ */ ++ ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++@@ -72,9 +74,9 @@ static bool log_ecn_error = true; ++ module_param(log_ecn_error, bool, 0644); ++ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); ++ ++-static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2) +++static u32 HASH(const struct in6_addr *addr) ++ { ++- u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2); +++ u32 hash = ipv6_addr_hash(addr); ++ ++ return hash_32(hash, IP6_TUNNEL_HASH_SIZE_SHIFT); ++ } ++@@ -141,20 +143,29 @@ static struct net_device_stats *ip6_get_ ++ static struct ip6_tnl * ++ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_addr *local) ++ { ++- unsigned int hash = HASH(remote, local); +++ unsigned int hash = HASH(local); ++ struct ip6_tnl *t; ++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); ++ struct in6_addr any; +++ struct __ip6_tnl_fmr *fmr; ++ ++ for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { ++- if (ipv6_addr_equal(local, &t->parms.laddr) && ++- ipv6_addr_equal(remote, &t->parms.raddr) && ++- (t->dev->flags & IFF_UP)) +++ if (!ipv6_addr_equal(local, &t->parms.laddr) || +++ !(t->dev->flags & IFF_UP)) +++ continue; +++ +++ if (ipv6_addr_equal(remote, &t->parms.raddr)) ++ return t; +++ +++ for (fmr = t->parms.fmrs; fmr; fmr = fmr->next) { +++ if (ipv6_prefix_equal(remote, &fmr->ip6_prefix, +++ fmr->ip6_prefix_len)) +++ return t; +++ } ++ } ++ ++ memset(&any, 0, sizeof(any)); ++- hash = HASH(&any, local); +++ hash = HASH(local); ++ for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { ++ if (ipv6_addr_equal(local, &t->parms.laddr) && ++ ipv6_addr_any(&t->parms.raddr) && ++@@ -162,7 +173,7 @@ ip6_tnl_lookup(struct net *net, const st ++ return t; ++ } ++ ++- hash = HASH(remote, &any); +++ hash = HASH(&any); ++ for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { ++ if (ipv6_addr_equal(remote, &t->parms.raddr) && ++ ipv6_addr_any(&t->parms.laddr) && ++@@ -202,7 +213,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, ++ ++ if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) { ++ prio = 1; ++- h = HASH(remote, local); +++ h = HASH(local); ++ } ++ return &ip6n->tnls[prio][h]; ++ } ++@@ -383,6 +394,12 @@ ip6_tnl_dev_uninit(struct net_device *de ++ struct net *net = t->net; ++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); ++ +++ while (t->parms.fmrs) { +++ struct __ip6_tnl_fmr *next = t->parms.fmrs->next; +++ kfree(t->parms.fmrs); +++ t->parms.fmrs = next; +++ } +++ ++ if (dev == ip6n->fb_tnl_dev) ++ RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); ++ else ++@@ -779,6 +796,107 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t, ++ } ++ EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl); ++ +++/** +++ * ip4ip6_fmr_calc - calculate target / source IPv6-address based on FMR +++ * @dest: destination IPv6 address buffer +++ * @skb: received socket buffer +++ * @fmr: MAP FMR +++ * @xmit: Calculate for xmit or rcv +++ **/ +++static void ip4ip6_fmr_calc(struct in6_addr *dest, +++ const struct iphdr *iph, const uint8_t *end, +++ const struct __ip6_tnl_fmr *fmr, bool xmit) +++{ +++ int psidlen = fmr->ea_len - (32 - fmr->ip4_prefix_len); +++ u8 *portp = NULL; +++ bool use_dest_addr; +++ const struct iphdr *dsth = iph; +++ +++ if ((u8*)dsth >= end) +++ return; +++ +++ /* find significant IP header */ +++ if (iph->protocol == IPPROTO_ICMP) { +++ struct icmphdr *ih = (struct icmphdr*)(((u8*)dsth) + dsth->ihl * 4); +++ if (ih && ((u8*)&ih[1]) <= end && ( +++ ih->type == ICMP_DEST_UNREACH || +++ ih->type == ICMP_SOURCE_QUENCH || +++ ih->type == ICMP_TIME_EXCEEDED || +++ ih->type == ICMP_PARAMETERPROB || +++ ih->type == ICMP_REDIRECT)) +++ dsth = (const struct iphdr*)&ih[1]; +++ } +++ +++ /* in xmit-path use dest port by default and source port only if +++ this is an ICMP reply to something else; vice versa in rcv-path */ +++ use_dest_addr = (xmit && dsth == iph) || (!xmit && dsth != iph); +++ +++ /* get dst port */ +++ if (((u8*)&dsth[1]) <= end && ( +++ dsth->protocol == IPPROTO_UDP || +++ dsth->protocol == IPPROTO_TCP || +++ dsth->protocol == IPPROTO_SCTP || +++ dsth->protocol == IPPROTO_DCCP)) { +++ /* for UDP, TCP, SCTP and DCCP source and dest port +++ follow IPv4 header directly */ +++ portp = ((u8*)dsth) + dsth->ihl * 4; +++ +++ if (use_dest_addr) +++ portp += sizeof(u16); +++ } else if (iph->protocol == IPPROTO_ICMP) { +++ struct icmphdr *ih = (struct icmphdr*)(((u8*)dsth) + dsth->ihl * 4); +++ +++ /* use icmp identifier as port */ +++ if (((u8*)&ih) <= end && ( +++ (use_dest_addr && ( +++ ih->type == ICMP_ECHOREPLY || +++ ih->type == ICMP_TIMESTAMPREPLY || +++ ih->type == ICMP_INFO_REPLY || +++ ih->type == ICMP_ADDRESSREPLY)) || +++ (!use_dest_addr && ( +++ ih->type == ICMP_ECHO || +++ ih->type == ICMP_TIMESTAMP || +++ ih->type == ICMP_INFO_REQUEST || +++ ih->type == ICMP_ADDRESS) +++ ))) +++ portp = (u8*)&ih->un.echo.id; +++ } +++ +++ if ((portp && &portp[2] <= end) || psidlen == 0) { +++ int frombyte = fmr->ip6_prefix_len / 8; +++ int fromrem = fmr->ip6_prefix_len % 8; +++ int bytes = sizeof(struct in6_addr) - frombyte; +++ const u32 *addr = (use_dest_addr) ? &iph->daddr : &iph->saddr; +++ u64 eabits = ((u64)ntohl(*addr)) << (32 + fmr->ip4_prefix_len); +++ u64 t = 0; +++ +++ /* extract PSID from port and add it to eabits */ +++ u16 psidbits = 0; +++ if (psidlen > 0) { +++ psidbits = ((u16)portp[0]) << 8 | ((u16)portp[1]); +++ psidbits >>= 16 - psidlen - fmr->offset; +++ psidbits = (u16)(psidbits << (16 - psidlen)); +++ eabits |= ((u64)psidbits) << (48 - (fmr->ea_len - psidlen)); +++ } +++ +++ /* rewrite destination address */ +++ *dest = fmr->ip6_prefix; +++ memcpy(&dest->s6_addr[10], addr, sizeof(*addr)); +++ dest->s6_addr16[7] = htons(psidbits >> (16 - psidlen)); +++ +++ if (bytes > sizeof(u64)) +++ bytes = sizeof(u64); +++ +++ /* insert eabits */ +++ memcpy(&t, &dest->s6_addr[frombyte], bytes); +++ t = be64_to_cpu(t) & ~(((((u64)1) << fmr->ea_len) - 1) +++ << (64 - fmr->ea_len - fromrem)); +++ t = cpu_to_be64(t | (eabits >> fromrem)); +++ memcpy(&dest->s6_addr[frombyte], &t, bytes); +++ } +++} +++ +++ ++ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb, ++ const struct tnl_ptk_info *tpi, ++ struct metadata_dst *tun_dst, ++@@ -831,6 +949,27 @@ static int __ip6_tnl_rcv(struct ip6_tnl ++ skb_reset_network_header(skb); ++ memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); ++ +++ if (tpi->proto == htons(ETH_P_IP) && tunnel->parms.fmrs && +++ !ipv6_addr_equal(&ipv6h->saddr, &tunnel->parms.raddr)) { +++ /* Packet didn't come from BR, so lookup FMR */ +++ struct __ip6_tnl_fmr *fmr; +++ struct in6_addr expected = tunnel->parms.raddr; +++ for (fmr = tunnel->parms.fmrs; fmr; fmr = fmr->next) +++ if (ipv6_prefix_equal(&ipv6h->saddr, +++ &fmr->ip6_prefix, fmr->ip6_prefix_len)) +++ break; +++ +++ /* Check that IPv6 matches IPv4 source to prevent spoofing */ +++ if (fmr) +++ ip4ip6_fmr_calc(&expected, ip_hdr(skb), +++ skb_tail_pointer(skb), fmr, false); +++ +++ if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) { +++ rcu_read_unlock(); +++ goto drop; +++ } +++ } +++ ++ __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); ++ ++ err = dscp_ecn_decapsulate(tunnel, ipv6h, skb); ++@@ -963,6 +1102,7 @@ static void init_tel_txopt(struct ipv6_t ++ opt->ops.opt_nflen = 8; ++ } ++ +++ ++ /** ++ * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own ++ * @t: the outgoing tunnel device ++@@ -1305,6 +1445,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str ++ { ++ struct ip6_tnl *t = netdev_priv(dev); ++ struct ipv6hdr *ipv6h; +++ struct __ip6_tnl_fmr *fmr; ++ int encap_limit = -1; ++ __u16 offset; ++ struct flowi6 fl6; ++@@ -1372,6 +1513,18 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str ++ fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); ++ dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h)); ++ +++ /* try to find matching FMR */ +++ for (fmr = t->parms.fmrs; fmr; fmr = fmr->next) { +++ unsigned mshift = 32 - fmr->ip4_prefix_len; +++ if (ntohl(fmr->ip4_prefix.s_addr) >> mshift == +++ ntohl(ip_hdr(skb)->daddr) >> mshift) +++ break; +++ } +++ +++ /* change dstaddr according to FMR */ +++ if (fmr) +++ ip4ip6_fmr_calc(&fl6.daddr, ip_hdr(skb), skb_tail_pointer(skb), fmr, true); +++ ++ if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) ++ return -1; ++ ++@@ -1498,6 +1651,14 @@ ip6_tnl_change(struct ip6_tnl *t, const ++ t->parms.link = p->link; ++ t->parms.proto = p->proto; ++ t->parms.fwmark = p->fwmark; +++ +++ while (t->parms.fmrs) { +++ struct __ip6_tnl_fmr *next = t->parms.fmrs->next; +++ kfree(t->parms.fmrs); +++ t->parms.fmrs = next; +++ } +++ t->parms.fmrs = p->fmrs; +++ ++ dst_cache_reset(&t->dst_cache); ++ ip6_tnl_link_config(t); ++ return 0; ++@@ -1536,6 +1697,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ ++ p->flowinfo = u->flowinfo; ++ p->link = u->link; ++ p->proto = u->proto; +++ p->fmrs = NULL; ++ memcpy(p->name, u->name, sizeof(u->name)); ++ } ++ ++@@ -1920,6 +2082,15 @@ static int ip6_tnl_validate(struct nlatt ++ return 0; ++ } ++ +++static const struct nla_policy ip6_tnl_fmr_policy[IFLA_IPTUN_FMR_MAX + 1] = { +++ [IFLA_IPTUN_FMR_IP6_PREFIX] = { .len = sizeof(struct in6_addr) }, +++ [IFLA_IPTUN_FMR_IP4_PREFIX] = { .len = sizeof(struct in_addr) }, +++ [IFLA_IPTUN_FMR_IP6_PREFIX_LEN] = { .type = NLA_U8 }, +++ [IFLA_IPTUN_FMR_IP4_PREFIX_LEN] = { .type = NLA_U8 }, +++ [IFLA_IPTUN_FMR_EA_LEN] = { .type = NLA_U8 }, +++ [IFLA_IPTUN_FMR_OFFSET] = { .type = NLA_U8 } +++}; +++ ++ static void ip6_tnl_netlink_parms(struct nlattr *data[], ++ struct __ip6_tnl_parm *parms) ++ { ++@@ -1957,6 +2128,46 @@ static void ip6_tnl_netlink_parms(struct ++ ++ if (data[IFLA_IPTUN_FWMARK]) ++ parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); +++ +++ if (data[IFLA_IPTUN_FMRS]) { +++ unsigned rem; +++ struct nlattr *fmr; +++ nla_for_each_nested(fmr, data[IFLA_IPTUN_FMRS], rem) { +++ struct nlattr *fmrd[IFLA_IPTUN_FMR_MAX + 1], *c; +++ struct __ip6_tnl_fmr *nfmr; +++ +++ nla_parse_nested(fmrd, IFLA_IPTUN_FMR_MAX, +++ fmr, ip6_tnl_fmr_policy, NULL); +++ +++ if (!(nfmr = kzalloc(sizeof(*nfmr), GFP_KERNEL))) +++ continue; +++ +++ nfmr->offset = 6; +++ +++ if ((c = fmrd[IFLA_IPTUN_FMR_IP6_PREFIX])) +++ nla_memcpy(&nfmr->ip6_prefix, fmrd[IFLA_IPTUN_FMR_IP6_PREFIX], +++ sizeof(nfmr->ip6_prefix)); +++ +++ if ((c = fmrd[IFLA_IPTUN_FMR_IP4_PREFIX])) +++ nla_memcpy(&nfmr->ip4_prefix, fmrd[IFLA_IPTUN_FMR_IP4_PREFIX], +++ sizeof(nfmr->ip4_prefix)); +++ +++ if ((c = fmrd[IFLA_IPTUN_FMR_IP6_PREFIX_LEN])) +++ nfmr->ip6_prefix_len = nla_get_u8(c); +++ +++ if ((c = fmrd[IFLA_IPTUN_FMR_IP4_PREFIX_LEN])) +++ nfmr->ip4_prefix_len = nla_get_u8(c); +++ +++ if ((c = fmrd[IFLA_IPTUN_FMR_EA_LEN])) +++ nfmr->ea_len = nla_get_u8(c); +++ +++ if ((c = fmrd[IFLA_IPTUN_FMR_OFFSET])) +++ nfmr->offset = nla_get_u8(c); +++ +++ nfmr->next = parms->fmrs; +++ parms->fmrs = nfmr; +++ } +++ } ++ } ++ ++ static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[], ++@@ -2072,6 +2283,12 @@ static void ip6_tnl_dellink(struct net_d ++ ++ static size_t ip6_tnl_get_size(const struct net_device *dev) ++ { +++ const struct ip6_tnl *t = netdev_priv(dev); +++ struct __ip6_tnl_fmr *c; +++ int fmrs = 0; +++ for (c = t->parms.fmrs; c; c = c->next) +++ ++fmrs; +++ ++ return ++ /* IFLA_IPTUN_LINK */ ++ nla_total_size(4) + ++@@ -2101,6 +2318,24 @@ static size_t ip6_tnl_get_size(const str ++ nla_total_size(0) + ++ /* IFLA_IPTUN_FWMARK */ ++ nla_total_size(4) + +++ /* IFLA_IPTUN_FMRS */ +++ nla_total_size(0) + +++ ( +++ /* nest */ +++ nla_total_size(0) + +++ /* IFLA_IPTUN_FMR_IP6_PREFIX */ +++ nla_total_size(sizeof(struct in6_addr)) + +++ /* IFLA_IPTUN_FMR_IP4_PREFIX */ +++ nla_total_size(sizeof(struct in_addr)) + +++ /* IFLA_IPTUN_FMR_EA_LEN */ +++ nla_total_size(1) + +++ /* IFLA_IPTUN_FMR_IP6_PREFIX_LEN */ +++ nla_total_size(1) + +++ /* IFLA_IPTUN_FMR_IP4_PREFIX_LEN */ +++ nla_total_size(1) + +++ /* IFLA_IPTUN_FMR_OFFSET */ +++ nla_total_size(1) +++ ) * fmrs + ++ 0; ++ } ++ ++@@ -2108,6 +2343,9 @@ static int ip6_tnl_fill_info(struct sk_b ++ { ++ struct ip6_tnl *tunnel = netdev_priv(dev); ++ struct __ip6_tnl_parm *parm = &tunnel->parms; +++ struct __ip6_tnl_fmr *c; +++ int fmrcnt = 0; +++ struct nlattr *fmrs; ++ ++ if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || ++ nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || ++@@ -2117,9 +2355,27 @@ static int ip6_tnl_fill_info(struct sk_b ++ nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || ++ nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || ++ nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || ++- nla_put_u32(skb, IFLA_IPTUN_FWMARK, parm->fwmark)) +++ nla_put_u32(skb, IFLA_IPTUN_FWMARK, parm->fwmark) || +++ !(fmrs = nla_nest_start(skb, IFLA_IPTUN_FMRS))) ++ goto nla_put_failure; ++ +++ for (c = parm->fmrs; c; c = c->next) { +++ struct nlattr *fmr = nla_nest_start(skb, ++fmrcnt); +++ if (!fmr || +++ nla_put(skb, IFLA_IPTUN_FMR_IP6_PREFIX, +++ sizeof(c->ip6_prefix), &c->ip6_prefix) || +++ nla_put(skb, IFLA_IPTUN_FMR_IP4_PREFIX, +++ sizeof(c->ip4_prefix), &c->ip4_prefix) || +++ nla_put_u8(skb, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, c->ip6_prefix_len) || +++ nla_put_u8(skb, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, c->ip4_prefix_len) || +++ nla_put_u8(skb, IFLA_IPTUN_FMR_EA_LEN, c->ea_len) || +++ nla_put_u8(skb, IFLA_IPTUN_FMR_OFFSET, c->offset)) +++ goto nla_put_failure; +++ +++ nla_nest_end(skb, fmr); +++ } +++ nla_nest_end(skb, fmrs); +++ ++ if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || ++ nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || ++ nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || ++@@ -2159,6 +2415,7 @@ static const struct nla_policy ip6_tnl_p ++ [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, ++ [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, ++ [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, +++ [IFLA_IPTUN_FMRS] = { .type = NLA_NESTED }, ++ }; ++ ++ static struct rtnl_link_ops ip6_link_ops __read_mostly = { +diff --git a/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +new file mode 100644 +index 0000000000..3839865712 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +@@ -0,0 +1,255 @@ ++From: Jonas Gorski ++Subject: ipv6: allow rejecting with "source address failed policy" ++ ++RFC6204 L-14 requires rejecting traffic from invalid addresses with ++ICMPv6 Destination Unreachable, Code 5 (Source address failed ingress/ ++egress policy) on the LAN side, so add an appropriate rule for that. ++ ++Signed-off-by: Jonas Gorski ++--- ++ include/net/netns/ipv6.h | 1 + ++ include/uapi/linux/fib_rules.h | 4 +++ ++ include/uapi/linux/rtnetlink.h | 1 + ++ net/ipv4/fib_semantics.c | 4 +++ ++ net/ipv4/fib_trie.c | 1 + ++ net/ipv4/ipmr.c | 1 + ++ net/ipv6/fib6_rules.c | 4 +++ ++ net/ipv6/ip6mr.c | 2 ++ ++ net/ipv6/route.c | 58 +++++++++++++++++++++++++++++++++++++++++- ++ 9 files changed, 75 insertions(+), 1 deletion(-) ++ ++--- a/include/net/netns/ipv6.h +++++ b/include/net/netns/ipv6.h ++@@ -69,6 +69,7 @@ struct netns_ipv6 { ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++ bool fib6_has_custom_rules; ++ struct rt6_info *ip6_prohibit_entry; +++ struct rt6_info *ip6_policy_failed_entry; ++ struct rt6_info *ip6_blk_hole_entry; ++ struct fib6_table *fib6_local_tbl; ++ struct fib_rules_ops *fib6_rules_ops; ++--- a/include/uapi/linux/fib_rules.h +++++ b/include/uapi/linux/fib_rules.h ++@@ -73,6 +73,10 @@ enum { ++ FR_ACT_BLACKHOLE, /* Drop without notification */ ++ FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ ++ FR_ACT_PROHIBIT, /* Drop with EACCES */ +++ FR_ACT_RES9, +++ FR_ACT_RES10, +++ FR_ACT_RES11, +++ FR_ACT_POLICY_FAILED, /* Drop with EACCES */ ++ __FR_ACT_MAX, ++ }; ++ ++--- a/include/uapi/linux/rtnetlink.h +++++ b/include/uapi/linux/rtnetlink.h ++@@ -221,6 +221,7 @@ enum { ++ RTN_THROW, /* Not in this table */ ++ RTN_NAT, /* Translate this address */ ++ RTN_XRESOLVE, /* Use external resolver */ +++ RTN_POLICY_FAILED, /* Failed ingress/egress policy */ ++ __RTN_MAX ++ }; ++ ++--- a/net/ipv4/fib_semantics.c +++++ b/net/ipv4/fib_semantics.c ++@@ -139,6 +139,10 @@ const struct fib_prop fib_props[RTN_MAX ++ .error = -EINVAL, ++ .scope = RT_SCOPE_NOWHERE, ++ }, +++ [RTN_POLICY_FAILED] = { +++ .error = -EACCES, +++ .scope = RT_SCOPE_UNIVERSE, +++ }, ++ }; ++ ++ static void rt_fibinfo_free(struct rtable __rcu **rtp) ++--- a/net/ipv4/fib_trie.c +++++ b/net/ipv4/fib_trie.c ++@@ -2472,6 +2472,7 @@ static const char *const rtn_type_names[ ++ [RTN_THROW] = "THROW", ++ [RTN_NAT] = "NAT", ++ [RTN_XRESOLVE] = "XRESOLVE", +++ [RTN_POLICY_FAILED] = "POLICY_FAILED", ++ }; ++ ++ static inline const char *rtn_type(char *buf, size_t len, unsigned int t) ++--- a/net/ipv4/ipmr.c +++++ b/net/ipv4/ipmr.c ++@@ -163,6 +163,7 @@ static int ipmr_rule_action(struct fib_r ++ case FR_ACT_UNREACHABLE: ++ return -ENETUNREACH; ++ case FR_ACT_PROHIBIT: +++ case FR_ACT_POLICY_FAILED: ++ return -EACCES; ++ case FR_ACT_BLACKHOLE: ++ default: ++--- a/net/ipv6/fib6_rules.c +++++ b/net/ipv6/fib6_rules.c ++@@ -121,6 +121,10 @@ static int fib6_rule_action(struct fib_r ++ err = -EACCES; ++ rt = net->ipv6.ip6_prohibit_entry; ++ goto discard_pkt; +++ case FR_ACT_POLICY_FAILED: +++ err = -EACCES; +++ rt = net->ipv6.ip6_policy_failed_entry; +++ goto discard_pkt; ++ } ++ ++ tb_id = fib_rule_get_table(rule, arg); ++--- a/net/ipv6/ip6mr.c +++++ b/net/ipv6/ip6mr.c ++@@ -170,6 +170,8 @@ static int ip6mr_rule_action(struct fib_ ++ return -ENETUNREACH; ++ case FR_ACT_PROHIBIT: ++ return -EACCES; +++ case FR_ACT_POLICY_FAILED: +++ return -EACCES; ++ case FR_ACT_BLACKHOLE: ++ default: ++ return -EINVAL; ++--- a/net/ipv6/route.c +++++ b/net/ipv6/route.c ++@@ -91,6 +91,8 @@ static int ip6_pkt_discard(struct sk_bu ++ static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); ++ static int ip6_pkt_prohibit(struct sk_buff *skb); ++ static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb); +++static int ip6_pkt_policy_failed(struct sk_buff *skb); +++static int ip6_pkt_policy_failed_out(struct net *net, struct sock *sk, struct sk_buff *skb); ++ static void ip6_link_failure(struct sk_buff *skb); ++ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, ++ struct sk_buff *skb, u32 mtu, ++@@ -323,6 +325,21 @@ static const struct rt6_info ip6_prohibi ++ .rt6i_ref = ATOMIC_INIT(1), ++ }; ++ +++static const struct rt6_info ip6_policy_failed_entry_template = { +++ .dst = { +++ .__refcnt = ATOMIC_INIT(1), +++ .__use = 1, +++ .obsolete = DST_OBSOLETE_FORCE_CHK, +++ .error = -EACCES, +++ .input = ip6_pkt_policy_failed, +++ .output = ip6_pkt_policy_failed_out, +++ }, +++ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), +++ .rt6i_protocol = RTPROT_KERNEL, +++ .rt6i_metric = ~(u32) 0, +++ .rt6i_ref = ATOMIC_INIT(1), +++}; +++ ++ static const struct rt6_info ip6_blk_hole_entry_template = { ++ .dst = { ++ .__refcnt = ATOMIC_INIT(1), ++@@ -2056,6 +2073,11 @@ static struct rt6_info *ip6_route_info_c ++ rt->dst.output = ip6_pkt_prohibit_out; ++ rt->dst.input = ip6_pkt_prohibit; ++ break; +++ case RTN_POLICY_FAILED: +++ rt->dst.error = -EACCES; +++ rt->dst.output = ip6_pkt_policy_failed_out; +++ rt->dst.input = ip6_pkt_policy_failed; +++ break; ++ case RTN_THROW: ++ case RTN_UNREACHABLE: ++ default: ++@@ -2781,6 +2803,17 @@ static int ip6_pkt_prohibit_out(struct n ++ return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); ++ } ++ +++static int ip6_pkt_policy_failed(struct sk_buff *skb) +++{ +++ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_INNOROUTES); +++} +++ +++static int ip6_pkt_policy_failed_out(struct net *net, struct sock *sk, struct sk_buff *skb) +++{ +++ skb->dev = skb_dst(skb)->dev; +++ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_OUTNOROUTES); +++} +++ ++ /* ++ * Allocate a dst for local (unicast / anycast) address. ++ */ ++@@ -3017,7 +3050,8 @@ static int rtm_to_fib6_config(struct sk_ ++ if (rtm->rtm_type == RTN_UNREACHABLE || ++ rtm->rtm_type == RTN_BLACKHOLE || ++ rtm->rtm_type == RTN_PROHIBIT || ++- rtm->rtm_type == RTN_THROW) +++ rtm->rtm_type == RTN_THROW || +++ rtm->rtm_type == RTN_POLICY_FAILED) ++ cfg->fc_flags |= RTF_REJECT; ++ ++ if (rtm->rtm_type == RTN_LOCAL) ++@@ -3517,6 +3551,9 @@ static int rt6_fill_node(struct net *net ++ case -EACCES: ++ rtm->rtm_type = RTN_PROHIBIT; ++ break; +++ case -EPERM: +++ rtm->rtm_type = RTN_POLICY_FAILED; +++ break; ++ case -EAGAIN: ++ rtm->rtm_type = RTN_THROW; ++ break; ++@@ -3835,6 +3872,8 @@ static int ip6_route_dev_notify(struct n ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++ net->ipv6.ip6_prohibit_entry->dst.dev = dev; ++ net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); +++ net->ipv6.ip6_policy_failed_entry->dst.dev = dev; +++ net->ipv6.ip6_policy_failed_entry->rt6i_idev = in6_dev_get(dev); ++ net->ipv6.ip6_blk_hole_entry->dst.dev = dev; ++ net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); ++ #endif ++@@ -3846,6 +3885,7 @@ static int ip6_route_dev_notify(struct n ++ in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++ in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); +++ in6_dev_put_clear(&net->ipv6.ip6_policy_failed_entry->rt6i_idev); ++ in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); ++ #endif ++ } ++@@ -4062,6 +4102,17 @@ static int __net_init ip6_route_net_init ++ net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; ++ dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ++ ip6_template_metrics, true); +++ +++ net->ipv6.ip6_policy_failed_entry = +++ kmemdup(&ip6_policy_failed_entry_template, +++ sizeof(*net->ipv6.ip6_policy_failed_entry), GFP_KERNEL); +++ if (!net->ipv6.ip6_policy_failed_entry) +++ goto out_ip6_blk_hole_entry; +++ net->ipv6.ip6_policy_failed_entry->dst.path = +++ (struct dst_entry *)net->ipv6.ip6_policy_failed_entry; +++ net->ipv6.ip6_policy_failed_entry->dst.ops = &net->ipv6.ip6_dst_ops; +++ dst_init_metrics(&net->ipv6.ip6_policy_failed_entry->dst, +++ ip6_template_metrics, true); ++ #endif ++ ++ net->ipv6.sysctl.flush_delay = 0; ++@@ -4080,6 +4131,8 @@ out: ++ return ret; ++ ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES +++out_ip6_blk_hole_entry: +++ kfree(net->ipv6.ip6_blk_hole_entry); ++ out_ip6_prohibit_entry: ++ kfree(net->ipv6.ip6_prohibit_entry); ++ out_ip6_null_entry: ++@@ -4097,6 +4150,7 @@ static void __net_exit ip6_route_net_exi ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++ kfree(net->ipv6.ip6_prohibit_entry); ++ kfree(net->ipv6.ip6_blk_hole_entry); +++ kfree(net->ipv6.ip6_policy_failed_entry); ++ #endif ++ dst_entries_destroy(&net->ipv6.ip6_dst_ops); ++ } ++@@ -4170,6 +4224,9 @@ void __init ip6_route_init_special_entri ++ init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); ++ init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; ++ init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); +++ init_net.ipv6.ip6_policy_failed_entry->dst.dev = init_net.loopback_dev; +++ init_net.ipv6.ip6_policy_failed_entry->rt6i_idev = +++ in6_dev_get(init_net.loopback_dev); ++ #endif ++ } ++ +diff --git a/target/linux/generic/pending-4.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch b/target/linux/generic/pending-4.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch +new file mode 100644 +index 0000000000..cfea527e3d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch +@@ -0,0 +1,50 @@ ++From: Jonas Gorski ++Subject: net: provide defines for _POLICY_FAILED until all code is updated ++ ++Upstream introduced ICMPV6_POLICY_FAIL for code 5 of destination ++unreachable, conflicting with our name. ++ ++Add appropriate defines to allow our code to build with the new ++name until we have updated our local patches for older kernels ++and userspace packages. ++ ++Signed-off-by: Jonas Gorski ++--- ++ include/uapi/linux/fib_rules.h | 2 ++ ++ include/uapi/linux/icmpv6.h | 2 ++ ++ include/uapi/linux/rtnetlink.h | 2 ++ ++ 3 files changed, 6 insertions(+) ++ ++--- a/include/uapi/linux/fib_rules.h +++++ b/include/uapi/linux/fib_rules.h ++@@ -80,6 +80,8 @@ enum { ++ __FR_ACT_MAX, ++ }; ++ +++#define FR_ACT_FAILED_POLICY FR_ACT_POLICY_FAILED +++ ++ #define FR_ACT_MAX (__FR_ACT_MAX - 1) ++ ++ #endif ++--- a/include/uapi/linux/icmpv6.h +++++ b/include/uapi/linux/icmpv6.h ++@@ -119,6 +119,8 @@ struct icmp6hdr { ++ #define ICMPV6_POLICY_FAIL 5 ++ #define ICMPV6_REJECT_ROUTE 6 ++ +++#define ICMPV6_FAILED_POLICY ICMPV6_POLICY_FAIL +++ ++ /* ++ * Codes for Time Exceeded ++ */ ++--- a/include/uapi/linux/rtnetlink.h +++++ b/include/uapi/linux/rtnetlink.h ++@@ -225,6 +225,8 @@ enum { ++ __RTN_MAX ++ }; ++ +++#define RTN_FAILED_POLICY RTN_POLICY_FAILED +++ ++ #define RTN_MAX (__RTN_MAX - 1) ++ ++ +diff --git a/target/linux/generic/pending-4.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-4.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +new file mode 100644 +index 0000000000..cf0e50f2d9 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +@@ -0,0 +1,152 @@ ++From: Felix Fietkau ++Subject: net: replace GRO optimization patch with a new one that supports VLANs/bridges with different MAC addresses ++ ++Signed-off-by: Felix Fietkau ++--- ++ include/linux/netdevice.h | 2 ++ ++ include/linux/skbuff.h | 3 ++- ++ net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ ++ net/ethernet/eth.c | 18 +++++++++++++++++- ++ 4 files changed, 69 insertions(+), 2 deletions(-) ++ ++--- a/include/linux/netdevice.h +++++ b/include/linux/netdevice.h ++@@ -1771,6 +1771,8 @@ struct net_device { ++ struct netdev_hw_addr_list mc; ++ struct netdev_hw_addr_list dev_addrs; ++ +++ unsigned char local_addr_mask[MAX_ADDR_LEN]; +++ ++ #ifdef CONFIG_SYSFS ++ struct kset *queues_kset; ++ #endif ++--- a/include/linux/skbuff.h +++++ b/include/linux/skbuff.h ++@@ -782,6 +782,7 @@ struct sk_buff { ++ __u8 tc_redirected:1; ++ __u8 tc_from_ingress:1; ++ #endif +++ __u8 gro_skip:1; ++ ++ #ifdef CONFIG_NET_SCHED ++ __u16 tc_index; /* traffic control index */ ++--- a/net/core/dev.c +++++ b/net/core/dev.c ++@@ -4802,6 +4802,9 @@ static enum gro_result dev_gro_receive(s ++ enum gro_result ret; ++ int grow; ++ +++ if (skb->gro_skip) +++ goto normal; +++ ++ if (netif_elide_gro(skb->dev)) ++ goto normal; ++ ++@@ -6279,6 +6282,48 @@ static void __netdev_adjacent_dev_unlink ++ &upper_dev->adj_list.lower); ++ } ++ +++static void __netdev_addr_mask(unsigned char *mask, const unsigned char *addr, +++ struct net_device *dev) +++{ +++ int i; +++ +++ for (i = 0; i < dev->addr_len; i++) +++ mask[i] |= addr[i] ^ dev->dev_addr[i]; +++} +++ +++static void __netdev_upper_mask(unsigned char *mask, struct net_device *dev, +++ struct net_device *lower) +++{ +++ struct net_device *cur; +++ struct list_head *iter; +++ +++ netdev_for_each_upper_dev_rcu(dev, cur, iter) { +++ __netdev_addr_mask(mask, cur->dev_addr, lower); +++ __netdev_upper_mask(mask, cur, lower); +++ } +++} +++ +++static void __netdev_update_addr_mask(struct net_device *dev) +++{ +++ unsigned char mask[MAX_ADDR_LEN]; +++ struct net_device *cur; +++ struct list_head *iter; +++ +++ memset(mask, 0, sizeof(mask)); +++ __netdev_upper_mask(mask, dev, dev); +++ memcpy(dev->local_addr_mask, mask, dev->addr_len); +++ +++ netdev_for_each_lower_dev(dev, cur, iter) +++ __netdev_update_addr_mask(cur); +++} +++ +++static void netdev_update_addr_mask(struct net_device *dev) +++{ +++ rcu_read_lock(); +++ __netdev_update_addr_mask(dev); +++ rcu_read_unlock(); +++} +++ ++ static int __netdev_upper_dev_link(struct net_device *dev, ++ struct net_device *upper_dev, bool master, ++ void *upper_priv, void *upper_info) ++@@ -6317,6 +6362,7 @@ static int __netdev_upper_dev_link(struc ++ if (ret) ++ return ret; ++ +++ netdev_update_addr_mask(dev); ++ ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, ++ &changeupper_info.info); ++ ret = notifier_to_errno(ret); ++@@ -6394,6 +6440,7 @@ void netdev_upper_dev_unlink(struct net_ ++ ++ __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); ++ +++ netdev_update_addr_mask(dev); ++ call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, ++ &changeupper_info.info); ++ } ++@@ -6958,6 +7005,7 @@ int dev_set_mac_address(struct net_devic ++ if (err) ++ return err; ++ dev->addr_assign_type = NET_ADDR_SET; +++ netdev_update_addr_mask(dev); ++ call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); ++ add_device_randomness(dev->dev_addr, dev->addr_len); ++ return 0; ++--- a/net/ethernet/eth.c +++++ b/net/ethernet/eth.c ++@@ -144,6 +144,18 @@ u32 eth_get_headlen(void *data, unsigned ++ } ++ EXPORT_SYMBOL(eth_get_headlen); ++ +++static inline bool +++eth_check_local_mask(const void *addr1, const void *addr2, const void *mask) +++{ +++ const u16 *a1 = addr1; +++ const u16 *a2 = addr2; +++ const u16 *m = mask; +++ +++ return (((a1[0] ^ a2[0]) & ~m[0]) | +++ ((a1[1] ^ a2[1]) & ~m[1]) | +++ ((a1[2] ^ a2[2]) & ~m[2])); +++} +++ ++ /** ++ * eth_type_trans - determine the packet's protocol ID. ++ * @skb: received socket data ++@@ -172,8 +184,12 @@ __be16 eth_type_trans(struct sk_buff *sk ++ skb->pkt_type = PACKET_MULTICAST; ++ } ++ else if (unlikely(!ether_addr_equal_64bits(eth->h_dest, ++- dev->dev_addr))) +++ dev->dev_addr))) { ++ skb->pkt_type = PACKET_OTHERHOST; +++ if (eth_check_local_mask(eth->h_dest, dev->dev_addr, +++ dev->local_addr_mask)) +++ skb->gro_skip = 1; +++ } ++ ++ /* ++ * Some variants of DSA tagging don't have an ethertype field +diff --git a/target/linux/generic/pending-4.14/681-NET-add-of_get_mac_address_mtd.patch b/target/linux/generic/pending-4.14/681-NET-add-of_get_mac_address_mtd.patch +new file mode 100644 +index 0000000000..2b89a05238 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/681-NET-add-of_get_mac_address_mtd.patch +@@ -0,0 +1,133 @@ ++From: John Crispin ++Subject: NET: add mtd-mac-address support to of_get_mac_address() ++ ++Many embedded devices have information such as mac addresses stored inside mtd ++devices. This patch allows us to add a property inside a node describing a ++network interface. The new property points at a mtd partition with an offset ++where the mac address can be found. ++ ++Signed-off-by: John Crispin ++Signed-off-by: Felix Fietkau ++--- ++ drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++++++++ ++ include/linux/of_net.h | 1 + ++ 2 files changed, 38 insertions(+) ++ ++--- a/drivers/of/of_net.c +++++ b/drivers/of/of_net.c ++@@ -10,6 +10,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ /** ++ * of_get_phy_mode - Get phy mode for given device_node ++@@ -38,7 +39,7 @@ int of_get_phy_mode(struct device_node * ++ } ++ EXPORT_SYMBOL_GPL(of_get_phy_mode); ++ ++-static const void *of_get_mac_addr(struct device_node *np, const char *name) +++static void *of_get_mac_addr(struct device_node *np, const char *name) ++ { ++ struct property *pp = of_find_property(np, name, NULL); ++ ++@@ -47,6 +48,79 @@ static const void *of_get_mac_addr(struc ++ return NULL; ++ } ++ +++static const void *of_get_mac_address_mtd(struct device_node *np) +++{ +++#ifdef CONFIG_MTD +++ struct device_node *mtd_np = NULL; +++ struct property *prop; +++ size_t retlen; +++ int size, ret; +++ struct mtd_info *mtd; +++ const char *part; +++ const __be32 *list; +++ phandle phandle; +++ u32 mac_inc = 0; +++ u8 mac[ETH_ALEN]; +++ void *addr; +++ u32 inc_idx; +++ +++ list = of_get_property(np, "mtd-mac-address", &size); +++ if (!list || (size != (2 * sizeof(*list)))) +++ return NULL; +++ +++ phandle = be32_to_cpup(list++); +++ if (phandle) +++ mtd_np = of_find_node_by_phandle(phandle); +++ +++ if (!mtd_np) +++ return NULL; +++ +++ 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 NULL; +++ +++ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac); +++ put_mtd_device(mtd); +++ +++ if (of_property_read_u32(np, "mtd-mac-address-increment-byte", &inc_idx)) +++ inc_idx = 5; +++ if (inc_idx > 5) +++ return NULL; +++ +++ if (!of_property_read_u32(np, "mtd-mac-address-increment", &mac_inc)) +++ mac[inc_idx] += mac_inc; +++ +++ if (!is_valid_ether_addr(mac)) +++ return NULL; +++ +++ addr = of_get_mac_addr(np, "mac-address"); +++ if (addr) { +++ memcpy(addr, mac, ETH_ALEN); +++ return addr; +++ } +++ +++ prop = kzalloc(sizeof(*prop), GFP_KERNEL); +++ if (!prop) +++ return NULL; +++ +++ prop->name = "mac-address"; +++ prop->length = ETH_ALEN; +++ prop->value = kmemdup(mac, ETH_ALEN, GFP_KERNEL); +++ if (!prop->value || of_add_property(np, prop)) +++ goto free; +++ +++ return prop->value; +++free: +++ kfree(prop->value); +++ kfree(prop); +++#endif +++ return NULL; +++} +++ ++ /** ++ * Search the device tree for the best MAC address to use. 'mac-address' is ++ * checked first, because that is supposed to contain to "most recent" MAC ++@@ -64,11 +138,18 @@ static const void *of_get_mac_addr(struc ++ * addresses. Some older U-Boots only initialized 'local-mac-address'. In ++ * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists ++ * but is all zeros. +++ * +++ * If a mtd-mac-address property exists, try to fetch the MAC address from the +++ * specified mtd device, and store it as a 'mac-address' property ++ */ ++ const void *of_get_mac_address(struct device_node *np) ++ { ++ const void *addr; ++ +++ addr = of_get_mac_address_mtd(np); +++ if (addr) +++ return addr; +++ ++ addr = of_get_mac_addr(np, "mac-address"); ++ if (addr) ++ return addr; +diff --git a/target/linux/generic/pending-4.14/690-net-add-support-for-threaded-NAPI-polling.patch b/target/linux/generic/pending-4.14/690-net-add-support-for-threaded-NAPI-polling.patch +new file mode 100644 +index 0000000000..1a531cb8fc +--- /dev/null ++++ b/target/linux/generic/pending-4.14/690-net-add-support-for-threaded-NAPI-polling.patch +@@ -0,0 +1,339 @@ ++From: Felix Fietkau ++Date: Sun, 26 Jul 2020 14:03:21 +0200 ++Subject: [PATCH] net: add support for threaded NAPI polling ++ ++For some drivers (especially 802.11 drivers), doing a lot of work in the NAPI ++poll function does not perform well. Since NAPI poll is bound to the CPU it ++was scheduled from, we can easily end up with a few very busy CPUs spending ++most of their time in softirq/ksoftirqd and some idle ones. ++ ++Introduce threaded NAPI for such drivers based on a workqueue. The API is the ++same except for using netif_threaded_napi_add instead of netif_napi_add. ++ ++In my tests with mt76 on MT7621 using threaded NAPI + a thread for tx scheduling ++improves LAN->WLAN bridging throughput by 10-50%. Throughput without threaded ++NAPI is wildly inconsistent, depending on the CPU that runs the tx scheduling ++thread. ++ ++With threaded NAPI it seems stable and consistent (and higher than the best ++results I got without it). ++ ++Based on a patch by Hillf Danton ++ ++Cc: Hillf Danton ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/linux/netdevice.h +++++ b/include/linux/netdevice.h ++@@ -326,6 +326,7 @@ struct napi_struct { ++ struct list_head dev_list; ++ struct hlist_node napi_hash_node; ++ unsigned int napi_id; +++ struct work_struct work; ++ }; ++ ++ enum { ++@@ -336,6 +337,7 @@ enum { ++ NAPI_STATE_HASHED, /* In NAPI hash (busy polling possible) */ ++ NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ ++ NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ +++ NAPI_STATE_THREADED, /* Use threaded NAPI */ ++ }; ++ ++ enum { ++@@ -346,6 +348,7 @@ enum { ++ NAPIF_STATE_HASHED = BIT(NAPI_STATE_HASHED), ++ NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), ++ NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), +++ NAPIF_STATE_THREADED = BIT(NAPI_STATE_THREADED), ++ }; ++ ++ enum gro_result { ++@@ -2093,6 +2096,26 @@ void netif_napi_add(struct net_device *d ++ int (*poll)(struct napi_struct *, int), int weight); ++ ++ /** +++ * netif_threaded_napi_add - initialize a NAPI context +++ * @dev: network device +++ * @napi: NAPI context +++ * @poll: polling function +++ * @weight: default weight +++ * +++ * This variant of netif_napi_add() should be used from drivers using NAPI +++ * with CPU intensive poll functions. +++ * This will schedule polling from a high priority workqueue +++ */ +++static inline void netif_threaded_napi_add(struct net_device *dev, +++ struct napi_struct *napi, +++ int (*poll)(struct napi_struct *, int), +++ int weight) +++{ +++ set_bit(NAPI_STATE_THREADED, &napi->state); +++ netif_napi_add(dev, napi, poll, weight); +++} +++ +++/** ++ * netif_tx_napi_add - initialize a NAPI context ++ * @dev: network device ++ * @napi: NAPI context ++--- a/net/core/dev.c +++++ b/net/core/dev.c ++@@ -160,6 +160,7 @@ static DEFINE_SPINLOCK(offload_lock); ++ struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; ++ struct list_head ptype_all __read_mostly; /* Taps */ ++ static struct list_head offload_base __read_mostly; +++static struct workqueue_struct *napi_workq __read_mostly; ++ ++ static int netif_rx_internal(struct sk_buff *skb); ++ static int call_netdevice_notifiers_info(unsigned long val, ++@@ -5237,6 +5238,11 @@ void __napi_schedule(struct napi_struct ++ { ++ unsigned long flags; ++ +++ if (test_bit(NAPI_STATE_THREADED, &n->state)) { +++ queue_work(napi_workq, &n->work); +++ return; +++ } +++ ++ local_irq_save(flags); ++ ____napi_schedule(this_cpu_ptr(&softnet_data), n); ++ local_irq_restore(flags); ++@@ -5284,6 +5290,11 @@ EXPORT_SYMBOL(napi_schedule_prep); ++ */ ++ void __napi_schedule_irqoff(struct napi_struct *n) ++ { +++ if (test_bit(NAPI_STATE_THREADED, &n->state)) { +++ queue_work(napi_workq, &n->work); +++ return; +++ } +++ ++ ____napi_schedule(this_cpu_ptr(&softnet_data), n); ++ } ++ EXPORT_SYMBOL(__napi_schedule_irqoff); ++@@ -5521,6 +5532,82 @@ static enum hrtimer_restart napi_watchdo ++ return HRTIMER_NORESTART; ++ } ++ +++static int __napi_poll(struct napi_struct *n, bool *repoll) +++{ +++ int work, weight; +++ +++ weight = n->weight; +++ +++ /* This NAPI_STATE_SCHED test is for avoiding a race +++ * with netpoll's poll_napi(). Only the entity which +++ * obtains the lock and sees NAPI_STATE_SCHED set will +++ * actually make the ->poll() call. Therefore we avoid +++ * accidentally calling ->poll() when NAPI is not scheduled. +++ */ +++ work = 0; +++ if (test_bit(NAPI_STATE_SCHED, &n->state)) { +++ work = n->poll(n, weight); +++ trace_napi_poll(n, work, weight); +++ } +++ +++ WARN_ON_ONCE(work > weight); +++ +++ if (likely(work < weight)) +++ return work; +++ +++ /* Drivers must not modify the NAPI state if they +++ * consume the entire weight. In such cases this code +++ * still "owns" the NAPI instance and therefore can +++ * move the instance around on the list at-will. +++ */ +++ if (unlikely(napi_disable_pending(n))) { +++ napi_complete(n); +++ return work; +++ } +++ +++ if (n->gro_list) { +++ /* flush too old packets +++ * If HZ < 1000, flush all packets. +++ */ +++ napi_gro_flush(n, HZ >= 1000); +++ } +++ +++ *repoll = true; +++ +++ return work; +++} +++ +++static void napi_workfn(struct work_struct *work) +++{ +++ struct napi_struct *n = container_of(work, struct napi_struct, work); +++ void *have; +++ +++ for (;;) { +++ bool repoll = false; +++ +++ local_bh_disable(); +++ +++ have = netpoll_poll_lock(n); +++ __napi_poll(n, &repoll); +++ netpoll_poll_unlock(have); +++ +++ local_bh_enable(); +++ +++ if (!repoll) +++ return; +++ +++ if (!need_resched()) +++ continue; +++ +++ /* +++ * have to pay for the latency of task switch even if +++ * napi is scheduled +++ */ +++ queue_work(napi_workq, work); +++ return; +++ } +++} +++ ++ void netif_napi_add(struct net_device *dev, struct napi_struct *napi, ++ int (*poll)(struct napi_struct *, int), int weight) ++ { ++@@ -5540,6 +5627,7 @@ void netif_napi_add(struct net_device *d ++ #ifdef CONFIG_NETPOLL ++ napi->poll_owner = -1; ++ #endif +++ INIT_WORK(&napi->work, napi_workfn); ++ set_bit(NAPI_STATE_SCHED, &napi->state); ++ napi_hash_add(napi); ++ } ++@@ -5565,6 +5653,7 @@ EXPORT_SYMBOL(napi_disable); ++ void netif_napi_del(struct napi_struct *napi) ++ { ++ might_sleep(); +++ cancel_work_sync(&napi->work); ++ if (napi_hash_del(napi)) ++ synchronize_net(); ++ list_del_init(&napi->dev_list); ++@@ -5578,48 +5667,18 @@ EXPORT_SYMBOL(netif_napi_del); ++ ++ static int napi_poll(struct napi_struct *n, struct list_head *repoll) ++ { +++ bool do_repoll = false; ++ void *have; ++- int work, weight; +++ int work; ++ ++ list_del_init(&n->poll_list); ++ ++ have = netpoll_poll_lock(n); ++ ++- weight = n->weight; ++- ++- /* This NAPI_STATE_SCHED test is for avoiding a race ++- * with netpoll's poll_napi(). Only the entity which ++- * obtains the lock and sees NAPI_STATE_SCHED set will ++- * actually make the ->poll() call. Therefore we avoid ++- * accidentally calling ->poll() when NAPI is not scheduled. ++- */ ++- work = 0; ++- if (test_bit(NAPI_STATE_SCHED, &n->state)) { ++- work = n->poll(n, weight); ++- trace_napi_poll(n, work, weight); ++- } ++- ++- WARN_ON_ONCE(work > weight); ++- ++- if (likely(work < weight)) ++- goto out_unlock; +++ work = __napi_poll(n, &do_repoll); ++ ++- /* Drivers must not modify the NAPI state if they ++- * consume the entire weight. In such cases this code ++- * still "owns" the NAPI instance and therefore can ++- * move the instance around on the list at-will. ++- */ ++- if (unlikely(napi_disable_pending(n))) { ++- napi_complete(n); +++ if (!do_repoll) ++ goto out_unlock; ++- } ++- ++- if (n->gro_list) { ++- /* flush too old packets ++- * If HZ < 1000, flush all packets. ++- */ ++- napi_gro_flush(n, HZ >= 1000); ++- } ++ ++ /* Some drivers may have called napi_schedule ++ * prior to exhausting their budget. ++@@ -8855,6 +8914,10 @@ static int __init net_dev_init(void) ++ sd->backlog.weight = weight_p; ++ } ++ +++ napi_workq = alloc_workqueue("napi_workq", WQ_UNBOUND | WQ_HIGHPRI, +++ WQ_UNBOUND_MAX_ACTIVE | WQ_SYSFS); +++ BUG_ON(!napi_workq); +++ ++ dev_boot_phase = 0; ++ ++ /* The loopback device is special if any other network devices ++--- a/net/core/net-sysfs.c +++++ b/net/core/net-sysfs.c ++@@ -441,6 +441,52 @@ static ssize_t proto_down_store(struct d ++ } ++ NETDEVICE_SHOW_RW(proto_down, fmt_dec); ++ +++static int change_napi_threaded(struct net_device *dev, unsigned long val) +++{ +++ struct napi_struct *napi; +++ +++ if (list_empty(&dev->napi_list)) +++ return -EOPNOTSUPP; +++ +++ list_for_each_entry(napi, &dev->napi_list, dev_list) { +++ if (val) +++ set_bit(NAPI_STATE_THREADED, &napi->state); +++ else +++ clear_bit(NAPI_STATE_THREADED, &napi->state); +++ } +++ +++ return 0; +++} +++ +++static ssize_t napi_threaded_store(struct device *dev, +++ struct device_attribute *attr, +++ const char *buf, size_t len) +++{ +++ return netdev_store(dev, attr, buf, len, change_napi_threaded); +++} +++ +++static ssize_t napi_threaded_show(struct device *dev, +++ struct device_attribute *attr, +++ char *buf) +++{ +++ struct net_device *netdev = to_net_dev(dev); +++ struct napi_struct *napi; +++ bool enabled = false; +++ +++ if (!rtnl_trylock()) +++ return restart_syscall(); +++ +++ list_for_each_entry(napi, &netdev->napi_list, dev_list) { +++ if (test_bit(NAPI_STATE_THREADED, &napi->state)) +++ enabled = true; +++ } +++ +++ rtnl_unlock(); +++ +++ return sprintf(buf, fmt_dec, enabled); +++} +++static DEVICE_ATTR_RW(napi_threaded); +++ ++ static ssize_t phys_port_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++ { ++@@ -536,6 +582,7 @@ static struct attribute *net_class_attrs ++ &dev_attr_flags.attr, ++ &dev_attr_tx_queue_len.attr, ++ &dev_attr_gro_flush_timeout.attr, +++ &dev_attr_napi_threaded.attr, ++ &dev_attr_phys_port_id.attr, ++ &dev_attr_phys_port_name.attr, ++ &dev_attr_phys_switch_id.attr, +diff --git a/target/linux/generic/pending-4.14/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-4.14/703-phy-add-detach-callback-to-struct-phy_driver.patch +new file mode 100644 +index 0000000000..03579657ee +--- /dev/null ++++ b/target/linux/generic/pending-4.14/703-phy-add-detach-callback-to-struct-phy_driver.patch +@@ -0,0 +1,38 @@ ++From: Gabor Juhos ++Subject: generic: add detach callback to struct phy_driver ++ ++lede-commit: fe61fc2d7d0b3fb348b502f68f98243b3ddf5867 ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/phy/phy_device.c | 3 +++ ++ include/linux/phy.h | 6 ++++++ ++ 2 files changed, 9 insertions(+) ++ ++--- a/drivers/net/phy/phy_device.c +++++ b/drivers/net/phy/phy_device.c ++@@ -1110,6 +1110,9 @@ void phy_detach(struct phy_device *phyde ++ struct module *ndev_owner = dev->dev.parent->driver->owner; ++ struct mii_bus *bus; ++ +++ if (phydev->drv && phydev->drv->detach) +++ phydev->drv->detach(phydev); +++ ++ if (phydev->sysfs_links) { ++ sysfs_remove_link(&dev->dev.kobj, "phydev"); ++ sysfs_remove_link(&phydev->mdio.dev.kobj, "attached_dev"); ++--- a/include/linux/phy.h +++++ b/include/linux/phy.h ++@@ -561,6 +561,12 @@ struct phy_driver { ++ */ ++ int (*did_interrupt)(struct phy_device *phydev); ++ +++ /* +++ * Called before an ethernet device is detached +++ * from the PHY. +++ */ +++ void (*detach)(struct phy_device *phydev); +++ ++ /* Clears up any memory if needed */ ++ void (*remove)(struct phy_device *phydev); ++ +diff --git a/target/linux/generic/pending-4.14/734-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/generic/pending-4.14/734-net-phy-at803x-allow-to-configure-via-pdata.patch +new file mode 100644 +index 0000000000..27bbf572e9 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/734-net-phy-at803x-allow-to-configure-via-pdata.patch +@@ -0,0 +1,142 @@ ++From: Gabor Juhos ++Subject: net: phy: allow to configure AR803x PHYs via platform data ++ ++Add a patch for the at803x phy driver, in order to be able ++to configure some register settings via platform data. ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/net/phy/at803x.c | 56 ++++++++++++++++++++++++++++++++ ++ include/linux/platform_data/phy-at803x.h | 11 +++++++ ++ 2 files changed, 67 insertions(+) ++ create mode 100644 include/linux/platform_data/phy-at803x.h ++ ++--- a/drivers/net/phy/at803x.c +++++ b/drivers/net/phy/at803x.c ++@@ -12,12 +12,14 @@ ++ */ ++ ++ #include +++#include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include +++#include ++ ++ #define AT803X_INTR_ENABLE 0x12 ++ #define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) ++@@ -45,6 +47,11 @@ ++ #define AT803X_REG_CHIP_CONFIG 0x1f ++ #define AT803X_BT_BX_REG_SEL 0x8000 ++ +++#define AT803X_PCS_SMART_EEE_CTRL3 0x805D +++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK 0x3 +++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT 12 +++#define AT803X_SMART_EEE_CTRL3_LPI_EN BIT(8) +++ ++ #define AT803X_DEBUG_ADDR 0x1D ++ #define AT803X_DEBUG_DATA 0x1E ++ ++@@ -74,6 +81,7 @@ MODULE_LICENSE("GPL"); ++ struct at803x_priv { ++ bool phy_reset:1; ++ struct gpio_desc *gpiod_reset; +++ int prev_speed; ++ }; ++ ++ struct at803x_context { ++@@ -274,8 +282,16 @@ does_not_require_reset_workaround: ++ return 0; ++ } ++ +++static void at803x_disable_smarteee(struct phy_device *phydev) +++{ +++ phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3, +++ 1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT); +++ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); +++} +++ ++ static int at803x_config_init(struct phy_device *phydev) ++ { +++ struct at803x_platform_data *pdata; ++ int ret; ++ ++ ret = genphy_config_init(phydev); ++@@ -296,6 +312,26 @@ static int at803x_config_init(struct phy ++ return ret; ++ } ++ +++ pdata = dev_get_platdata(&phydev->mdio.dev); +++ if (pdata) { +++ if (pdata->disable_smarteee) +++ at803x_disable_smarteee(phydev); +++ +++ if (pdata->enable_rgmii_rx_delay) +++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0, +++ AT803X_DEBUG_RX_CLK_DLY_EN); +++ else +++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, +++ AT803X_DEBUG_RX_CLK_DLY_EN, 0); +++ +++ if (pdata->enable_rgmii_tx_delay) +++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0, +++ AT803X_DEBUG_TX_CLK_DLY_EN); +++ else +++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, +++ AT803X_DEBUG_TX_CLK_DLY_EN, 0); +++ } +++ ++ return 0; ++ } ++ ++@@ -333,6 +369,8 @@ static int at803x_config_intr(struct phy ++ static void at803x_link_change_notify(struct phy_device *phydev) ++ { ++ struct at803x_priv *priv = phydev->priv; +++ struct at803x_platform_data *pdata; +++ pdata = dev_get_platdata(&phydev->mdio.dev); ++ ++ /* ++ * Conduct a hardware reset for AT8030/2 every time a link loss is ++@@ -361,6 +399,24 @@ static void at803x_link_change_notify(st ++ } else { ++ priv->phy_reset = false; ++ } +++ if (pdata && pdata->fixup_rgmii_tx_delay && +++ phydev->speed != priv->prev_speed) { +++ switch (phydev->speed) { +++ case SPEED_10: +++ case SPEED_100: +++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0, +++ AT803X_DEBUG_TX_CLK_DLY_EN); +++ break; +++ case SPEED_1000: +++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, +++ AT803X_DEBUG_TX_CLK_DLY_EN, 0); +++ break; +++ default: +++ break; +++ } +++ +++ priv->prev_speed = phydev->speed; +++ } ++ } ++ ++ static int at803x_aneg_done(struct phy_device *phydev) ++--- /dev/null +++++ b/include/linux/platform_data/phy-at803x.h ++@@ -0,0 +1,11 @@ +++#ifndef _PHY_AT803X_PDATA_H +++#define _PHY_AT803X_PDATA_H +++ +++struct at803x_platform_data { +++ int disable_smarteee:1; +++ int enable_rgmii_tx_delay:1; +++ int enable_rgmii_rx_delay:1; +++ int fixup_rgmii_tx_delay:1; +++}; +++ +++#endif /* _PHY_AT803X_PDATA_H */ +diff --git a/target/linux/generic/pending-4.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/target/linux/generic/pending-4.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch +new file mode 100644 +index 0000000000..8c5c21b1bc +--- /dev/null ++++ b/target/linux/generic/pending-4.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch +@@ -0,0 +1,51 @@ ++From: Roman Yeryomin ++Subject: kernel: add at803x fix for sgmii mode ++ ++Some (possibly broken) bootloaders incorreclty initialize at8033 ++phy. This patch enables sgmii autonegotiation mode. ++ ++[john@phrozen.org: felix added this to his upstream queue] ++ ++Signed-off-by: Roman Yeryomin ++--- ++ drivers/net/phy/at803x.c | 25 +++++++++++++++++++++++++ ++ 1 file changed, 25 insertions(+) ++ ++--- a/drivers/net/phy/at803x.c +++++ b/drivers/net/phy/at803x.c ++@@ -46,6 +46,7 @@ ++ #define AT803X_FUNC_DATA 0x4003 ++ #define AT803X_REG_CHIP_CONFIG 0x1f ++ #define AT803X_BT_BX_REG_SEL 0x8000 +++#define AT803X_SGMII_ANEG_EN 0x1000 ++ ++ #define AT803X_PCS_SMART_EEE_CTRL3 0x805D ++ #define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK 0x3 ++@@ -293,6 +294,27 @@ static int at803x_config_init(struct phy ++ { ++ struct at803x_platform_data *pdata; ++ int ret; +++ u32 v; +++ +++ if (phydev->drv->phy_id == ATH8031_PHY_ID && +++ phydev->interface == PHY_INTERFACE_MODE_SGMII) +++ { +++ v = phy_read(phydev, AT803X_REG_CHIP_CONFIG); +++ /* select SGMII/fiber page */ +++ ret = phy_write(phydev, AT803X_REG_CHIP_CONFIG, +++ v & ~AT803X_BT_BX_REG_SEL); +++ if (ret) +++ return ret; +++ /* enable SGMII autonegotiation */ +++ ret = phy_write(phydev, MII_BMCR, AT803X_SGMII_ANEG_EN); +++ if (ret) +++ return ret; +++ /* select copper page */ +++ ret = phy_write(phydev, AT803X_REG_CHIP_CONFIG, +++ v | AT803X_BT_BX_REG_SEL); +++ if (ret) +++ return ret; +++ } ++ ++ ret = genphy_config_init(phydev); ++ if (ret < 0) +diff --git a/target/linux/generic/pending-4.14/810-pci_disable_common_quirks.patch b/target/linux/generic/pending-4.14/810-pci_disable_common_quirks.patch +new file mode 100644 +index 0000000000..1d10af647f +--- /dev/null ++++ b/target/linux/generic/pending-4.14/810-pci_disable_common_quirks.patch +@@ -0,0 +1,60 @@ ++From: Gabor Juhos ++Subject: debloat: add kernel config option to disabling common PCI quirks ++ ++Signed-off-by: Gabor Juhos ++--- ++ drivers/pci/Kconfig | 6 ++++++ ++ drivers/pci/quirks.c | 6 ++++++ ++ 2 files changed, 12 insertions(+) ++ ++--- a/drivers/pci/Kconfig +++++ b/drivers/pci/Kconfig ++@@ -71,6 +71,12 @@ config XEN_PCIDEV_FRONTEND ++ The PCI device frontend driver allows the kernel to import arbitrary ++ PCI devices from a PCI backend to support PCI driver domains. ++ +++config PCI_DISABLE_COMMON_QUIRKS +++ bool "PCI disable common quirks" +++ depends on PCI +++ help +++ If you don't know what to do here, say N. +++ ++ config HT_IRQ ++ bool "Interrupts on hypertransport devices" ++ default y ++--- a/drivers/pci/quirks.c +++++ b/drivers/pci/quirks.c ++@@ -44,6 +44,7 @@ static void quirk_mmio_always_on(struct ++ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on); ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ /* The Mellanox Tavor device gives false positive parity errors ++ * Mark this device with a broken_parity_status, to allow ++ * PCI scanning code to "skip" this now blacklisted device. ++@@ -3108,6 +3109,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I ++ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); ++ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); ++ +++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ ++ /* ++ * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. To ++@@ -3164,6 +3166,8 @@ static void fixup_debug_report(struct pc ++ } ++ } ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS +++ ++ /* ++ * Some BIOS implementations leave the Intel GPU interrupts enabled, ++ * even though no one is handling them (f.e. i915 driver is never loaded). ++@@ -3202,6 +3206,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN ++ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); ++ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); ++ +++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ +++ ++ /* ++ * PCI devices which are on Intel chips can skip the 10ms delay ++ * before entering D3 mode. +diff --git a/target/linux/generic/pending-4.14/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-4.14/811-pci_disable_usb_common_quirks.patch +new file mode 100644 +index 0000000000..aeb13c5ef7 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/811-pci_disable_usb_common_quirks.patch +@@ -0,0 +1,115 @@ ++From: Felix Fietkau ++Subject: debloat: disable common USB quirks ++ ++Signed-off-by: Felix Fietkau ++--- ++ drivers/usb/host/pci-quirks.c | 16 ++++++++++++++++ ++ drivers/usb/host/pci-quirks.h | 18 +++++++++++++++++- ++ include/linux/usb/hcd.h | 7 +++++++ ++ 3 files changed, 40 insertions(+), 1 deletion(-) ++ ++--- a/drivers/usb/host/pci-quirks.c +++++ b/drivers/usb/host/pci-quirks.c ++@@ -124,6 +124,8 @@ struct amd_chipset_type { ++ u8 rev; ++ }; ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS +++ ++ static struct amd_chipset_info { ++ struct pci_dev *nb_dev; ++ struct pci_dev *smbus_dev; ++@@ -627,6 +629,10 @@ bool usb_amd_pt_check_port(struct device ++ } ++ EXPORT_SYMBOL_GPL(usb_amd_pt_check_port); ++ +++#endif /* CONFIG_PCI_DISABLE_COMMON_QUIRKS */ +++ +++#if IS_ENABLED(CONFIG_USB_UHCI_HCD) +++ ++ /* ++ * Make sure the controller is completely inactive, unable to ++ * generate interrupts or do DMA. ++@@ -706,8 +712,17 @@ reset_needed: ++ uhci_reset_hc(pdev, base); ++ return 1; ++ } +++#else +++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) +++{ +++ return 0; +++} +++ +++#endif ++ EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS +++ ++ static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) ++ { ++ u16 cmd; ++@@ -1294,3 +1309,4 @@ bool usb_xhci_needs_pci_reset(struct pci ++ return false; ++ } ++ EXPORT_SYMBOL_GPL(usb_xhci_needs_pci_reset); +++#endif ++--- a/drivers/usb/host/pci-quirks.h +++++ b/drivers/usb/host/pci-quirks.h ++@@ -5,6 +5,9 @@ ++ #ifdef CONFIG_USB_PCI ++ void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); ++ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); +++#endif /* CONFIG_USB_PCI */ +++ +++#if defined(CONFIG_USB_PCI) && !defined(CONFIG_PCI_DISABLE_COMMON_QUIRKS) ++ int usb_amd_find_chipset_info(void); ++ int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev); ++ bool usb_amd_hang_symptom_quirk(void); ++@@ -20,6 +23,18 @@ bool usb_xhci_needs_pci_reset(struct pci ++ bool usb_amd_pt_check_port(struct device *device, int port); ++ #else ++ struct pci_dev; +++static inline int usb_amd_find_chipset_info(void) +++{ +++ return 0; +++} +++static inline bool usb_amd_hang_symptom_quirk(void) +++{ +++ return false; +++} +++static inline bool usb_amd_prefetch_quirk(void) +++{ +++ return false; +++} ++ static inline void usb_amd_quirk_pll_disable(void) {} ++ static inline void usb_amd_quirk_pll_enable(void) {} ++ static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {} ++@@ -30,6 +45,11 @@ static inline bool usb_amd_pt_check_port ++ { ++ return false; ++ } +++static inline void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) {} +++static inline bool usb_xhci_needs_pci_reset(struct pci_dev *pdev) +++{ +++ return false; +++} ++ #endif /* CONFIG_USB_PCI */ ++ ++ #endif /* __LINUX_USB_PCI_QUIRKS_H */ ++--- a/include/linux/usb/hcd.h +++++ b/include/linux/usb/hcd.h ++@@ -465,7 +465,14 @@ extern int usb_hcd_pci_probe(struct pci_ ++ extern void usb_hcd_pci_remove(struct pci_dev *dev); ++ extern void usb_hcd_pci_shutdown(struct pci_dev *dev); ++ +++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev); +++#else +++static inline int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev) +++{ +++ return 0; +++} +++#endif ++ ++ #ifdef CONFIG_PM ++ extern const struct dev_pm_ops usb_hcd_pci_pm_ops; +diff --git a/target/linux/generic/pending-4.14/834-ledtrig-libata.patch b/target/linux/generic/pending-4.14/834-ledtrig-libata.patch +new file mode 100644 +index 0000000000..8a15efdc0e +--- /dev/null ++++ b/target/linux/generic/pending-4.14/834-ledtrig-libata.patch +@@ -0,0 +1,149 @@ ++From: Daniel Golle ++Subject: libata: add ledtrig support ++ ++This adds a LED trigger for each ATA port indicating disk activity. ++ ++As this is needed only on specific platforms (NAS SoCs and such), ++these platforms should define ARCH_WANTS_LIBATA_LEDS if there ++are boards with LED(s) intended to indicate ATA disk activity and ++need the OS to take care of that. ++In that way, if not selected, LED trigger support not will be ++included in libata-core and both, codepaths and structures remain ++untouched. ++ ++Signed-off-by: Daniel Golle ++--- ++ drivers/ata/Kconfig | 16 ++++++++++++++++ ++ drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++ ++ include/linux/libata.h | 9 +++++++++ ++ 3 files changed, 66 insertions(+) ++ ++--- a/drivers/ata/Kconfig +++++ b/drivers/ata/Kconfig ++@@ -46,6 +46,22 @@ config ATA_VERBOSE_ERROR ++ ++ If unsure, say Y. ++ +++config ARCH_WANT_LIBATA_LEDS +++ bool +++ +++config ATA_LEDS +++ bool "support ATA port LED triggers" +++ depends on ARCH_WANT_LIBATA_LEDS +++ select NEW_LEDS +++ select LEDS_CLASS +++ select LEDS_TRIGGERS +++ default y +++ help +++ This option adds a LED trigger for each registered ATA port. +++ It is used to drive disk activity leds connected via GPIO. +++ +++ If unsure, say N. +++ ++ config ATA_ACPI ++ bool "ATA ACPI Support" ++ depends on ACPI ++--- a/drivers/ata/libata-core.c +++++ b/drivers/ata/libata-core.c ++@@ -730,6 +730,19 @@ u64 ata_tf_read_block(const struct ata_t ++ return block; ++ } ++ +++#ifdef CONFIG_ATA_LEDS +++#define LIBATA_BLINK_DELAY 20 /* ms */ +++static inline void ata_led_act(struct ata_port *ap) +++{ +++ unsigned long led_delay = LIBATA_BLINK_DELAY; +++ +++ if (unlikely(!ap->ledtrig)) +++ return; +++ +++ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0); +++} +++#endif +++ ++ /** ++ * ata_build_rw_tf - Build ATA taskfile for given read/write request ++ * @tf: Target ATA taskfile ++@@ -5123,6 +5136,9 @@ struct ata_queued_cmd *ata_qc_new_init(s ++ if (tag < 0) ++ return NULL; ++ } +++#ifdef CONFIG_ATA_LEDS +++ ata_led_act(ap); +++#endif ++ ++ qc = __ata_qc_from_tag(ap, tag); ++ qc->tag = tag; ++@@ -6024,6 +6040,9 @@ struct ata_port *ata_port_alloc(struct a ++ ap->stats.unhandled_irq = 1; ++ ap->stats.idle_irq = 1; ++ #endif +++#ifdef CONFIG_ATA_LEDS +++ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); +++#endif ++ ata_sff_port_init(ap); ++ ++ return ap; ++@@ -6045,6 +6064,12 @@ static void ata_host_release(struct devi ++ ++ kfree(ap->pmp_link); ++ kfree(ap->slave_link); +++#ifdef CONFIG_ATA_LEDS +++ if (ap->ledtrig) { +++ led_trigger_unregister(ap->ledtrig); +++ kfree(ap->ledtrig); +++ }; +++#endif ++ kfree(ap); ++ host->ports[i] = NULL; ++ } ++@@ -6491,7 +6516,23 @@ int ata_host_register(struct ata_host *h ++ host->ports[i]->print_id = atomic_inc_return(&ata_print_id); ++ host->ports[i]->local_port_no = i + 1; ++ } +++#ifdef CONFIG_ATA_LEDS +++ for (i = 0; i < host->n_ports; i++) { +++ if (unlikely(!host->ports[i]->ledtrig)) +++ continue; ++ +++ snprintf(host->ports[i]->ledtrig_name, +++ sizeof(host->ports[i]->ledtrig_name), "ata%u", +++ host->ports[i]->print_id); +++ +++ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name; +++ +++ if (led_trigger_register(host->ports[i]->ledtrig)) { +++ kfree(host->ports[i]->ledtrig); +++ host->ports[i]->ledtrig = NULL; +++ } +++ } +++#endif ++ /* Create associated sysfs transport objects */ ++ for (i = 0; i < host->n_ports; i++) { ++ rc = ata_tport_add(host->dev,host->ports[i]); ++--- a/include/linux/libata.h +++++ b/include/linux/libata.h ++@@ -39,6 +39,9 @@ ++ #include ++ #include ++ #include +++#ifdef CONFIG_ATA_LEDS +++#include +++#endif ++ ++ /* ++ * Define if arch has non-standard setup. This is a _PCI_ standard ++@@ -893,6 +896,12 @@ struct ata_port { ++ #ifdef CONFIG_ATA_ACPI ++ struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ ++ #endif +++ +++#ifdef CONFIG_ATA_LEDS +++ struct led_trigger *ledtrig; +++ char ledtrig_name[8]; +++#endif +++ ++ /* owned by EH */ ++ u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; ++ }; +diff --git a/target/linux/generic/pending-4.14/920-mangle_bootargs.patch b/target/linux/generic/pending-4.14/920-mangle_bootargs.patch +new file mode 100644 +index 0000000000..2f6a52c23d +--- /dev/null ++++ b/target/linux/generic/pending-4.14/920-mangle_bootargs.patch +@@ -0,0 +1,71 @@ ++From: Imre Kaloz ++Subject: init: add CONFIG_MANGLE_BOOTARGS and disable it by default ++ ++Enabling this option renames the bootloader supplied root= ++and rootfstype= variables, which might have to be know but ++would break the automatisms OpenWrt uses. ++ ++Signed-off-by: Imre Kaloz ++--- ++ init/Kconfig | 9 +++++++++ ++ init/main.c | 24 ++++++++++++++++++++++++ ++ 2 files changed, 33 insertions(+) ++ ++--- a/init/Kconfig +++++ b/init/Kconfig ++@@ -1427,6 +1427,15 @@ config EMBEDDED ++ an embedded system so certain expert options are available ++ for configuration. ++ +++config MANGLE_BOOTARGS +++ bool "Rename offending bootargs" +++ depends on EXPERT +++ help +++ Sometimes the bootloader passed bogus root= and rootfstype= +++ parameters to the kernel, and while you want to ignore them, +++ you need to know the values f.e. to support dual firmware +++ layouts on the flash. +++ ++ config HAVE_PERF_EVENTS ++ bool ++ help ++--- a/init/main.c +++++ b/init/main.c ++@@ -358,6 +358,29 @@ static inline void setup_nr_cpu_ids(void ++ static inline void smp_prepare_cpus(unsigned int maxcpus) { } ++ #endif ++ +++#ifdef CONFIG_MANGLE_BOOTARGS +++static void __init mangle_bootargs(char *command_line) +++{ +++ char *rootdev; +++ char *rootfs; +++ +++ rootdev = strstr(command_line, "root=/dev/mtdblock"); +++ +++ if (rootdev) +++ strncpy(rootdev, "mangled_rootblock=", 18); +++ +++ rootfs = strstr(command_line, "rootfstype"); +++ +++ if (rootfs) +++ strncpy(rootfs, "mangled_fs", 10); +++ +++} +++#else +++static void __init mangle_bootargs(char *command_line) +++{ +++} +++#endif +++ ++ /* ++ * We need to store the untouched command line for future reference. ++ * We also need to store the touched command line since the parameter ++@@ -539,6 +562,7 @@ asmlinkage __visible void __init start_k ++ add_device_randomness(command_line, strlen(command_line)); ++ boot_init_stack_canary(); ++ mm_init_cpumask(&init_mm); +++ mangle_bootargs(command_line); ++ setup_command_line(command_line); ++ setup_nr_cpu_ids(); ++ setup_per_cpu_areas(); +diff --git a/tools/Makefile b/tools/Makefile +index a2665dbc9a..0b8727205e 100644 +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -30,7 +30,7 @@ tools-$(BUILD_B43_TOOLS) += b43-tools + tools-$(BUILD_ISL) += isl + tools-$(BUILD_TOOLCHAIN) += expat gmp libelf mpc mpfr + tools-$(CONFIG_TARGET_apm821xx)$(CONFIG_TARGET_gemini) += genext2fs +-tools-$(CONFIG_TARGET_ath79) += lzma-old squashfs ++tools-$(CONFIG_TARGET_ath79)tools-$(CONFIG_TARGET_ar71xx) += lzma-old squashfs + tools-$(CONFIG_TARGET_mxs) += elftosb sdimage + tools-$(CONFIG_TARGET_tegra) += cbootimage cbootimage-configs + tools-$(CONFIG_USES_MINOR) += kernel2minor +-- +2.25.1 + diff --git a/feeds/ucentral/ucentral-wifi/Makefile b/feeds/ucentral/ucentral-wifi/Makefile index 1c6615705..8a57444ce 100644 --- a/feeds/ucentral/ucentral-wifi/Makefile +++ b/feeds/ucentral/ucentral-wifi/Makefile @@ -6,7 +6,7 @@ PKG_RELEASE:=1 PKG_SOURCE_URL=https://github.com/blogic/ucentral-wifi.git PKG_SOURCE_PROTO:=git PKG_SOURCE_DATE:=2021-04-13 -PKG_SOURCE_VERSION:=b5a5fee87f23333a922f7d515f4da21daaf9b7ea +PKG_SOURCE_VERSION:=a601cf055673eb27a1e8dd499528e3e1921e0306 PKG_MAINTAINER:=John Crispin PKG_LICENSE:=BSD-3-Clause diff --git a/feeds/ucentral/ucentralgw/Makefile b/feeds/ucentral/ucentralgw/Makefile index f1f01112e..f422b428f 100644 --- a/feeds/ucentral/ucentralgw/Makefile +++ b/feeds/ucentral/ucentralgw/Makefile @@ -6,7 +6,7 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=git@github.com:Telecominfraproject/wlan-cloud-ucentralgw.git PKG_SOURCE_DATE:=2021-03-28 -PKG_SOURCE_VERSION:=6ed4167f1a2cd0bc0b4ebd34d488fcae4ac9e47 +PKG_SOURCE_VERSION:=8711011f932351dc1dc5a6d9adba9774b94503b7 CMAKE_INSTALL:=1 PKG_LICENSE:=BSD-3-Clause diff --git a/profiles/mikrotik_rb91x.yml b/profiles/mikrotik_rb91x.yml new file mode 100644 index 000000000..9de8b42c0 --- /dev/null +++ b/profiles/mikrotik_rb91x.yml @@ -0,0 +1,7 @@ +--- +profile: nand-large +target: ar71xx +subtarget: mikrotik +description: Build image for the Mikrotik RouterBoards +include: + - ucentral-ap-light diff --git a/profiles/ucentral-ap-light.yml b/profiles/ucentral-ap-light.yml index ad0e10fb5..cc2d011ff 100644 --- a/profiles/ucentral-ap-light.yml +++ b/profiles/ucentral-ap-light.yml @@ -17,7 +17,7 @@ packages: - ucentral-tools - ucode - usteer - - wpad-openssl + - wpad-mesh-openssl diffconfig: | CONFIG_OPENSSL_ENGINE=y CONFIG_OPENSSL_PREFER_CHACHA_OVER_GCM=y diff --git a/profiles/ucentral-ap.yml b/profiles/ucentral-ap.yml index e4f94396c..5d574f052 100644 --- a/profiles/ucentral-ap.yml +++ b/profiles/ucentral-ap.yml @@ -13,16 +13,16 @@ packages: - cJSON - curl - dnsmasq-full + - gre - igmpproxy - ip-bridge - - libmosquitto-ssl - lldpd - - gre - - tmate - opennds + - radsecproxy - ratelimit - rtty-openssl - tcpdump + - tmate - ucentral-client - ucentral-jsonschema - ucentral-schema