From d3ce52d090b7fcf1248a76dfa26e709dc94b9868 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Thu, 12 Oct 2017 16:12:47 +0800 Subject: [PATCH 01/15] ar71xx: update kernel from 4.4 to 4.9.54 --- target/linux/ar71xx/Makefile | 2 +- .../ar71xx/base-files/etc/board.d/02_network | 3 +- target/linux/ar71xx/config-4.4 | 2 +- target/linux/ar71xx/config-4.9 | 485 ++++++++++ .../arch/mips/ath79/mach-archer-c25-v1.c | 2 +- .../arch/mips/ath79/mach-archer-c59-v1.c | 2 +- .../files/arch/mips/ath79/mach-archer-c7.c | 2 +- .../ar71xx/files/arch/mips/ath79/mach-c60.c | 56 ++ .../files/arch/mips/ath79/mach-ew-dorin.c | 16 +- .../files/arch/mips/ath79/mach-mynet-n750.c | 2 +- .../files/arch/mips/ath79/mach-rb2011.c | 60 +- .../ar71xx/files/arch/mips/ath79/mach-rb91x.c | 2 +- .../ar71xx/files/arch/mips/ath79/mach-rb922.c | 58 ++ .../ar71xx/files/arch/mips/ath79/mach-rb95x.c | 56 ++ .../ar71xx/files/arch/mips/ath79/mach-rbspi.c | 2 +- .../files/arch/mips/ath79/mach-rbsxtlite.c | 58 ++ .../files/arch/mips/ath79/mach-tl-wdr4300.c | 2 +- .../arch/mips/ath79/mach-tl-wr1043nd-v4.c | 2 +- .../files/arch/mips/ath79/mach-tl-wr942n-v1.c | 2 +- .../files/drivers/gpio/gpio-nxp-74hc153.c | 4 + .../ar71xx/files/drivers/leds/leds-nu801.c | 8 +- .../ar71xx/files/drivers/mtd/cybertan_part.c | 5 + .../files/drivers/mtd/nand/ar934x_nfc.c | 99 +- .../files/drivers/mtd/nand/rb4xx_nand.c | 56 ++ .../files/drivers/mtd/nand/rb750_nand.c | 56 ++ .../files/drivers/mtd/nand/rb91x_nand.c | 56 ++ .../ar71xx/files/drivers/mtd/tplinkpart.c | 13 + .../ar71xx/files/drivers/net/dsa/mv88e6063.c | 104 +- .../net/ethernet/atheros/ag71xx/ag71xx_main.c | 6 +- .../net/ethernet/atheros/ag71xx/ag71xx_mdio.c | 4 + .../net/ethernet/atheros/ag71xx/ag71xx_phy.c | 28 +- .../ar71xx/files/drivers/spi/spi-rb4xx-cpld.c | 5 + target/linux/ar71xx/generic/config-default | 1 - target/linux/ar71xx/image/generic.mk | 20 + target/linux/ar71xx/image/legacy-devices.mk | 18 - target/linux/ar71xx/image/legacy.mk | 5 - target/linux/ar71xx/image/tp-link.mk | 3 +- target/linux/ar71xx/mikrotik/config-default | 3 +- target/linux/ar71xx/nand/config-default | 3 +- .../902-at803x-add-reset-gpio-pdata.patch | 4 +- ...usb-chipidea-AR933x-platform-support.patch | 57 +- .../ar71xx/patches-4.9/001-spi-cs-gpio.patch | 20 + .../002-add_back_gpio_function_select.patch | 92 ++ .../004-register_gpio_driver_earlier.patch | 15 + ...Avoid-using-unitialized-reg-variable.patch | 42 + ...egister-address-in-ath79_ddr_wb_flus.patch | 23 + ...pport-multiple-internal-chip-select-.patch | 70 ++ ...e-gpio_set_value_cansleep-for-GPIO-c.patch | 19 + ...ix-AR724X_PLL_REG_PCIE_CONFIG-offset.patch | 29 + ...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 + .../203-MIPS-ath79-fix-restart.patch | 20 + .../220-add_cpu_feature_overrides.patch | 28 + ...0-MIPS-add-MIPS_MACHINE_NONAME-macro.patch | 21 + .../310-lib-add-rle-decompression.patch | 124 +++ .../401-mtd-physmap-add-lock-unlock.patch | 94 ++ .../402-mtd-SST39VF6401B-support.patch | 29 + ...mtd_fix_cfi_cmdset_0002_status_check.patch | 69 ++ .../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 | 24 + .../430-drivers-link-spi-before-mtd.patch | 12 + .../432-spi-rb4xx-spi-driver.patch | 25 + .../433-spi-rb4xx-cpld-driver.patch | 26 + .../patches-4.9/435-spi-vsc7385_driver.patch | 24 + .../440-leds-wndr3700-usb-led-driver.patch | 26 + .../441-leds-rb750-led-driver.patch | 23 + ...50-gpio-nxp-74hc153-gpio-chip-driver.patch | 25 + ...x164-improve-platform-device-support.patch | 117 +++ .../452-gpio-add-gpio-latch-driver.patch | 22 + .../461-spi-ath79-add-fast-flash-read.patch | 54 ++ ...ath79-swizzle-pci-address-for-ar71xx.patch | 111 +++ ...490-usb-ehci-add-quirks-for-qca-socs.patch | 103 ++ .../patches-4.9/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 +++ .../605-MIPS-ath79-db120-fixes.patch | 204 ++++ .../606-MIPS-ath79-pb44-fixes.patch | 146 +++ .../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 | 705 ++++++++++++++ ...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 | 30 + ...d-gpio-func-register-for-QCA955x-SoC.patch | 38 + ...0-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch | 44 + .../818-MIPS-ath79-add-nu801-led-driver.patch | 26 + ...-MIPS-ath79-add_gpio_function2_setup.patch | 67 ++ .../900-mdio_bitbang_ignore_ta_value.patch | 32 + ...-prevent-rescheduling-during-command.patch | 61 ++ .../902-at803x-add-reset-gpio-pdata.patch | 68 ++ .../910-unaligned_access_hacks.patch | 888 ++++++++++++++++++ ...usb-chipidea-AR933x-platform-support.patch | 123 +++ .../patches-4.9/930-chipidea-pullup.patch | 72 ++ 128 files changed, 8420 insertions(+), 149 deletions(-) create mode 100644 target/linux/ar71xx/config-4.9 create mode 100644 target/linux/ar71xx/patches-4.9/001-spi-cs-gpio.patch create mode 100644 target/linux/ar71xx/patches-4.9/002-add_back_gpio_function_select.patch create mode 100644 target/linux/ar71xx/patches-4.9/004-register_gpio_driver_earlier.patch create mode 100644 target/linux/ar71xx/patches-4.9/100-MIPS-ath79-Avoid-using-unitialized-reg-variable.patch create mode 100644 target/linux/ar71xx/patches-4.9/103-MIPS-ath79-fix-register-address-in-ath79_ddr_wb_flus.patch create mode 100644 target/linux/ar71xx/patches-4.9/104-spi-spi-ath79-support-multiple-internal-chip-select-.patch create mode 100644 target/linux/ar71xx/patches-4.9/105-spi-spi-ath79-use-gpio_set_value_cansleep-for-GPIO-c.patch create mode 100644 target/linux/ar71xx/patches-4.9/106-01-MIPS-ath79-fix-AR724X_PLL_REG_PCIE_CONFIG-offset.patch create mode 100644 target/linux/ar71xx/patches-4.9/106-02-MIPS-ath79-do-AR724x-PCIe-root-complex-init.patch create mode 100644 target/linux/ar71xx/patches-4.9/200-MIPS-ath79-fix-ar933x-wmac-reset.patch create mode 100644 target/linux/ar71xx/patches-4.9/201-ar913x_wmac_external_reset.patch create mode 100644 target/linux/ar71xx/patches-4.9/202-MIPS-ath79-ar934x-wmac-revision.patch create mode 100644 target/linux/ar71xx/patches-4.9/203-MIPS-ath79-fix-restart.patch create mode 100644 target/linux/ar71xx/patches-4.9/220-add_cpu_feature_overrides.patch create mode 100644 target/linux/ar71xx/patches-4.9/300-MIPS-add-MIPS_MACHINE_NONAME-macro.patch create mode 100644 target/linux/ar71xx/patches-4.9/310-lib-add-rle-decompression.patch create mode 100644 target/linux/ar71xx/patches-4.9/401-mtd-physmap-add-lock-unlock.patch create mode 100644 target/linux/ar71xx/patches-4.9/402-mtd-SST39VF6401B-support.patch create mode 100644 target/linux/ar71xx/patches-4.9/403-mtd_fix_cfi_cmdset_0002_status_check.patch create mode 100644 target/linux/ar71xx/patches-4.9/404-mtd-cybertan-trx-parser.patch create mode 100644 target/linux/ar71xx/patches-4.9/405-mtd-tp-link-partition-parser.patch create mode 100644 target/linux/ar71xx/patches-4.9/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch create mode 100644 target/linux/ar71xx/patches-4.9/408-mtd-redboot_partition_scan.patch create mode 100644 target/linux/ar71xx/patches-4.9/409-mtd-rb4xx_nand_driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/410-mtd-rb750-nand-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/411-mtd-cfi_cmdset_0002-force-word-write.patch create mode 100644 target/linux/ar71xx/patches-4.9/413-mtd-ar934x-nand-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/414-mtd-rb91x-nand-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/420-net-ar71xx_mac_driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/423-dsa-add-88e6063-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/430-drivers-link-spi-before-mtd.patch create mode 100644 target/linux/ar71xx/patches-4.9/432-spi-rb4xx-spi-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/433-spi-rb4xx-cpld-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/435-spi-vsc7385_driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/440-leds-wndr3700-usb-led-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/441-leds-rb750-led-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/450-gpio-nxp-74hc153-gpio-chip-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/451-gpio-74x164-improve-platform-device-support.patch create mode 100644 target/linux/ar71xx/patches-4.9/452-gpio-add-gpio-latch-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/461-spi-ath79-add-fast-flash-read.patch create mode 100644 target/linux/ar71xx/patches-4.9/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch create mode 100644 target/linux/ar71xx/patches-4.9/490-usb-ehci-add-quirks-for-qca-socs.patch create mode 100644 target/linux/ar71xx/patches-4.9/500-MIPS-fw-myloader.patch create mode 100644 target/linux/ar71xx/patches-4.9/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch create mode 100644 target/linux/ar71xx/patches-4.9/504-MIPS-ath79-add-ath79_device_reset_get.patch create mode 100644 target/linux/ar71xx/patches-4.9/505-MIPS-ath79-add-ath79_gpio_function_select.patch create mode 100644 target/linux/ar71xx/patches-4.9/506-MIPS-ath79-prom-parse-redboot-args.patch create mode 100644 target/linux/ar71xx/patches-4.9/507-MIPS-ath79-prom-add-myloader-support.patch create mode 100644 target/linux/ar71xx/patches-4.9/508-MIPS-ath79-prom-image-command-line-hack.patch create mode 100644 target/linux/ar71xx/patches-4.9/509-MIPS-ath79-process-board-kernel-option.patch create mode 100644 target/linux/ar71xx/patches-4.9/510-MIPS-ath79-init-gpio-pin-of-wmac-device.patch create mode 100644 target/linux/ar71xx/patches-4.9/520-MIPS-ath79-enable-UART-function.patch create mode 100644 target/linux/ar71xx/patches-4.9/521-MIPS-ath79-enable-UART-for-early_serial.patch create mode 100644 target/linux/ar71xx/patches-4.9/522-MIPS-ath79-add-ath79_wmac_register_simple-helper.patch create mode 100644 target/linux/ar71xx/patches-4.9/523-MIPS-ath79-OTP-support.patch create mode 100644 target/linux/ar71xx/patches-4.9/524-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch create mode 100644 target/linux/ar71xx/patches-4.9/525-MIPS-ath79-enable-qca-usb-quirks.patch create mode 100644 target/linux/ar71xx/patches-4.9/601-MIPS-ath79-add-more-register-defines.patch create mode 100644 target/linux/ar71xx/patches-4.9/602-MIPS-ath79-add-openwrt-stuff.patch create mode 100644 target/linux/ar71xx/patches-4.9/603-MIPS-ath79-ap121-fixes.patch create mode 100644 target/linux/ar71xx/patches-4.9/605-MIPS-ath79-db120-fixes.patch create mode 100644 target/linux/ar71xx/patches-4.9/606-MIPS-ath79-pb44-fixes.patch create mode 100644 target/linux/ar71xx/patches-4.9/607-MIPS-ath79-ubnt-xm-fixes.patch create mode 100644 target/linux/ar71xx/patches-4.9/608-MIPS-ath79-ubnt-xm-add-more-boards.patch create mode 100644 target/linux/ar71xx/patches-4.9/609-MIPS-ath79-ap136-fixes.patch create mode 100644 target/linux/ar71xx/patches-4.9/611-MIPS-ath79-wdt-timeout.patch create mode 100644 target/linux/ar71xx/patches-4.9/612-MIPS-ath79-set-buffalo-txgain.patch create mode 100644 target/linux/ar71xx/patches-4.9/613-MIPS-ath79-add-ath79_wmac_setup_ext_lna_gpio-helper.patch create mode 100644 target/linux/ar71xx/patches-4.9/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch create mode 100644 target/linux/ar71xx/patches-4.9/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch create mode 100644 target/linux/ar71xx/patches-4.9/622-MIPS-ath79-add-more-register-defines-for-QCA956x-SoC.patch create mode 100644 target/linux/ar71xx/patches-4.9/630-MIPS-ath79-fix-chained-irq-disable.patch create mode 100644 target/linux/ar71xx/patches-4.9/631-MIPS-ath79-wmac-enable-set-led-pin.patch create mode 100644 target/linux/ar71xx/patches-4.9/632-MIPS-ath79-gpio-enable-set-direction.patch create mode 100644 target/linux/ar71xx/patches-4.9/640-MIPS-ath79-add-QCA955x-wmac-reset.patch create mode 100644 target/linux/ar71xx/patches-4.9/700-MIPS-ath79-add-openwrt-Kconfig.patch create mode 100644 target/linux/ar71xx/patches-4.9/701-MIPS-ath79-add-routerboard-detection.patch create mode 100644 target/linux/ar71xx/patches-4.9/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch create mode 100644 target/linux/ar71xx/patches-4.9/740-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch create mode 100644 target/linux/ar71xx/patches-4.9/818-MIPS-ath79-add-nu801-led-driver.patch create mode 100644 target/linux/ar71xx/patches-4.9/820-MIPS-ath79-add_gpio_function2_setup.patch create mode 100644 target/linux/ar71xx/patches-4.9/900-mdio_bitbang_ignore_ta_value.patch create mode 100644 target/linux/ar71xx/patches-4.9/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch create mode 100644 target/linux/ar71xx/patches-4.9/902-at803x-add-reset-gpio-pdata.patch create mode 100644 target/linux/ar71xx/patches-4.9/910-unaligned_access_hacks.patch create mode 100644 target/linux/ar71xx/patches-4.9/920-usb-chipidea-AR933x-platform-support.patch create mode 100644 target/linux/ar71xx/patches-4.9/930-chipidea-pullup.patch diff --git a/target/linux/ar71xx/Makefile b/target/linux/ar71xx/Makefile index 3f5bc6724..6d5b4c52b 100644 --- a/target/linux/ar71xx/Makefile +++ b/target/linux/ar71xx/Makefile @@ -13,7 +13,7 @@ FEATURES:=usbgadget CPU_TYPE:=24kc SUBTARGETS:=generic nand mikrotik -KERNEL_PATCHVER:=4.4 +KERNEL_PATCHVER:=4.9 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network index 9a9288780..39e819fd3 100755 --- a/target/linux/ar71xx/base-files/etc/board.d/02_network +++ b/target/linux/ar71xx/base-files/etc/board.d/02_network @@ -531,7 +531,8 @@ ar71xx_setup_macs() lan_mac=$(fritz_tffs -n maca -i $(find_mtd_part "tffs (1)")) ;; tl-wr1043nd-v4) - wan_mac=$(mtd_get_mac_binary config 0x1017c) + lan_mac=$(mtd_get_mac_binary product-info 8) + wan_mac=$(macaddr_add "$lan_mac" 1) ;; esr900) wan_mac=$(mtd_get_mac_ascii u-boot-env "wanaddr") diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 index 09097d0b4..0e7756041 100644 --- a/target/linux/ar71xx/config-4.4 +++ b/target/linux/ar71xx/config-4.4 @@ -260,7 +260,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y CONFIG_CLKDEV_LOOKUP=y CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2 noinitrd" +CONFIG_CMDLINE="rootfstype=squashfs noinitrd" CONFIG_CMDLINE_BOOL=y # CONFIG_CMDLINE_OVERRIDE is not set CONFIG_COMMON_CLK=y diff --git a/target/linux/ar71xx/config-4.9 b/target/linux/ar71xx/config-4.9 new file mode 100644 index 000000000..c5b89088f --- /dev/null +++ b/target/linux/ar71xx/config-4.9 @@ -0,0 +1,485 @@ +CONFIG_AG71XX=y +CONFIG_AG71XX_AR8216_SUPPORT=y +# CONFIG_AG71XX_DEBUG is not set +# CONFIG_AG71XX_DEBUG_FS is not set +CONFIG_AR8216_PHY=y +CONFIG_AR8216_PHY_LEDS=y +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=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=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_AP81 is not set +CONFIG_ATH79_MACH_AP90Q=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_C7=y +CONFIG_ATH79_MACH_ARDUINO_YUN=y +CONFIG_ATH79_MACH_AW_NR580=y +CONFIG_ATH79_MACH_BHR_4GRV2=y +CONFIG_ATH79_MACH_BHU_BXU2000N2_A=y +CONFIG_ATH79_MACH_BSB=y +CONFIG_ATH79_MACH_C55=y +# CONFIG_ATH79_MACH_C60 is not set +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_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_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_600_A1=y +CONFIG_ATH79_MACH_DIR_615_C1=y +CONFIG_ATH79_MACH_DIR_615_I1=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_DOMYWIFI_DW33D is not set +CONFIG_ATH79_MACH_DR344=y +CONFIG_ATH79_MACH_DR531=y +CONFIG_ATH79_MACH_DRAGINO2=y +CONFIG_ATH79_MACH_E2100L=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_ENS202EXT=y +CONFIG_ATH79_MACH_EPG5000=y +CONFIG_ATH79_MACH_ESR1750=y +CONFIG_ATH79_MACH_ESR900=y +CONFIG_ATH79_MACH_EW_DORIN=y +CONFIG_ATH79_MACH_F9K1115V2=y +CONFIG_ATH79_MACH_FRITZ300E=y +CONFIG_ATH79_MACH_GL_AR150=y +CONFIG_ATH79_MACH_GL_AR300=y +CONFIG_ATH79_MACH_GL_AR300M=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_V1=y +CONFIG_ATH79_MACH_GS_OOLITE=y +# CONFIG_ATH79_MACH_HIVEAP_121 is not set +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_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_MR18 is not set +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_NBG460N=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_R602N=y +# 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_RE450=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_TELLSTICK_ZNET_LITE=y +CONFIG_ATH79_MACH_TEW_632BRP=y +CONFIG_ATH79_MACH_TEW_673GRU=y +CONFIG_ATH79_MACH_TEW_712BR=y +CONFIG_ATH79_MACH_TEW_732BR=y +CONFIG_ATH79_MACH_TEW_823DRU=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_MR6400=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_WDR4300=y +CONFIG_ATH79_MACH_TL_WDR6500_V2=y +CONFIG_ATH79_MACH_TL_WPA8630=y +CONFIG_ATH79_MACH_TL_WR1041N_V2=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_WR2543N=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_WR810N=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_WR902AC_V1=y +CONFIG_ATH79_MACH_TL_WR940N_V4=y +CONFIG_ATH79_MACH_TL_WR941ND=y +CONFIG_ATH79_MACH_TL_WR941ND_V6=y +CONFIG_ATH79_MACH_TL_WR942N_V1=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_WEIO=y +CONFIG_ATH79_MACH_WHR_HP_G300N=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_WNDR4300 is not set +CONFIG_ATH79_MACH_WNR2000=y +CONFIG_ATH79_MACH_WNR2000_V3=y +CONFIG_ATH79_MACH_WNR2000_V4=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_Z1 is not set +CONFIG_ATH79_MACH_ZBT_WE1526=y +CONFIG_ATH79_MACH_ZCN_1523H=y +CONFIG_ATH79_NVRAM=y +CONFIG_ATH79_PCI_ATH9K_FIXUP=y +# CONFIG_ATH79_ROUTERBOOT is not set +CONFIG_ATH79_WDT=y +CONFIG_BLK_MQ_PCI=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=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_DTC=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_GPIO_SYSFS=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_HW_HAS_PCI=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_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_WNDR3700_USB is not set +CONFIG_LIBFDT=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_DTB_EXTEND is not set +CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_MIPS_CMDLINE_FROM_DTB is not set +# CONFIG_MIPS_ELF_APPENDED_DTB is not set +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_MIPS_MACHINE=y +CONFIG_MIPS_NO_APPENDED_DTB=y +# CONFIG_MIPS_RAW_APPENDED_DTB is not set +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_MYLOADER=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=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_PCI=y +CONFIG_PCI_AR724X=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +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_RTL8306_PHY=y +CONFIG_RTL8366RB_PHY=y +CONFIG_RTL8366S_PHY=y +CONFIG_RTL8366_SMI=y +CONFIG_RTL8367_PHY=y +# 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_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 +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_SWCONFIG=y +CONFIG_SWCONFIG_LEDS=y +CONFIG_SWPHY=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_USE_OF=y 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 index a0f001cb4..9e08c157e 100644 --- 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 @@ -74,7 +74,7 @@ static struct spi_gpio_platform_data archer_c25_v1_spi_data = { .num_chipselect = 1, }; -static u8 archer_c25_v1_ssr_initdata[] __initdata = { +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) | 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 index f385d4a5a..da15919a5 100644 --- 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 @@ -180,7 +180,7 @@ static struct spi_gpio_platform_data archer_c59_v1_spi_data = { .num_chipselect = 1, }; -static u8 archer_c59_v1_ssr_initdata[] __initdata = { +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) | 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 index f00998c66..46b49bc9b 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7.c @@ -141,7 +141,7 @@ static struct gpio_keys_button archer_c7_v2_gpio_keys[] __initdata = { }, }; -static const struct ar8327_led_info archer_c7_leds_ar8327[] __initconst = { +static const struct ar8327_led_info archer_c7_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"), diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-c60.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-c60.c index e78e311d2..7b01af515 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-c60.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-c60.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -119,6 +120,7 @@ static struct mdio_board_info c60_mdio0_info[] = { }, }; +#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 }, @@ -126,13 +128,67 @@ static struct nand_ecclayout c60_nand_ecclayout = { .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) { struct nand_chip *chip = mtd->priv; 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; } 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 index e686b5fa6..575a976ae 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-ew-dorin.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ew-dorin.c @@ -2,7 +2,7 @@ * EW Dorin board support * (based on Atheros Ref. Design AP121) * Copyright (C) 2011-2012 Gabor Juhos - * Copyright (C) 2012-2015 Embedded Wireless GmbH www.80211.de + * 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 @@ -27,24 +27,12 @@ #define DORIN_CALDATA_OFFSET 0x1000 #define DORIN_WMAC_MAC_OFFSET 0x1002 -#define DORIN_GPIO_LED_21 21 -#define DORIN_GPIO_LED_22 22 -#define DORIN_GPIO_LED_STATUS 23 +#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:led21", - .gpio = DORIN_GPIO_LED_21, - .active_low = 1, - }, - { - .name = "dorin:green:led22", - .gpio = DORIN_GPIO_LED_22, - .active_low = 1, - }, { .name = "dorin:green:status", .gpio = DORIN_GPIO_LED_STATUS, 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 index 9d69dc53f..0c9b197e8 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n750.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-n750.c @@ -98,7 +98,7 @@ static struct gpio_keys_button mynet_n750_gpio_keys[] __initdata = { }, }; -static const struct ar8327_led_info mynet_n750_leds_ar8327[] __initconst = { +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"), diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c index 6e498395b..4dc4647cc 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb2011.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -124,7 +125,7 @@ static struct ar8327_led_cfg rb2011_ar8327_led_cfg = { .open_drain = false, }; -static const struct ar8327_led_info rb2011_ar8327_leds[] __initconst = { +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"), @@ -188,6 +189,7 @@ static void rb2011_nand_select_chip(int chip_no) 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 }, @@ -195,16 +197,72 @@ static struct nand_ecclayout rb2011_nand_ecclayout = { .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; +#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 = &rb2011_nand_ecclayout; +#else + mtd_set_ooblayout(mtd, &rb2011_nand_ecclayout_ops); +#endif } return 0; diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb91x.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb91x.c index ba4da8553..64f927dc6 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb91x.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb91x.c @@ -140,7 +140,7 @@ static struct rb91x_nand_platform_data rb711gr100_nand_data __initdata = { .gpio_nle = RB91X_GPIO_NLE, }; -static u8 rb711gr100_ssr_initdata[] __initdata = { +static u8 rb711gr100_ssr_initdata[] = { BIT(RB91X_SSR_BIT_PCIE_POWER) | BIT(RB91X_SSR_BIT_USB_POWER) | BIT(RB91X_SSR_BIT_5) diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb922.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb922.c index 0c5373c36..577fb0eee 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb922.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb922.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -132,6 +133,7 @@ static void rb922gs_nand_select_chip(int chip_no) 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 }, @@ -139,16 +141,72 @@ static struct nand_ecclayout rb922gs_nand_ecclayout = { .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; +#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 = &rb922gs_nand_ecclayout; +#else + mtd_set_ooblayout(mtd, &rb922gs_nand_ecclayout_ops); +#endif } return 0; diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c index e940d6cc1..9eaeaa7f9 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rb95x.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -146,6 +147,7 @@ static void rb95x_nand_select_chip(int chip_no) 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 }, @@ -153,6 +155,56 @@ static struct nand_ecclayout rb95x_nand_ecclayout = { .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) { struct nand_chip *chip = mtd->priv; @@ -162,7 +214,11 @@ static int rb95x_nand_scan_fixup(struct mtd_info *mtd) * 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; diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c index 9b4c53a57..58e3138b5 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rbspi.c @@ -267,7 +267,7 @@ static struct gpio_led rb962_leds_gpio[] __initdata = { }, }; -static const struct ar8327_led_info rb962_leds_ar8327[] __initconst = { +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"), diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-rbsxtlite.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-rbsxtlite.c index 62063e06a..d2edfc9c7 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-rbsxtlite.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-rbsxtlite.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -163,6 +164,7 @@ static void rbsxtlite_nand_select_chip(int chip_no) 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 }, @@ -170,16 +172,72 @@ static struct nand_ecclayout rbsxtlite_nand_ecclayout = { .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; 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 index 3afc71462..cb5dc1dd2 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c @@ -107,7 +107,7 @@ static struct gpio_keys_button wdr4300_gpio_keys[] __initdata = { }, }; -static const struct ar8327_led_info wdr4300_leds_ar8327[] __initconst = { +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"), 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 index cb224f461..b1539c5d7 100644 --- 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 @@ -57,7 +57,7 @@ #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 0x1ff80174 +#define TL_WR1043_V4_MAC_LOCATION 0x1ff50008 #define TL_WR1043_V4_EEPROM_ADDR 0x1fff0000 #define TL_WR1043_V4_WMAC_CALDATA_OFFSET 0x1000 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 index 72910400c..76f6a0759 100644 --- 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 @@ -148,7 +148,7 @@ static struct spi_gpio_platform_data tl_wr942n_v1_spi_data = { .num_chipselect = 1, }; -static u8 tl_wr942n_v1_ssr_initdata[] __initdata = { +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) | diff --git a/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c b/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c index 8c01efe4a..1355e3ff6 100644 --- a/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c +++ b/target/linux/ar71xx/files/drivers/gpio/gpio-nxp-74hc153.c @@ -168,7 +168,11 @@ static int nxp_74hc153_probe(struct platform_device *pdev) 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); diff --git a/target/linux/ar71xx/files/drivers/leds/leds-nu801.c b/target/linux/ar71xx/files/drivers/leds/leds-nu801.c index f04df61c0..11e892778 100644 --- a/target/linux/ar71xx/files/drivers/leds/leds-nu801.c +++ b/target/linux/ar71xx/files/drivers/leds/leds-nu801.c @@ -98,7 +98,7 @@ static void led_nu801_set(struct led_classdev *led_cdev, } } -static int __init led_nu801_create(struct led_nu801_data *controller, +static int led_nu801_create(struct led_nu801_data *controller, struct device *parent, int index, enum led_brightness brightness, @@ -131,7 +131,7 @@ err: return ret; } -static int __init +static int led_nu801_create_chain(const struct led_nu801_template *template, struct led_nu801_data *controller, struct device *parent) @@ -237,7 +237,7 @@ static void led_nu801_delete_chain(struct led_nu801_data *controller) kfree(led_chain); } -static struct led_nu801_data * __init +static struct led_nu801_data * leds_nu801_create_of(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node, *child; @@ -307,7 +307,7 @@ err: return NULL; } -static int __init led_nu801_probe(struct platform_device *pdev) +static int led_nu801_probe(struct platform_device *pdev) { struct led_nu801_platform_data *pdata = pdev->dev.platform_data; struct led_nu801_data *controllers; diff --git a/target/linux/ar71xx/files/drivers/mtd/cybertan_part.c b/target/linux/ar71xx/files/drivers/mtd/cybertan_part.c index 391411f8d..4d33c19b7 100644 --- a/target/linux/ar71xx/files/drivers/mtd/cybertan_part.c +++ b/target/linux/ar71xx/files/drivers/mtd/cybertan_part.c @@ -28,6 +28,7 @@ #include #include +#include struct cybertan_header { char magic[4]; @@ -82,7 +83,11 @@ struct firmware_header { #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; diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c b/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c index a47fc0468..a135e0f52 100644 --- a/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c +++ b/target/linux/ar71xx/files/drivers/mtd/nand/ar934x_nfc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -187,7 +188,9 @@ 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; @@ -259,7 +262,22 @@ ar934x_nfc_get_platform_data(struct ar934x_nfc *nfc) 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) @@ -648,7 +666,7 @@ 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 = mtd->priv; + struct nand_chip *nand = &nfc->nand_chip; nfc->read_id = false; if (command != NAND_CMD_PAGEPROG) @@ -1241,6 +1259,7 @@ ar934x_nfc_init_tail(struct mtd_info *mtd) return err; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) static struct nand_ecclayout ar934x_nfc_oob_64_hwecc = { .eccbytes = 28, .eccpos = { @@ -1261,19 +1280,60 @@ static struct nand_ecclayout ar934x_nfc_oob_64_hwecc = { }, }; +#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 (!config_enabled(CONFIG_MTD_NAND_AR934X_HW_ECC)) { + if (!IS_ENABLED(CONFIG_MTD_NAND_AR934X_HW_ECC)) { dev_err(nfc->parent, "hardware ECC support is disabled\n"); return -EINVAL; } - switch (nfc->mtd.writesize) { + switch (mtd->writesize) { case 2048: /* * Writing a subpage separately is not supported, because @@ -1284,17 +1344,25 @@ ar934x_nfc_setup_hwecc(struct ar934x_nfc *nfc) 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", - nfc->mtd.writesize); + 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: @@ -1309,12 +1377,17 @@ ar934x_nfc_setup_hwecc(struct ar934x_nfc *nfc) } 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 = nfc->mtd.writesize + nfc->ecc_oob_pos; + nfc->ecc_offset_reg = mtd->writesize + nfc->ecc_oob_pos; nand->ecc.mode = NAND_ECC_HW; nand->ecc.read_page = ar934x_nfc_read_page; @@ -1382,9 +1455,11 @@ ar934x_nfc_probe(struct platform_device *pdev) nfc->swap_dma = pdata->swap_dma; nand = &nfc->nand_chip; - mtd = &nfc->mtd; + 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; @@ -1429,10 +1504,18 @@ ar934x_nfc_probe(struct platform_device *pdev) 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: @@ -1474,10 +1557,12 @@ static int ar934x_nfc_remove(struct platform_device *pdev) { struct ar934x_nfc *nfc; + struct mtd_info *mtd; nfc = platform_get_drvdata(pdev); if (nfc) { - nand_release(&nfc->mtd); + mtd = ar934x_nfc_to_mtd(nfc); + nand_release(mtd); ar934x_nfc_free_buf(nfc); free_irq(nfc->irq, nfc); } diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c b/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c index 96ec5dd1e..b397575f7 100644 --- a/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c +++ b/target/linux/ar71xx/files/drivers/mtd/nand/rb4xx_nand.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,7 @@ struct rb4xx_nand_info { struct mtd_info mtd; }; +#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. @@ -52,6 +54,56 @@ static struct nand_ecclayout rb4xx_nand_ecclayout = { .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", @@ -229,7 +281,11 @@ static int rb4xx_nand_probe(struct platform_device *pdev) } if (info->mtd.writesize == 512) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) info->chip.ecc.layout = &rb4xx_nand_ecclayout; +#else + mtd_set_ooblayout(&info->mtd, &rb4xx_nand_ecclayout_ops); +#endif ret = nand_scan_tail(&info->mtd); if (ret) { diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c b/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c index 0604c5a23..f8a6722cb 100644 --- a/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c +++ b/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ static inline struct rb750_nand_info *mtd_to_rbinfo(struct mtd_info *mtd) return container_of(mtd, struct rb750_nand_info, mtd); } +#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. @@ -60,6 +62,56 @@ static struct nand_ecclayout rb750_nand_ecclayout = { .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", @@ -292,7 +344,11 @@ static int rb750_nand_probe(struct platform_device *pdev) } if (info->mtd.writesize == 512) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) info->chip.ecc.layout = &rb750_nand_ecclayout; +#else + mtd_set_ooblayout(&info->mtd, &rb750_nand_ecclayout_ops); +#endif ret = nand_scan_tail(&info->mtd); if (ret) { diff --git a/target/linux/ar71xx/files/drivers/mtd/nand/rb91x_nand.c b/target/linux/ar71xx/files/drivers/mtd/nand/rb91x_nand.c index 1308e18ba..15b1816ae 100644 --- a/target/linux/ar71xx/files/drivers/mtd/nand/rb91x_nand.c +++ b/target/linux/ar71xx/files/drivers/mtd/nand/rb91x_nand.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,7 @@ static inline struct rb91x_nand_info *mtd_to_rbinfo(struct mtd_info *mtd) return container_of(mtd, struct rb91x_nand_info, mtd); } +#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. @@ -67,6 +69,56 @@ static struct nand_ecclayout rb91x_nand_ecclayout = { .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", @@ -334,7 +386,11 @@ static int rb91x_nand_probe(struct platform_device *pdev) return ret; if (rbni->mtd.writesize == 512) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) rbni->chip.ecc.layout = &rb91x_nand_ecclayout; +#else + mtd_set_ooblayout(&rbni->mtd, &rb91x_nand_ecclayout_ops); +#endif ret = nand_scan_tail(&rbni->mtd); if (ret) diff --git a/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c b/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c index ac1efa1c2..1b94163b8 100644 --- a/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c +++ b/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c @@ -15,6 +15,7 @@ #include #include +#include #define TPLINK_NUM_PARTS 5 #define TPLINK_HEADER_V1 0x01000000 @@ -109,7 +110,11 @@ static int tplink_check_rootfs_magic(struct mtd_info *mtd, size_t offset) } 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) { @@ -181,7 +186,11 @@ err: } 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, @@ -189,7 +198,11 @@ static int tplink_parse_partitions(struct mtd_info *master, } 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, diff --git a/target/linux/ar71xx/files/drivers/net/dsa/mv88e6063.c b/target/linux/ar71xx/files/drivers/net/dsa/mv88e6063.c index b9e9af35b..5b6da713f 100644 --- a/target/linux/ar71xx/files/drivers/net/dsa/mv88e6063.c +++ b/target/linux/ar71xx/files/drivers/net/dsa/mv88e6063.c @@ -17,6 +17,7 @@ #include #include #include +#include #define REG_BASE 0x10 #define REG_PHY(p) (REG_BASE + (p)) @@ -26,11 +27,12 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) - return mdiobus_read(ds->master_mii_bus, addr, reg); -#else +#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 } @@ -47,14 +49,22 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg) static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) - return mdiobus_write(ds->master_mii_bus, addr, reg, val); -#else +#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; \ @@ -64,16 +74,20 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) return __ret; \ }) -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) -static char *mv88e6063_probe(struct mii_bus *bus, int sw_addr) -{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static char *mv88e6063_drv_probe(struct device *host_dev, int sw_addr) #else -static char *mv88e6063_probe(struct device *host_dev, int sw_addr) +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); -#endif int ret; + if (!bus) + return NULL; + ret = mdiobus_read(bus, REG_PORT(0), 0x03); if (ret >= 0) { ret &= 0xfff0; @@ -163,7 +177,11 @@ static int mv88e6063_setup_port(struct dsa_switch *ds, int p) 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 (1 << ds->dst->cpu_port))); /* @@ -240,72 +258,32 @@ mv88e6063_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) return reg_write(ds, addr, regnum, val); } -static void mv88e6063_poll_link(struct dsa_switch *ds) -{ - int i; - - for (i = 0; i < DSA_MAX_PORTS; i++) { - struct net_device *dev; - int uninitialized_var(port_status); - int link; - int speed; - int duplex; - int fc; - - dev = ds->ports[i]; - if (dev == NULL) - continue; - - link = 0; - if (dev->flags & IFF_UP) { - port_status = reg_read(ds, REG_PORT(i), 0x00); - if (port_status < 0) - continue; - - link = !!(port_status & 0x1000); - } - - if (!link) { - if (netif_carrier_ok(dev)) { - printk(KERN_INFO "%s: link down\n", dev->name); - netif_carrier_off(dev); - } - continue; - } - - speed = (port_status & 0x0100) ? 100 : 10; - duplex = (port_status & 0x0200) ? 1 : 0; - fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0; - - if (!netif_carrier_ok(dev)) { - printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, " - "flow control %sabled\n", dev->name, - speed, duplex ? "full" : "half", - fc ? "en" : "dis"); - netif_carrier_on(dev); - } - } -} - -static struct dsa_switch_driver mv88e6063_switch_driver = { +#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), - .probe = mv88e6063_probe, +#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, - .poll_link = mv88e6063_poll_link, }; static int __init mv88e6063_init(void) { - register_switch_driver(&mv88e6063_switch_driver); + register_switch_driver(&mv88e6063_switch_ops); return 0; } module_init(mv88e6063_init); static void __exit mv88e6063_cleanup(void) { - unregister_switch_driver(&mv88e6063_switch_driver); + unregister_switch_driver(&mv88e6063_switch_ops); } module_exit(mv88e6063_cleanup); 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 index 566e9513d..ae1bdf606 100644 --- 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 @@ -1089,7 +1089,7 @@ next: while ((skb = __skb_dequeue(&queue)) != NULL) { skb->protocol = eth_type_trans(skb, dev); - netif_receive_skb(skb); + napi_gro_receive(&ag->napi, skb); } DBG("%s: rx finish, curr=%u, dirty=%u, done=%d\n", @@ -1141,7 +1141,7 @@ static int ag71xx_poll(struct napi_struct *napi, int limit) DBG("%s: disable polling mode, rx=%d, tx=%d,limit=%d\n", dev->name, rx_done, tx_done, limit); - napi_complete(napi); + napi_complete_done(napi, rx_done); /* enable interrupts */ spin_lock_irqsave(&ag->lock, flags); @@ -1160,7 +1160,7 @@ oom: pr_info("%s: out of memory\n", dev->name); mod_timer(&ag->oom_timer, jiffies + AG71XX_OOM_REFILL); - napi_complete(napi); + napi_complete_done(napi, rx_done); return 0; } 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 index b63a4b7f9..291547656 100644 --- 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 @@ -254,7 +254,11 @@ static int ag71xx_mdio_probe(struct platform_device *pdev) 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; +#else + memcpy(am->mii_bus->irq, am->mii_irq, sizeof(am->mii_bus->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)); 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 index 9de77e924..12fa2e301 100644 --- 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 @@ -112,6 +112,7 @@ static int ag71xx_phy_connect_multi(struct ag71xx *ag) 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; @@ -122,6 +123,18 @@ static int ag71xx_phy_connect_multi(struct ag71xx *ag) 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), + ag->mii_bus->mdio_map[phy_addr]->phy_id); + + if (phydev == NULL) + phydev = mdiobus_get_phy(ag->mii_bus, phy_addr); +#endif } if (!phydev) { @@ -130,13 +143,21 @@ static int ag71xx_phy_connect_multi(struct ag71xx *ag) 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); } @@ -149,7 +170,12 @@ static int ag71xx_phy_connect_multi(struct ag71xx *ag) phydev->advertising = phydev->supported; dev_info(dev, "connected to PHY at %s [uid=%08x, driver=%s]\n", - dev_name(&phydev->dev), phydev->phy_id, phydev->drv->name); +#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; diff --git a/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c b/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c index 0534c7c37..18af83b67 100644 --- a/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c +++ b/target/linux/ar71xx/files/drivers/spi/spi-rb4xx-cpld.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -246,7 +247,11 @@ static int rb4xx_cpld_gpio_init(struct rb4xx_cpld *cpld, unsigned int base) 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); diff --git a/target/linux/ar71xx/generic/config-default b/target/linux/ar71xx/generic/config-default index 45169689e..e69de29bb 100644 --- a/target/linux/ar71xx/generic/config-default +++ b/target/linux/ar71xx/generic/config-default @@ -1 +0,0 @@ -CONFIG_CMDLINE="rootfstype=squashfs,jffs2 noinitrd" diff --git a/target/linux/ar71xx/image/generic.mk b/target/linux/ar71xx/image/generic.mk index 3352d156a..6f5a7016e 100644 --- a/target/linux/ar71xx/image/generic.mk +++ b/target/linux/ar71xx/image/generic.mk @@ -229,6 +229,26 @@ define Device/dragino2 endef TARGET_DEVICES += dragino2 +define Device/ew-dorin + DEVICE_TITLE := Embedded Wireless Dorin Platform + DEVICE_PACKAGES := kmod-usb-core kmod-usb-chipidea + BOARDNAME = EW-DORIN + CONSOLE := ttyATH0,115200 + IMAGE_SIZE = 16000k + MTDPARTS = spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro +endef +TARGET_DEVICES += ew-dorin + +define Device/ew-dorin-router + DEVICE_TITLE := Embedded Wireless Dorin Router Platform + DEVICE_PACKAGES := kmod-usb-core kmod-usb-chipidea + BOARDNAME = EW-DORIN-ROUTER + CONSOLE := ttyATH0,115200 + IMAGE_SIZE = 16000k + MTDPARTS = spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro +endef +TARGET_DEVICES += ew-dorin-router + define Device/weio DEVICE_TITLE := WeIO DEVICE_PACKAGES := kmod-usb-core kmod-usb2 diff --git a/target/linux/ar71xx/image/legacy-devices.mk b/target/linux/ar71xx/image/legacy-devices.mk index 77230249a..e418282dd 100644 --- a/target/linux/ar71xx/image/legacy-devices.mk +++ b/target/linux/ar71xx/image/legacy-devices.mk @@ -132,24 +132,6 @@ define LegacyDevice/DB120 endef LEGACY_DEVICES += DB120 -define LegacyDevice/EWDORINAP - DEVICE_TITLE := Embedded Wireless Dorin Platform (4MB flash) - DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport kmod-usb-storage -endef -LEGACY_DEVICES += EWDORINAP - -define LegacyDevice/EWDORINRT - DEVICE_TITLE := Embedded Wireless Dorin Router - DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport kmod-usb-storage -endef -LEGACY_DEVICES += EWDORINRT - -define LegacyDevice/EWDORIN16M - DEVICE_TITLE := Embedded Wireless Dorin Platform (16MB flash) - DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport kmod-usb-storage -endef -LEGACY_DEVICES += EWDORIN16M - define LegacyDevice/HORNETUBx2 DEVICE_TITLE := ALFA Network Hornet-UB-x2 board (16MB flash, 64MB ram) DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport diff --git a/target/linux/ar71xx/image/legacy.mk b/target/linux/ar71xx/image/legacy.mk index b400e5ddb..701116be4 100644 --- a/target/linux/ar71xx/image/legacy.mk +++ b/target/linux/ar71xx/image/legacy.mk @@ -258,8 +258,6 @@ cameo_ap94_mtdlayout_fat=mtdparts=spi0.0:256k(uboot)ro,64k(config)ro,7808k(firmw 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) -ew-dorin_mtdlayout_4M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env),3712k(firmware),64k(art)ro -ew-dorin_mtdlayout_16M=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env),16000k(firmware),64k(art)ro 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) @@ -897,9 +895,6 @@ $(eval $(call SingleProfile,AthLzma,64k,AP152_16M,ap152-16M,AP152,ttyS0,115200,$ $(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,EWDORINAP,ew-dorin,EW-DORIN,ttyATH0,115200,$$(ew-dorin_mtdlayout_4M),KRuImage,65536)) -$(eval $(call SingleProfile,AthLzma,64k,EWDORINRT,ew-dorin-router,EW-DORIN-ROUTER,ttyATH0,115200,$$(ew-dorin_mtdlayout_4M),KRuImage,65536)) -$(eval $(call SingleProfile,AthLzma,64k,EWDORIN16M,ew-dorin-16M,EW-DORIN,ttyATH0,115200,$$(ew-dorin_mtdlayout_16M),KRuImage,65536)) $(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,AthLzma,64k,WLR8100,wlr8100,WLR8100,ttyS0,115200,$$(wlr8100_mtdlayout),KRuImage)) diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk index 74540b92a..94cb7f373 100644 --- a/target/linux/ar71xx/image/tp-link.mk +++ b/target/linux/ar71xx/image/tp-link.mk @@ -76,7 +76,7 @@ define Device/tplink-8m IMAGE_SIZE := 7936k endef -define Device/tplink-8mlzma +define Device/tplink-4mlzma $(Device/tplink) TPLINK_FLASHLAYOUT := 4Mlzma IMAGE_SIZE := 3904k @@ -486,6 +486,7 @@ endef define Device/tl-wa850re-v1 $(Device/tplink-8mlzma) DEVICE_TITLE := TP-LINK TL-WA850RE v1 + DEVICE_PACKAGES := rssileds BOARDNAME := TL-WA850RE DEVICE_PROFILE := TLWA850 TPLINK_HWID := 0x08500001 diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default index d448560eb..e333166e9 100644 --- a/target/linux/ar71xx/mikrotik/config-default +++ b/target/linux/ar71xx/mikrotik/config-default @@ -212,11 +212,10 @@ CONFIG_ATH79_MACH_RBSXTLITE=y # CONFIG_ATH79_MACH_ZCN_1523H is not set # CONFIG_ATH79_NVRAM is not set CONFIG_ATH79_ROUTERBOOT=y -CONFIG_CMDLINE="rootfstype=squashfs noinitrd" CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_GPIO_LATCH=y -# CONFIG_LANTIQ_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set CONFIG_LEDS_RB750=y CONFIG_LZO_DECOMPRESS=y # CONFIG_MTD_CFI is not set diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default index 2d3b06f69..fc243c500 100644 --- a/target/linux/ar71xx/nand/config-default +++ b/target/linux/ar71xx/nand/config-default @@ -209,12 +209,11 @@ CONFIG_ATH79_MACH_Z1=y # CONFIG_ATH79_MACH_ZBT_WE1526 is not set # CONFIG_ATH79_MACH_ZCN_1523H is not set CONFIG_BCH=y -CONFIG_CMDLINE="rootfstype=squashfs noinitrd" CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y +# CONFIG_INTEL_XWAY_PHY is not set # CONFIG_IP17XX_PHY is not set -# CONFIG_LANTIQ_PHY is not set CONFIG_LEDS_NU801=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y diff --git a/target/linux/ar71xx/patches-4.4/902-at803x-add-reset-gpio-pdata.patch b/target/linux/ar71xx/patches-4.4/902-at803x-add-reset-gpio-pdata.patch index 2244f882e..efc8502bc 100644 --- a/target/linux/ar71xx/patches-4.4/902-at803x-add-reset-gpio-pdata.patch +++ b/target/linux/ar71xx/patches-4.4/902-at803x-add-reset-gpio-pdata.patch @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau */ if (phydev->state == PHY_NOLINK) { - if (priv->gpiod_reset && !priv->phy_reset) { -+ if ((priv->gpiod_reset || pdata->has_reset_gpio) && ++ if ((priv->gpiod_reset || (pdata && pdata->has_reset_gpio)) && + !priv->phy_reset) { struct at803x_context context; @@ -52,7 +52,7 @@ Signed-off-by: Felix Fietkau - msleep(1); - gpiod_set_value(priv->gpiod_reset, 0); - msleep(1); -+ if (pdata->has_reset_gpio) { ++ if (pdata && pdata->has_reset_gpio) { + gpio_set_value_cansleep(pdata->reset_gpio, 0); + msleep(1); + gpio_set_value_cansleep(pdata->reset_gpio, 1); diff --git a/target/linux/ar71xx/patches-4.4/920-usb-chipidea-AR933x-platform-support.patch b/target/linux/ar71xx/patches-4.4/920-usb-chipidea-AR933x-platform-support.patch index 1a78af077..740ffec4a 100644 --- a/target/linux/ar71xx/patches-4.4/920-usb-chipidea-AR933x-platform-support.patch +++ b/target/linux/ar71xx/patches-4.4/920-usb-chipidea-AR933x-platform-support.patch @@ -29,7 +29,7 @@ #include #include -@@ -170,6 +173,51 @@ static void __init ar913x_usb_setup(void +@@ -170,6 +173,67 @@ static void __init ar913x_usb_setup(void &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); } @@ -46,22 +46,29 @@ + iounmap(usb_ctrl_base); +} + -+static void __init ar933x_ci_usb_setup(void) ++static void __init ar9xxx_ci_usb_setup(void) +{ + struct ci_hdrc_platform_data ci_pdata; + enum usb_dr_mode dr_mode; -+ u32 bootstrap; ++ bool host_mode = true; + -+ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); -+ if (bootstrap & AR933X_BOOTSTRAP_USB_MODE_HOST) { ++ if (soc_is_ar933x()) ++ host_mode = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP) & ++ AR933X_BOOTSTRAP_USB_MODE_HOST; ++ else if (soc_is_ar934x() || soc_is_qca955x()) ++ host_mode = !(ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP) & ++ AR934X_BOOTSTRAP_USB_MODE_DEVICE); ++ ++ if (host_mode) { + dr_mode = USB_DR_MODE_HOST; + } else { + dr_mode = USB_DR_MODE_PERIPHERAL; -+ ar933x_usb_setup_ctrl_config(); ++ if (soc_is_ar933x()) ++ ar933x_usb_setup_ctrl_config(); + } + + memset(&ci_pdata, 0, sizeof(ci_pdata)); -+ ci_pdata.name = "ci_hdrc_ar933x"; ++ ci_pdata.name = "ci_hdrc_ar9xxx"; + ci_pdata.capoffset = DEF_CAPOFFSET; + ci_pdata.dr_mode = dr_mode; + ci_pdata.flags = CI_HDRC_DUAL_ROLE_NOT_OTG | CI_HDRC_DP_ALWAYS_PULLUP; @@ -76,17 +83,41 @@ + AR933X_EHCI_BASE, AR933X_EHCI_SIZE, + ATH79_CPU_IRQ(3), + &ci_pdata, sizeof(ci_pdata)); ++ ++ if (!host_mode) ++ return; ++ ++ 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 __init ar933x_usb_setup(void) { ath79_device_reset_set(AR933X_RESET_USBSUS_OVERRIDE); -@@ -185,6 +233,8 @@ static void __init ar933x_usb_setup(void - AR933X_EHCI_BASE, AR933X_EHCI_SIZE, - ATH79_CPU_IRQ(3), - &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); -+ -+ ar933x_ci_usb_setup(); +@@ -181,10 +245,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(); } static void enable_tx_tx_idp_violation_fix(unsigned base) +@@ -230,10 +291,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(); + } + + static void __init qca953x_usb_setup(void) diff --git a/target/linux/ar71xx/patches-4.9/001-spi-cs-gpio.patch b/target/linux/ar71xx/patches-4.9/001-spi-cs-gpio.patch new file mode 100644 index 000000000..7a0b669e4 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/002-add_back_gpio_function_select.patch b/target/linux/ar71xx/patches-4.9/002-add_back_gpio_function_select.patch new file mode 100644 index 000000000..5b26a640e --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/004-register_gpio_driver_earlier.patch b/target/linux/ar71xx/patches-4.9/004-register_gpio_driver_earlier.patch new file mode 100644 index 000000000..e6e972b7e --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/004-register_gpio_driver_earlier.patch @@ -0,0 +1,15 @@ +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,4 +322,8 @@ 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); diff --git a/target/linux/ar71xx/patches-4.9/100-MIPS-ath79-Avoid-using-unitialized-reg-variable.patch b/target/linux/ar71xx/patches-4.9/100-MIPS-ath79-Avoid-using-unitialized-reg-variable.patch new file mode 100644 index 000000000..8d5b08998 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/103-MIPS-ath79-fix-register-address-in-ath79_ddr_wb_flus.patch b/target/linux/ar71xx/patches-4.9/103-MIPS-ath79-fix-register-address-in-ath79_ddr_wb_flus.patch new file mode 100644 index 000000000..64fb545b2 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/103-MIPS-ath79-fix-register-address-in-ath79_ddr_wb_flus.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Wed, 18 May 2016 18:03:31 +0200 +Subject: [PATCH] MIPS: ath79: fix register address in ath79_ddr_wb_flush() + +ath79_ddr_wb_flush_base has the type void __iomem *, so register offsets +need to be a multiple of 4. + +Cc: Alban Bedel +Fixes: 24b0e3e84fbf ("MIPS: ath79: Improve the DDR controller interface") +Signed-off-by: Felix Fietkau +--- + +--- a/arch/mips/ath79/common.c ++++ b/arch/mips/ath79/common.c +@@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init); + + void ath79_ddr_wb_flush(u32 reg) + { +- void __iomem *flush_reg = ath79_ddr_wb_flush_base + reg; ++ void __iomem *flush_reg = ath79_ddr_wb_flush_base + reg * 4; + + /* Flush the DDR write buffer. */ + __raw_writel(0x1, flush_reg); diff --git a/target/linux/ar71xx/patches-4.9/104-spi-spi-ath79-support-multiple-internal-chip-select-.patch b/target/linux/ar71xx/patches-4.9/104-spi-spi-ath79-support-multiple-internal-chip-select-.patch new file mode 100644 index 000000000..3c355cd21 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/104-spi-spi-ath79-support-multiple-internal-chip-select-.patch @@ -0,0 +1,70 @@ +From: Felix Fietkau +Date: Fri, 9 Dec 2016 20:09:16 +0100 +Subject: [PATCH] spi: spi-ath79: support multiple internal chip select + lines + +Several devices with multiple flash chips use the internal chip select +lines. Don't assume that chip select 1 and above are GPIO lines. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/spi/spi-ath79.c ++++ b/drivers/spi/spi-ath79.c +@@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); + } + +- if (spi->chip_select) { ++ if (gpio_is_valid(spi->cs_gpio)) { + /* SPI is normally active-low */ + gpio_set_value(spi->cs_gpio, cs_high); + } else { ++ u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); ++ + if (cs_high) +- sp->ioc_base |= AR71XX_SPI_IOC_CS0; ++ sp->ioc_base |= cs_bit; + else +- sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; ++ sp->ioc_base &= ~cs_bit; + + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); + } +@@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi + struct ath79_spi *sp = ath79_spidev_to_sp(spi); + int status; + +- if (spi->chip_select && !gpio_is_valid(spi->cs_gpio)) +- return -EINVAL; +- + status = 0; +- if (spi->chip_select) { ++ if (gpio_is_valid(spi->cs_gpio)) { + unsigned long flags; + + flags = GPIOF_DIR_OUT; +@@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi + status = gpio_request_one(spi->cs_gpio, flags, + dev_name(&spi->dev)); + } else { ++ u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); ++ + if (spi->mode & SPI_CS_HIGH) +- sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; ++ sp->ioc_base &= ~cs_bit; + else +- sp->ioc_base |= AR71XX_SPI_IOC_CS0; ++ sp->ioc_base |= cs_bit; + + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); + } +@@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct spi + + static void ath79_spi_cleanup_cs(struct spi_device *spi) + { +- if (spi->chip_select) { ++ if (gpio_is_valid(spi->cs_gpio)) { + gpio_free(spi->cs_gpio); + } + } diff --git a/target/linux/ar71xx/patches-4.9/105-spi-spi-ath79-use-gpio_set_value_cansleep-for-GPIO-c.patch b/target/linux/ar71xx/patches-4.9/105-spi-spi-ath79-use-gpio_set_value_cansleep-for-GPIO-c.patch new file mode 100644 index 000000000..11b6a8310 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/105-spi-spi-ath79-use-gpio_set_value_cansleep-for-GPIO-c.patch @@ -0,0 +1,19 @@ +From: Felix Fietkau +Date: Fri, 9 Dec 2016 20:11:35 +0100 +Subject: [PATCH] spi: spi-ath79: use gpio_set_value_cansleep for GPIO chip + select + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/spi/spi-ath79.c ++++ b/drivers/spi/spi-ath79.c +@@ -80,7 +80,7 @@ static void ath79_spi_chipselect(struct + + if (gpio_is_valid(spi->cs_gpio)) { + /* SPI is normally active-low */ +- gpio_set_value(spi->cs_gpio, cs_high); ++ gpio_set_value_cansleep(spi->cs_gpio, cs_high); + } else { + u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); + diff --git a/target/linux/ar71xx/patches-4.9/106-01-MIPS-ath79-fix-AR724X_PLL_REG_PCIE_CONFIG-offset.patch b/target/linux/ar71xx/patches-4.9/106-01-MIPS-ath79-fix-AR724X_PLL_REG_PCIE_CONFIG-offset.patch new file mode 100644 index 000000000..e785b30ef --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/106-01-MIPS-ath79-fix-AR724X_PLL_REG_PCIE_CONFIG-offset.patch @@ -0,0 +1,29 @@ +From 0f15814bcdf59f10b708a3fba636acb089e9a4f1 Mon Sep 17 00:00:00 2001 +From: Mathias Kresin +Date: Thu, 30 Mar 2017 15:34:39 +0200 +Subject: [PATCH] MIPS: ath79: fix AR724X_PLL_REG_PCIE_CONFIG offset + +According to the QCA u-boot source the "PCIE Phase Lock Loop +Configuration (PCIE_PLL_CONFIG)" register is for all SoCs except the +QCA955X and QCA956X at offset 0x10. + +Since the PCIE PLL config register is only defined for the AR724x fix +only this value. The value is wrong since the day it was added and isn't +yet used by any driver. + +Signed-off-by: Mathias Kresin +--- + arch/mips/include/asm/mach-ath79/ar71xx_regs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +@@ -167,7 +167,7 @@ + #define AR71XX_AHB_DIV_MASK 0x7 + + #define AR724X_PLL_REG_CPU_CONFIG 0x00 +-#define AR724X_PLL_REG_PCIE_CONFIG 0x18 ++#define AR724X_PLL_REG_PCIE_CONFIG 0x10 + + #define AR724X_PLL_FB_SHIFT 0 + #define AR724X_PLL_FB_MASK 0x3ff diff --git a/target/linux/ar71xx/patches-4.9/106-02-MIPS-ath79-do-AR724x-PCIe-root-complex-init.patch b/target/linux/ar71xx/patches-4.9/106-02-MIPS-ath79-do-AR724x-PCIe-root-complex-init.patch new file mode 100644 index 000000000..3af99bf3b --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/200-MIPS-ath79-fix-ar933x-wmac-reset.patch b/target/linux/ar71xx/patches-4.9/200-MIPS-ath79-fix-ar933x-wmac-reset.patch new file mode 100644 index 000000000..b7ae0ce64 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/201-ar913x_wmac_external_reset.patch b/target/linux/ar71xx/patches-4.9/201-ar913x_wmac_external_reset.patch new file mode 100644 index 000000000..9b704a3c4 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/202-MIPS-ath79-ar934x-wmac-revision.patch b/target/linux/ar71xx/patches-4.9/202-MIPS-ath79-ar934x-wmac-revision.patch new file mode 100644 index 000000000..0f8016f84 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/203-MIPS-ath79-fix-restart.patch b/target/linux/ar71xx/patches-4.9/203-MIPS-ath79-fix-restart.patch new file mode 100644 index 000000000..48f4d95e7 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/203-MIPS-ath79-fix-restart.patch @@ -0,0 +1,20 @@ +--- a/arch/mips/ath79/setup.c ++++ b/arch/mips/ath79/setup.c +@@ -40,6 +40,7 @@ static char ath79_sys_type[ATH79_SYS_TYP + + static void ath79_restart(char *command) + { ++ local_irq_disable(); + ath79_device_reset_set(AR71XX_RESET_FULL_CHIP); + for (;;) + if (cpu_wait) +--- a/arch/mips/include/asm/mach-ath79/ath79.h ++++ b/arch/mips/include/asm/mach-ath79/ath79.h +@@ -135,6 +135,7 @@ static inline u32 ath79_pll_rr(unsigned + static inline void ath79_reset_wr(unsigned reg, u32 val) + { + __raw_writel(val, ath79_reset_base + reg); ++ (void) __raw_readl(ath79_reset_base + reg); /* flush */ + } + + static inline u32 ath79_reset_rr(unsigned reg) diff --git a/target/linux/ar71xx/patches-4.9/220-add_cpu_feature_overrides.patch b/target/linux/ar71xx/patches-4.9/220-add_cpu_feature_overrides.patch new file mode 100644 index 000000000..d925f9262 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/300-MIPS-add-MIPS_MACHINE_NONAME-macro.patch b/target/linux/ar71xx/patches-4.9/300-MIPS-add-MIPS_MACHINE_NONAME-macro.patch new file mode 100644 index 000000000..0bc64b7a1 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/310-lib-add-rle-decompression.patch b/target/linux/ar71xx/patches-4.9/310-lib-add-rle-decompression.patch new file mode 100644 index 000000000..d8480125a --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/310-lib-add-rle-decompression.patch @@ -0,0 +1,124 @@ +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -247,6 +247,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 +@@ -120,6 +120,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.9/401-mtd-physmap-add-lock-unlock.patch b/target/linux/ar71xx/patches-4.9/401-mtd-physmap-add-lock-unlock.patch new file mode 100644 index 000000000..db7b3ca83 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/402-mtd-SST39VF6401B-support.patch b/target/linux/ar71xx/patches-4.9/402-mtd-SST39VF6401B-support.patch new file mode 100644 index 000000000..0d483ab1a --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/403-mtd_fix_cfi_cmdset_0002_status_check.patch b/target/linux/ar71xx/patches-4.9/403-mtd_fix_cfi_cmdset_0002_status_check.patch new file mode 100644 index 000000000..415d835ee --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/403-mtd_fix_cfi_cmdset_0002_status_check.patch @@ -0,0 +1,69 @@ +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -1630,8 +1630,8 @@ static int __xipram do_write_oneword(str + break; + } + +- if (chip_ready(map, adr)) +- break; ++ if (chip_good(map, adr, datum)) ++ goto enable_xip; + + /* Latency issues. Drop the lock, wait a while and retry */ + UDELAY(map, chip, adr, 1); +@@ -1647,6 +1647,8 @@ static int __xipram do_write_oneword(str + + ret = -EIO; + } ++ ++ enable_xip: + xip_enable(map, chip, adr); + op_done: + if (mode == FL_OTP_WRITE) +@@ -2225,7 +2227,6 @@ static int cfi_amdstd_panic_write(struct + return 0; + } + +- + /* + * Handle devices with one erase region, that only implement + * the chip erase command. +@@ -2289,8 +2290,8 @@ static int __xipram do_erase_chip(struct + chip->erase_suspended = 0; + } + +- if (chip_ready(map, adr)) +- break; ++ if (chip_good(map, adr, map_word_ff(map))) ++ goto op_done; + + if (time_after(jiffies, timeo)) { + printk(KERN_WARNING "MTD %s(): software timeout\n", +@@ -2310,6 +2311,7 @@ static int __xipram do_erase_chip(struct + ret = -EIO; + } + ++ op_done: + chip->state = FL_READY; + xip_enable(map, chip, adr); + DISABLE_VPP(map); +@@ -2378,9 +2380,9 @@ static int __xipram do_erase_oneblock(st + chip->erase_suspended = 0; + } + +- if (chip_ready(map, adr)) { ++ if (chip_good(map, adr, map_word_ff(map))) { + xip_enable(map, chip, adr); +- break; ++ goto op_done; + } + + if (time_after(jiffies, timeo)) { +@@ -2402,6 +2404,7 @@ static int __xipram do_erase_oneblock(st + ret = -EIO; + } + ++ op_done: + chip->state = FL_READY; + DISABLE_VPP(map); + put_chip(map, chip, adr); diff --git a/target/linux/ar71xx/patches-4.9/404-mtd-cybertan-trx-parser.patch b/target/linux/ar71xx/patches-4.9/404-mtd-cybertan-trx-parser.patch new file mode 100644 index 000000000..6c2322e07 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -17,6 +17,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.9/405-mtd-tp-link-partition-parser.patch b/target/linux/ar71xx/patches-4.9/405-mtd-tp-link-partition-parser.patch new file mode 100644 index 000000000..a53d9501e --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -17,6 +17,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.9/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch b/target/linux/ar71xx/patches-4.9/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch new file mode 100644 index 000000000..4fa957e70 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -192,6 +192,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; +@@ -244,8 +245,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 +@@ -24,6 +24,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.9/408-mtd-redboot_partition_scan.patch b/target/linux/ar71xx/patches-4.9/408-mtd-redboot_partition_scan.patch new file mode 100644 index 000000000..cd41e7ceb --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/409-mtd-rb4xx_nand_driver.patch b/target/linux/ar71xx/patches-4.9/409-mtd-rb4xx_nand_driver.patch new file mode 100644 index 000000000..93d34b882 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/409-mtd-rb4xx_nand_driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -569,4 +569,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 +@@ -33,6 +33,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_FSL_ELBC) += fsl_elbc_nand.o diff --git a/target/linux/ar71xx/patches-4.9/410-mtd-rb750-nand-driver.patch b/target/linux/ar71xx/patches-4.9/410-mtd-rb750-nand-driver.patch new file mode 100644 index 000000000..9ea879c8e --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/410-mtd-rb750-nand-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -573,4 +573,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 +@@ -34,6 +34,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_FSL_ELBC) += fsl_elbc_nand.o diff --git a/target/linux/ar71xx/patches-4.9/411-mtd-cfi_cmdset_0002-force-word-write.patch b/target/linux/ar71xx/patches-4.9/411-mtd-cfi_cmdset_0002-force-word-write.patch new file mode 100644 index 000000000..7f5b2f55a --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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_WORD_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) +@@ -1789,6 +1793,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) +@@ -1917,7 +1922,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) + { +@@ -1992,6 +1996,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.9/413-mtd-ar934x-nand-driver.patch b/target/linux/ar71xx/patches-4.9/413-mtd-ar934x-nand-driver.patch new file mode 100644 index 000000000..9f9c339e6 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/413-mtd-ar934x-nand-driver.patch @@ -0,0 +1,25 @@ +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -577,4 +577,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.9/414-mtd-rb91x-nand-driver.patch b/target/linux/ar71xx/patches-4.9/414-mtd-rb91x-nand-driver.patch new file mode 100644 index 000000000..d1b61f096 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/414-mtd-rb91x-nand-driver.patch @@ -0,0 +1,23 @@ +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -577,6 +577,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 +@@ -36,6 +36,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_FSL_ELBC) += fsl_elbc_nand.o diff --git a/target/linux/ar71xx/patches-4.9/420-net-ar71xx_mac_driver.patch b/target/linux/ar71xx/patches-4.9/420-net-ar71xx_mac_driver.patch new file mode 100644 index 000000000..feb2e6a39 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -2,6 +2,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.9/423-dsa-add-88e6063-driver.patch b/target/linux/ar71xx/patches-4.9/423-dsa-add-88e6063-driver.patch new file mode 100644 index 000000000..1df93e996 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/423-dsa-add-88e6063-driver.patch @@ -0,0 +1,24 @@ +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -9,6 +9,13 @@ config NET_DSA_MV88E6060 + This enables support for the Marvell 88E6060 ethernet switch + chip. + ++config NET_DSA_MV88E6063 ++ bool "Marvell 88E6063 ethernet switch chip support" ++ 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 +--- a/drivers/net/dsa/Makefile ++++ b/drivers/net/dsa/Makefile +@@ -1,4 +1,5 @@ + obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o ++obj-$(CONFIG_NET_DSA_MV88E6063) += mv88e6063.o + obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm_sf2.o + obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o + diff --git a/target/linux/ar71xx/patches-4.9/430-drivers-link-spi-before-mtd.patch b/target/linux/ar71xx/patches-4.9/430-drivers-link-spi-before-mtd.patch new file mode 100644 index 000000000..a86245459 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/430-drivers-link-spi-before-mtd.patch @@ -0,0 +1,12 @@ +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -77,8 +77,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.9/432-spi-rb4xx-spi-driver.patch b/target/linux/ar71xx/patches-4.9/432-spi-rb4xx-spi-driver.patch new file mode 100644 index 000000000..e896d0bdf --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/432-spi-rb4xx-spi-driver.patch @@ -0,0 +1,25 @@ +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -533,6 +533,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 +@@ -72,6 +72,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.9/433-spi-rb4xx-cpld-driver.patch b/target/linux/ar71xx/patches-4.9/433-spi-rb4xx-cpld-driver.patch new file mode 100644 index 000000000..c44acab32 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/433-spi-rb4xx-cpld-driver.patch @@ -0,0 +1,26 @@ +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -761,6 +761,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 +@@ -73,6 +73,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.9/435-spi-vsc7385_driver.patch b/target/linux/ar71xx/patches-4.9/435-spi-vsc7385_driver.patch new file mode 100644 index 000000000..f9f1f7a1e --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/435-spi-vsc7385_driver.patch @@ -0,0 +1,24 @@ +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -768,6 +768,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 +@@ -99,6 +99,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.9/440-leds-wndr3700-usb-led-driver.patch b/target/linux/ar71xx/patches-4.9/440-leds-wndr3700-usb-led-driver.patch new file mode 100644 index 000000000..0bf5b1a7d --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/440-leds-wndr3700-usb-led-driver.patch @@ -0,0 +1,26 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -659,6 +659,13 @@ config LEDS_MLXCPLD + This option enabled support for the LEDs on the Mellanox + boards. Say Y to enabled these. + ++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 +@@ -48,6 +48,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.9/441-leds-rb750-led-driver.patch b/target/linux/ar71xx/patches-4.9/441-leds-rb750-led-driver.patch new file mode 100644 index 000000000..777a0df91 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/441-leds-rb750-led-driver.patch @@ -0,0 +1,23 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -666,6 +666,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 +@@ -55,6 +55,7 @@ obj-$(CONFIG_LEDS_LT3593) += leds-lt359 + obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o + obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.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.9/450-gpio-nxp-74hc153-gpio-chip-driver.patch b/target/linux/ar71xx/patches-4.9/450-gpio-nxp-74hc153-gpio-chip-driver.patch new file mode 100644 index 000000000..41cf75a55 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/450-gpio-nxp-74hc153-gpio-chip-driver.patch @@ -0,0 +1,25 @@ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -1211,4 +1211,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 +@@ -83,6 +83,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.9/451-gpio-74x164-improve-platform-device-support.patch b/target/linux/ar71xx/patches-4.9/451-gpio-74x164-improve-platform-device-support.patch new file mode 100644 index 000000000..d9cfa888f --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/451-gpio-74x164-improve-platform-device-support.patch @@ -0,0 +1,117 @@ +--- a/drivers/gpio/gpio-74x164.c ++++ b/drivers/gpio/gpio-74x164.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -103,9 +104,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 + */ +@@ -115,17 +123,23 @@ 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) + return -ENOMEM; + ++ if (pdata && pdata->init_data) ++ memcpy(chip->buffer, pdata->init_data, chip->registers); ++ + spi_set_drvdata(spi, chip); + + chip->gpio_chip.label = spi->modalias; +@@ -133,7 +147,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; +@@ -170,17 +188,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 +@@ -1154,7 +1154,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.9/452-gpio-add-gpio-latch-driver.patch b/target/linux/ar71xx/patches-4.9/452-gpio-add-gpio-latch-driver.patch new file mode 100644 index 000000000..5ddf6de92 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/452-gpio-add-gpio-latch-driver.patch @@ -0,0 +1,22 @@ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -1218,4 +1218,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 +@@ -56,6 +56,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.9/461-spi-ath79-add-fast-flash-read.patch b/target/linux/ar71xx/patches-4.9/461-spi-ath79-add-fast-flash-read.patch new file mode 100644 index 000000000..0dc73a8b5 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/461-spi-ath79-add-fast-flash-read.patch @@ -0,0 +1,54 @@ +--- 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) +@@ -205,6 +202,33 @@ static u32 ath79_spi_txrx_mode0(struct s + return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS); + } + ++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; ++ ++ if (spi->chip_select || gpio_is_valid(spi->cs_gpio)) ++ 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; +@@ -234,6 +258,7 @@ 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; + + sp->bitbang.master = master; + sp->bitbang.chipselect = ath79_spi_chipselect; diff --git a/target/linux/ar71xx/patches-4.9/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch b/target/linux/ar71xx/patches-4.9/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch new file mode 100644 index 000000000..520c65205 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 __initdata; + static unsigned ath79_pci_nr_irqs __initdata; + ++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[] __initconst = { + { + .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.9/490-usb-ehci-add-quirks-for-qca-socs.patch b/target/linux/ar71xx/patches-4.9/490-usb-ehci-add-quirks-for-qca-socs.patch new file mode 100644 index 000000000..8a05adb05 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -231,6 +231,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 +@@ -52,6 +52,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); +@@ -261,6 +269,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.9/500-MIPS-fw-myloader.patch b/target/linux/ar71xx/patches-4.9/500-MIPS-fw-myloader.patch new file mode 100644 index 000000000..bcb19372e --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/500-MIPS-fw-myloader.patch @@ -0,0 +1,22 @@ +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -213,6 +213,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 +@@ -1144,6 +1144,9 @@ config MIPS_MSC + config MIPS_NILE4 + bool + ++config MYLOADER ++ bool ++ + config SYNC_R4K + bool + diff --git a/target/linux/ar71xx/patches-4.9/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch b/target/linux/ar71xx/patches-4.9/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch new file mode 100644 index 000000000..12ab3b50d --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/504-MIPS-ath79-add-ath79_device_reset_get.patch b/target/linux/ar71xx/patches-4.9/504-MIPS-ath79-add-ath79_device_reset_get.patch new file mode 100644 index 000000000..c0e96b272 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/505-MIPS-ath79-add-ath79_gpio_function_select.patch b/target/linux/ar71xx/patches-4.9/505-MIPS-ath79-add-ath79_gpio_function_select.patch new file mode 100644 index 000000000..278e78153 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/506-MIPS-ath79-prom-parse-redboot-args.patch b/target/linux/ar71xx/patches-4.9/506-MIPS-ath79-prom-parse-redboot-args.patch new file mode 100644 index 000000000..46beeffee --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/507-MIPS-ath79-prom-add-myloader-support.patch b/target/linux/ar71xx/patches-4.9/507-MIPS-ath79-prom-add-myloader-support.patch new file mode 100644 index 000000000..17a97335d --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/508-MIPS-ath79-prom-image-command-line-hack.patch b/target/linux/ar71xx/patches-4.9/508-MIPS-ath79-prom-image-command-line-hack.patch new file mode 100644 index 000000000..cfa5e72ee --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/509-MIPS-ath79-process-board-kernel-option.patch b/target/linux/ar71xx/patches-4.9/509-MIPS-ath79-process-board-kernel-option.patch new file mode 100644 index 000000000..3091ab69b --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/509-MIPS-ath79-process-board-kernel-option.patch @@ -0,0 +1,11 @@ +--- a/arch/mips/ath79/setup.c ++++ b/arch/mips/ath79/setup.c +@@ -283,6 +283,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.9/510-MIPS-ath79-init-gpio-pin-of-wmac-device.patch b/target/linux/ar71xx/patches-4.9/510-MIPS-ath79-init-gpio-pin-of-wmac-device.patch new file mode 100644 index 000000000..2d2235e29 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/520-MIPS-ath79-enable-UART-function.patch b/target/linux/ar71xx/patches-4.9/520-MIPS-ath79-enable-UART-function.patch new file mode 100644 index 000000000..c8649b749 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/521-MIPS-ath79-enable-UART-for-early_serial.patch b/target/linux/ar71xx/patches-4.9/521-MIPS-ath79-enable-UART-for-early_serial.patch new file mode 100644 index 000000000..e546ff26f --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/522-MIPS-ath79-add-ath79_wmac_register_simple-helper.patch b/target/linux/ar71xx/patches-4.9/522-MIPS-ath79-add-ath79_wmac_register_simple-helper.patch new file mode 100644 index 000000000..2d5559cb9 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/523-MIPS-ath79-OTP-support.patch b/target/linux/ar71xx/patches-4.9/523-MIPS-ath79-OTP-support.patch new file mode 100644 index 000000000..d11d418f1 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/524-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch b/target/linux/ar71xx/patches-4.9/524-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch new file mode 100644 index 000000000..91e037e24 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/525-MIPS-ath79-enable-qca-usb-quirks.patch b/target/linux/ar71xx/patches-4.9/525-MIPS-ath79-enable-qca-usb-quirks.patch new file mode 100644 index 000000000..0e33674ad --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 = 0x18116c94; ++ 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.9/601-MIPS-ath79-add-more-register-defines.patch b/target/linux/ar71xx/patches-4.9/601-MIPS-ath79-add-more-register-defines.patch new file mode 100644 index 000000000..d0f5b7890 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/602-MIPS-ath79-add-openwrt-stuff.patch b/target/linux/ar71xx/patches-4.9/602-MIPS-ath79-add-openwrt-stuff.patch new file mode 100644 index 000000000..cbd69e337 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/602-MIPS-ath79-add-openwrt-stuff.patch @@ -0,0 +1,49 @@ +--- a/arch/mips/ath79/Kconfig ++++ b/arch/mips/ath79/Kconfig +@@ -98,6 +98,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 + +@@ -107,6 +121,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 + +@@ -117,4 +135,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.9/603-MIPS-ath79-ap121-fixes.patch b/target/linux/ar71xx/patches-4.9/603-MIPS-ath79-ap121-fixes.patch new file mode 100644 index 000000000..773a858ae --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -5,9 +5,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.9/605-MIPS-ath79-db120-fixes.patch b/target/linux/ar71xx/patches-4.9/605-MIPS-ath79-db120-fixes.patch new file mode 100644 index 000000000..1029d4366 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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", ++ .phy_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 +@@ -42,9 +42,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.9/606-MIPS-ath79-pb44-fixes.patch b/target/linux/ar71xx/patches-4.9/606-MIPS-ath79-pb44-fixes.patch new file mode 100644 index 000000000..f2943d083 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/606-MIPS-ath79-pb44-fixes.patch @@ -0,0 +1,146 @@ +--- a/arch/mips/ath79/mach-pb44.c ++++ b/arch/mips/ath79/mach-pb44.c +@@ -8,23 +8,48 @@ + * by the Free Software Foundation. + */ + ++#include + #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 +112,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 +180,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 +@@ -57,6 +57,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.9/607-MIPS-ath79-ubnt-xm-fixes.patch b/target/linux/ar71xx/patches-4.9/607-MIPS-ath79-ubnt-xm-fixes.patch new file mode 100644 index 000000000..d667215a1 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/607-MIPS-ath79-ubnt-xm-fixes.patch @@ -0,0 +1,14 @@ +--- a/arch/mips/ath79/Kconfig ++++ b/arch/mips/ath79/Kconfig +@@ -69,9 +69,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.9/608-MIPS-ath79-ubnt-xm-add-more-boards.patch b/target/linux/ar71xx/patches-4.9/608-MIPS-ath79-ubnt-xm-add-more-boards.patch new file mode 100644 index 000000000..536c28d1c --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/608-MIPS-ath79-ubnt-xm-add-more-boards.patch @@ -0,0 +1,20 @@ +--- a/arch/mips/ath79/Kconfig ++++ b/arch/mips/ath79/Kconfig +@@ -67,12 +67,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.9/609-MIPS-ath79-ap136-fixes.patch b/target/linux/ar71xx/patches-4.9/609-MIPS-ath79-ap136-fixes.patch new file mode 100644 index 000000000..4d7902e16 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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", ++ .phy_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 +@@ -16,16 +16,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.9/611-MIPS-ath79-wdt-timeout.patch b/target/linux/ar71xx/patches-4.9/611-MIPS-ath79-wdt-timeout.patch new file mode 100644 index 000000000..0927d5a97 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/612-MIPS-ath79-set-buffalo-txgain.patch b/target/linux/ar71xx/patches-4.9/612-MIPS-ath79-set-buffalo-txgain.patch new file mode 100644 index 000000000..3d100e054 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/613-MIPS-ath79-add-ath79_wmac_setup_ext_lna_gpio-helper.patch b/target/linux/ar71xx/patches-4.9/613-MIPS-ath79-add-ath79_wmac_setup_ext_lna_gpio-helper.patch new file mode 100644 index 000000000..5c1205d59 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch b/target/linux/ar71xx/patches-4.9/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch new file mode 100644 index 000000000..869fdd6dd --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch @@ -0,0 +1,705 @@ +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 +@@ -104,6 +104,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 +@@ -143,7 +147,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 +@@ -356,6 +356,91 @@ 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; ++ u32 bootstrap; ++ ++ bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP); ++ if (bootstrap & QCA953X_BOOTSTRAP_REF_CLK_40) ++ ref_rate = 40 * 1000 * 1000; ++ else ++ 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; +@@ -451,6 +536,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,26 @@ static void ar934x_wmac_setup(void) + ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; + } + ++static void qca953x_wmac_setup(void) ++{ ++ u32 t; ++ ++ 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); ++ ++ t = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP); ++ if (t & QCA953X_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 void qca955x_wmac_setup(void) + { + u32 t; +@@ -379,6 +399,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 +@@ -56,6 +56,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; +@@ -143,7 +171,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; + } + +@@ -154,6 +182,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 +@@ -164,6 +193,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_40 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.9/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-4.9/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch new file mode 100644 index 000000000..dafac9919 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch @@ -0,0 +1,717 @@ +--- a/arch/mips/ath79/Kconfig ++++ b/arch/mips/ath79/Kconfig +@@ -113,6 +113,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 +@@ -147,7 +153,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 +@@ -526,6 +526,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()) +@@ -540,6 +634,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 +@@ -200,6 +200,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) + { +@@ -403,6 +423,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 +@@ -156,6 +156,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; +@@ -183,7 +264,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(); +@@ -197,4 +280,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[] __initconst = { ++ { ++ .bus = 0, ++ .slot = 0, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(0), ++ }, ++ { ++ .bus = 1, ++ .slot = 0, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(1), ++ }, ++}; ++ + int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) + { + int irq = -1; +@@ -86,6 +101,9 @@ int __init pcibios_map_irq(const struct + } 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.9/622-MIPS-ath79-add-more-register-defines-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-4.9/622-MIPS-ath79-add-more-register-defines-for-QCA956x-SoC.patch new file mode 100644 index 000000000..cab2f6f9c --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/630-MIPS-ath79-fix-chained-irq-disable.patch b/target/linux/ar71xx/patches-4.9/630-MIPS-ath79-fix-chained-irq-disable.patch new file mode 100644 index 000000000..2b92b88d0 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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; +@@ -50,8 +53,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); + } +@@ -79,7 +81,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); + } +@@ -143,15 +145,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); + } +@@ -222,13 +222,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); + +@@ -237,12 +237,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.9/631-MIPS-ath79-wmac-enable-set-led-pin.patch b/target/linux/ar71xx/patches-4.9/631-MIPS-ath79-wmac-enable-set-led-pin.patch new file mode 100644 index 000000000..29f7f3d0a --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -411,6 +411,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.9/632-MIPS-ath79-gpio-enable-set-direction.patch b/target/linux/ar71xx/patches-4.9/632-MIPS-ath79-gpio-enable-set-direction.patch new file mode 100644 index 000000000..4cf36325e --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/640-MIPS-ath79-add-QCA955x-wmac-reset.patch b/target/linux/ar71xx/patches-4.9/640-MIPS-ath79-add-QCA955x-wmac-reset.patch new file mode 100644 index 000000000..d7f4536ba --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -170,6 +170,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; +@@ -186,6 +207,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.9/700-MIPS-ath79-add-openwrt-Kconfig.patch b/target/linux/ar71xx/patches-4.9/700-MIPS-ath79-add-openwrt-Kconfig.patch new file mode 100644 index 000000000..5d4b18000 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/700-MIPS-ath79-add-openwrt-Kconfig.patch @@ -0,0 +1,11 @@ +--- a/arch/mips/ath79/Kconfig ++++ b/arch/mips/ath79/Kconfig +@@ -82,6 +82,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.9/701-MIPS-ath79-add-routerboard-detection.patch b/target/linux/ar71xx/patches-4.9/701-MIPS-ath79-add-routerboard-detection.patch new file mode 100644 index 000000000..cd91ac3c0 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/701-MIPS-ath79-add-routerboard-detection.patch @@ -0,0 +1,30 @@ +--- a/arch/mips/ath79/prom.c ++++ b/arch/mips/ath79/prom.c +@@ -136,6 +136,27 @@ 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=2011L") || ++ strstr(arcs_cmdline, "board=2011r") || ++ strstr(arcs_cmdline, "board=711Gr100") || ++ 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.9/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch b/target/linux/ar71xx/patches-4.9/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch new file mode 100644 index 000000000..a65f7d993 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/740-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch b/target/linux/ar71xx/patches-4.9/740-MIPS-ath79-add-PCI-for-QCA953x-SoC.patch new file mode 100644 index 000000000..a57351efd --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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[] __initconst = { ++ { ++ .bus = 0, ++ .slot = 0, ++ .pin = 1, ++ .irq = ATH79_PCI_IRQ(0), ++ }, ++}; ++ + static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = { + { + .bus = 0, +@@ -98,6 +107,9 @@ int __init pcibios_map_irq(const struct + 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.9/818-MIPS-ath79-add-nu801-led-driver.patch b/target/linux/ar71xx/patches-4.9/818-MIPS-ath79-add-nu801-led-driver.patch new file mode 100644 index 000000000..337447e2b --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/818-MIPS-ath79-add-nu801-led-driver.patch @@ -0,0 +1,26 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -606,6 +606,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 +@@ -56,6 +56,7 @@ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5 + obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.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.9/820-MIPS-ath79-add_gpio_function2_setup.patch b/target/linux/ar71xx/patches-4.9/820-MIPS-ath79-add_gpio_function2_setup.patch new file mode 100644 index 000000000..afa7b69b4 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/900-mdio_bitbang_ignore_ta_value.patch b/target/linux/ar71xx/patches-4.9/900-mdio_bitbang_ignore_ta_value.patch new file mode 100644 index 000000000..8f8f349a6 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch b/target/linux/ar71xx/patches-4.9/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch new file mode 100644 index 000000000..a830346a3 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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.9/902-at803x-add-reset-gpio-pdata.patch b/target/linux/ar71xx/patches-4.9/902-at803x-add-reset-gpio-pdata.patch new file mode 100644 index 000000000..cb3ed89e9 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/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 +@@ -264,6 +264,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; +@@ -276,6 +277,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); +@@ -407,15 +414,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.9/910-unaligned_access_hacks.patch b/target/linux/ar71xx/patches-4.9/910-unaligned_access_hacks.patch new file mode 100644 index 000000000..21ceca156 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/910-unaligned_access_hacks.patch @@ -0,0 +1,888 @@ +--- 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 +@@ -102,7 +102,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 +@@ -129,7 +129,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 +@@ -54,7 +54,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 +@@ -64,7 +64,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 +@@ -24,7 +24,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 +@@ -41,8 +41,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 +@@ -81,7 +81,7 @@ struct icmphdr { + } frag; + __u8 reserved[4]; + } un; +-}; ++} __attribute__((packed, aligned(2))); + + + /* +--- a/include/uapi/linux/in6.h ++++ b/include/uapi/linux/in6.h +@@ -42,7 +42,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 +@@ -796,10 +797,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 +@@ -5,6 +5,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 +@@ -471,7 +471,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; + } +@@ -814,12 +814,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 +@@ -394,7 +394,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 +@@ -574,7 +574,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 +@@ -231,5 +231,11 @@ typedef void (*call_rcu_func_t)(struct r + /* clocksource cycle base type */ + typedef u64 cycle_t; + ++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 +@@ -1318,8 +1318,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 +@@ -458,7 +458,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 +@@ -448,48 +448,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)) { +@@ -497,16 +502,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; +@@ -519,13 +525,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 +@@ -509,7 +509,7 @@ static struct sk_buff *add_grec(struct s + if (!skb) + return NULL; + psrc = (__be32 *)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 +@@ -32,7 +32,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 +@@ -48,7 +48,7 @@ struct igmpv3_grec { + __be16 grec_nsrcs; + __be32 grec_mca; + __be32 grec_src[0]; +-}; ++} __attribute__((packed, aligned(2))); + + struct igmpv3_report { + __u8 type; +@@ -57,7 +57,7 @@ struct igmpv3_report { + __be16 resv2; + __be16 ngrec; + struct igmpv3_grec grec[0]; +-}; ++} __attribute__((packed, aligned(2))); + + struct igmpv3_query { + __u8 type; +@@ -78,7 +78,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 +@@ -84,7 +84,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 +@@ -76,7 +76,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 +@@ -87,7 +87,7 @@ struct ra_msg { + struct icmp6hdr icmph; + __be32 reachable_time; + __be32 retrans_timer; +-}; ++} __attribute__((packed, aligned(2))); + + struct rd_msg { + struct icmp6hdr icmph; +@@ -365,10 +365,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 +@@ -159,7 +159,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; + } +@@ -212,8 +212,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 +@@ -220,7 +220,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 +@@ -46,7 +46,7 @@ struct prefix_info { + __be32 reserved2; + + struct in6_addr prefix; +-}; ++} __attribute__((packed, aligned(2))); + + + #include +--- a/include/net/inet_ecn.h ++++ b/include/net/inet_ecn.h +@@ -124,9 +124,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); +@@ -135,7 +135,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 +@@ -107,7 +107,7 @@ struct frag_hdr { + __u8 reserved; + __be16 frag_off; + __be32 identification; +-}; ++} __attribute__((packed, aligned(2))); + + #define IP6_MF 0x0001 + #define IP6_OFFSET 0xFFF8 +@@ -449,8 +449,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, +@@ -509,6 +509,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; +@@ -517,7 +519,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; +@@ -661,13 +665,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)); + } +@@ -836,17 +840,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 +@@ -2,6 +2,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 +@@ -83,7 +83,7 @@ enum { + /* Internet address. */ + struct in_addr { + __be32 s_addr; +-}; ++} __attribute__((packed, aligned(2))); + #endif + + #define IP_TOS 1 +--- a/net/core/secure_seq.c ++++ b/net/core/secure_seq.c +@@ -46,11 +46,12 @@ __u32 secure_tcpv6_sequence_number(const + u32 secret[MD5_MESSAGE_BYTES / 4]; + u32 hash[MD5_DIGEST_WORDS]; + u32 i; ++ const struct in6_addr *daddr6 = (struct in6_addr *) daddr; + + net_secret_init(); + memcpy(hash, saddr, 16); + for (i = 0; i < 4; i++) +- secret[i] = net_secret[i] + (__force u32)daddr[i]; ++ secret[i] = net_secret[i] + (__force u32)daddr6->s6_addr32[i]; + secret[4] = net_secret[4] + + (((__force u16)sport << 16) + (__force u16)dport); + for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) +@@ -68,11 +69,12 @@ u32 secure_ipv6_port_ephemeral(const __b + u32 secret[MD5_MESSAGE_BYTES / 4]; + u32 hash[MD5_DIGEST_WORDS]; + u32 i; ++ const struct in6_addr *daddr6 = (struct in6_addr *) daddr; + + net_secret_init(); + memcpy(hash, saddr, 16); + for (i = 0; i < 4; i++) +- secret[i] = net_secret[i] + (__force u32) daddr[i]; ++ secret[i] = net_secret[i] + (__force u32) daddr6->s6_addr32[i]; + secret[4] = net_secret[4] + (__force u32)dport; + for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) + secret[i] = net_secret[i]; +@@ -146,6 +148,7 @@ EXPORT_SYMBOL(secure_dccp_sequence_numbe + u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport) + { ++ const struct in6_addr *daddr6 = (struct in6_addr *) daddr; + u32 secret[MD5_MESSAGE_BYTES / 4]; + u32 hash[MD5_DIGEST_WORDS]; + u64 seq; +@@ -154,7 +157,7 @@ u64 secure_dccpv6_sequence_number(__be32 + net_secret_init(); + memcpy(hash, saddr, 16); + for (i = 0; i < 4; i++) +- secret[i] = net_secret[i] + (__force u32)daddr[i]; ++ secret[i] = net_secret[i] + (__force u32)daddr6->s6_addr32[i]; + secret[4] = net_secret[4] + + (((__force u16)sport << 16) + (__force u16)dport); + for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -136,7 +136,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 +@@ -452,7 +452,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 +@@ -154,8 +154,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; + } + +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3886,14 +3886,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 +@@ -50,6 +50,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 +@@ -263,8 +263,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 +@@ -69,7 +69,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 +@@ -321,8 +321,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), diff --git a/target/linux/ar71xx/patches-4.9/920-usb-chipidea-AR933x-platform-support.patch b/target/linux/ar71xx/patches-4.9/920-usb-chipidea-AR933x-platform-support.patch new file mode 100644 index 000000000..740ffec4a --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/920-usb-chipidea-AR933x-platform-support.patch @@ -0,0 +1,123 @@ +--- 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,67 @@ static void __init ar913x_usb_setup(void + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); + } + ++static void __init ar933x_usb_setup_ctrl_config(void) ++{ ++ void __iomem *usb_ctrl_base, *usb_config_reg; ++ u32 usb_config; ++ ++ usb_ctrl_base = ioremap(AR71XX_USB_CTRL_BASE, AR71XX_USB_CTRL_SIZE); ++ usb_config_reg = usb_ctrl_base + AR71XX_USB_CTRL_REG_CONFIG; ++ usb_config = __raw_readl(usb_config_reg); ++ usb_config &= ~AR933X_USB_CONFIG_HOST_ONLY; ++ __raw_writel(usb_config, usb_config_reg); ++ iounmap(usb_ctrl_base); ++} ++ ++static void __init ar9xxx_ci_usb_setup(void) ++{ ++ struct ci_hdrc_platform_data ci_pdata; ++ enum usb_dr_mode dr_mode; ++ bool host_mode = true; ++ ++ if (soc_is_ar933x()) ++ host_mode = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP) & ++ AR933X_BOOTSTRAP_USB_MODE_HOST; ++ else if (soc_is_ar934x() || soc_is_qca955x()) ++ host_mode = !(ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP) & ++ AR934X_BOOTSTRAP_USB_MODE_DEVICE); ++ ++ if (host_mode) { ++ dr_mode = USB_DR_MODE_HOST; ++ } else { ++ dr_mode = USB_DR_MODE_PERIPHERAL; ++ if (soc_is_ar933x()) ++ ar933x_usb_setup_ctrl_config(); ++ } ++ ++ memset(&ci_pdata, 0, sizeof(ci_pdata)); ++ ci_pdata.name = "ci_hdrc_ar9xxx"; ++ ci_pdata.capoffset = DEF_CAPOFFSET; ++ ci_pdata.dr_mode = dr_mode; ++ 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, ++ AR933X_EHCI_BASE, AR933X_EHCI_SIZE, ++ ATH79_CPU_IRQ(3), ++ &ci_pdata, sizeof(ci_pdata)); ++ ++ if (!host_mode) ++ return; ++ ++ 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 __init ar933x_usb_setup(void) + { + ath79_device_reset_set(AR933X_RESET_USBSUS_OVERRIDE); +@@ -181,10 +245,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(); + } + + static void enable_tx_tx_idp_violation_fix(unsigned base) +@@ -230,10 +291,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(); + } + + static void __init qca953x_usb_setup(void) diff --git a/target/linux/ar71xx/patches-4.9/930-chipidea-pullup.patch b/target/linux/ar71xx/patches-4.9/930-chipidea-pullup.patch new file mode 100644 index 000000000..ce31595d9 --- /dev/null +++ b/target/linux/ar71xx/patches-4.9/930-chipidea-pullup.patch @@ -0,0 +1,72 @@ +--- a/drivers/usb/chipidea/ci.h ++++ b/drivers/usb/chipidea/ci.h +@@ -199,6 +199,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; +@@ -248,6 +249,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 +@@ -839,7 +839,7 @@ static inline void ci_role_destroy(struc + { + ci_hdrc_gadget_destroy(ci); + ci_hdrc_host_destroy(ci); +- if (ci->is_otg) ++ if (!ci->dp_always_pullup && ci->roles[CI_ROLE_GADGET]) + ci_hdrc_otg_destroy(ci); + } + +@@ -890,6 +890,9 @@ static int ci_hdrc_probe(struct platform + ci->supports_runtime_pm = !!(ci->platdata->flags & + CI_HDRC_SUPPORTS_RUNTIME_PM); + ++ 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"); +@@ -955,7 +958,7 @@ static int ci_hdrc_probe(struct platform + goto deinit_phy; + } + +- 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 +@@ -57,6 +57,7 @@ struct ci_hdrc_platform_data { + #define CI_HDRC_OVERRIDE_AHB_BURST BIT(9) + #define CI_HDRC_OVERRIDE_TX_BURST BIT(10) + #define CI_HDRC_OVERRIDE_RX_BURST BIT(11) ++#define CI_HDRC_DP_ALWAYS_PULLUP BIT(12) + enum usb_dr_mode dr_mode; + #define CI_HDRC_CONTROLLER_RESET_EVENT 0 + #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 From 3fb9fdf5cdcbadf8cbf9f3fe303c52f409d7a8b4 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Fri, 13 Oct 2017 01:24:22 +0800 Subject: [PATCH 02/15] enable MIPS_FPU_EMULATOR for AR71xx to run frp and kcptun etc --- target/linux/ar71xx/config-4.9 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/ar71xx/config-4.9 b/target/linux/ar71xx/config-4.9 index c5b89088f..0bd20e7b6 100644 --- a/target/linux/ar71xx/config-4.9 +++ b/target/linux/ar71xx/config-4.9 @@ -378,6 +378,7 @@ CONFIG_MIPS_CLOCK_VSYSCALL=y CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER=y # CONFIG_MIPS_CMDLINE_FROM_DTB is not set # CONFIG_MIPS_ELF_APPENDED_DTB is not set +CONFIG_MIPS_FPU_EMULATOR=y # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set CONFIG_MIPS_L1_CACHE_SHIFT=5 CONFIG_MIPS_MACHINE=y From fe825bbce62baf0cafbe042ac502e93befc544fc Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Fri, 13 Oct 2017 21:56:58 +0800 Subject: [PATCH 03/15] update luci-app-kcptun to 1.4.3 --- package/lean/luci-app-kcptun/LICENSE | 202 +++++++++++++++++++++++++ package/lean/luci-app-kcptun/Makefile | 2 +- package/lean/luci-app-kcptun/README.md | 64 ++++++++ 3 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 package/lean/luci-app-kcptun/LICENSE create mode 100644 package/lean/luci-app-kcptun/README.md diff --git a/package/lean/luci-app-kcptun/LICENSE b/package/lean/luci-app-kcptun/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/package/lean/luci-app-kcptun/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/package/lean/luci-app-kcptun/Makefile b/package/lean/luci-app-kcptun/Makefile index fcdc65d47..c569e5c94 100644 --- a/package/lean/luci-app-kcptun/Makefile +++ b/package/lean/luci-app-kcptun/Makefile @@ -20,7 +20,7 @@ define Package/$(PKG_NAME)/conffiles /etc/config/kcptun endef -include $(TOPDIR)/feeds/luci/luci.mk +include $(TOPDIR)/feeds/luci.mk define Package/$(PKG_NAME)/postinst #!/bin/sh diff --git a/package/lean/luci-app-kcptun/README.md b/package/lean/luci-app-kcptun/README.md new file mode 100644 index 000000000..ad819f336 --- /dev/null +++ b/package/lean/luci-app-kcptun/README.md @@ -0,0 +1,64 @@ +# luci-app-kcptun + +Luci support for kcptun + +OpenWrt/LEDE 上的 Kcptun Luci 支持界面 + +[![Release Version](https://img.shields.io/github/release/kuoruan/luci-app-kcptun.svg)](https://github.com/kuoruan/luci-app-kcptun/releases/latest) [![Latest Release Download](https://img.shields.io/github/downloads/kuoruan/luci-app-kcptun/latest/total.svg)](https://github.com/kuoruan/luci-app-kcptun/releases/latest) + +## 编译说明 + +由于目录结构原因,无法使用 OpenWrt/LEDE 的 SDK 直接编译。 + +需要下载 OpenWrt/LEDE 的完整源码 https://github.com/lede-project/source +并将 luci-app-kcptun 放入 ```feeds/luci/applications/``` 目录下。 + +``` +cd openwrt +git clone https://github.com/kuoruan/luci-app-kcptun.git feeds/luci/applications/luci-app-kcptun +rm -rf tmp/ + +./scripts/feeds update luci +./scripts/feeds install luci + +make menuconfig +make package/luci-app-kcptun/{clean,compile} V=s +``` + +如果需要在 SDK 上编译,需要自行修改目录结构。参考:https://github.com/shadowsocks/luci-app-shadowsocks + +## 安装说明 + +1. 到 [release](https://github.com/kuoruan/luci-app-kcptun/releases) 页面下载最新版 luci-app-kcptun 和 luci-i18n-kcptun-zh-cn (简体中文翻译文件) +2. 将下载好的 ipk 文件上传到路由器任意目录下, 如 /tmp +3. 先安装 luci-app-kcptun 再安装 luci-i18n-kcptun-zh-cn + +``` +opkg install luci-app-kcptun_*.ipk +opkg install luci-i18n-kcptun-zh-cn_*.ipk +``` + +安装好 LuCI 之后,进入配置页面,会提示 ```客户端文件配置有误```。 + +若路由器上已经有 Kcptun 客户端,直接配置好路径即可,如果当前还没有客户端文件,可以使用以下操作: + +1. 配置好 ```客户端文件``` 路径(可选,默认路径 ```/var/kcptun_client```),确保客户端文件所在目录的剩余空间足以放下两个客户端文件; +2. 根据当前设备,配置好 ```CPU 架构```(可选); +3. 如果你的路由器上装有透明代理软件,最好先打开; +4. 点击 ```检查 Kcptun```,正常情况下应该会获取到 Kcptun 最新版本号; +5. ```点击更新``` 按钮来自动下载配置客户端文件。 + +如果自动下载更新失败,请手动下载 Kcptun 客户端文件并上传到路由器上,然后配置好 ```客户端文件``` 路径。 + +下载地址: https://github.com/xtaci/kcptun/releases + +注:Golang 的 MIPS/MIPSLE 版本暂时不支持 Soft Float,需要在编译 OpenWrt/LEDE 时打开 ```MIPS FPU Emulator```,其他版本不受影响。 + +## 卸载说明 + +卸载时需要先卸载 luci-i18n-kcptun-zh-cn, 再卸载 luci-app-kcptun + +``` +opkg remove luci-i18n-kcptun-zh-cn +opkg remove luci-app-kcptun +``` From b29e9ad9792c68a9a59bd5b9be73d9d9fc5f35b0 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Fri, 13 Oct 2017 22:25:22 +0800 Subject: [PATCH 04/15] update dnsmasq to 2.78 for CVE fix --- package/network/services/dnsmasq/Makefile | 24 +- .../services/dnsmasq/files/dhcp-script.sh | 46 ++ .../network/services/dnsmasq/files/dhcp.conf | 2 +- .../services/dnsmasq/files/dnsmasq.init | 428 ++++++++++++++---- .../services/dnsmasq/files/dnsmasq_acl.json | 4 + .../services/dnsmasq/files/dnsmasqsec.hotplug | 6 +- .../services/dnsmasq/files/rfc6761.conf | 15 + .../100-fix-dhcp-no-address-warning.patch | 47 -- .../110-ipset-remove-old-kernel-support.patch | 69 +-- ...20-dnsmasq-compile-time-option-NO_ID.patch | 149 ------ ...0-dnssec-improve-timestamp-heuristic.patch | 12 +- ...0-fix-poll-h-include-warning-on-musl.patch | 2 +- .../services/dnsmasq/patches/240-ubus.patch | 126 ++++++ 13 files changed, 574 insertions(+), 356 deletions(-) create mode 100755 package/network/services/dnsmasq/files/dhcp-script.sh create mode 100644 package/network/services/dnsmasq/files/dnsmasq_acl.json create mode 100644 package/network/services/dnsmasq/files/rfc6761.conf delete mode 100644 package/network/services/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch delete mode 100644 package/network/services/dnsmasq/patches/120-dnsmasq-compile-time-option-NO_ID.patch create mode 100644 package/network/services/dnsmasq/patches/240-ubus.patch diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index 29079795c..33644e8e5 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq -PKG_VERSION:=2.76 -PKG_RELEASE:=12 +PKG_VERSION:=2.78 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq -PKG_MD5SUM:=00f5ee66b4e4b7f14538bf62ae3c9461 +PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/ +PKG_HASH:=89949f438c74b0c7543f06689c319484bd126cc4b1f8c745c742ab397681252b PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING @@ -37,6 +37,7 @@ define Package/dnsmasq/Default CATEGORY:=Base system TITLE:=DNS and DHCP server URL:=http://www.thekelleys.org.uk/dnsmasq/ + DEPENDS:=+libubus USERID:=dnsmasq=453:dnsmasq=453 endef @@ -48,14 +49,14 @@ endef define Package/dnsmasq-dhcpv6 $(call Package/dnsmasq/Default) TITLE += (with DHCPv6 support) - DEPENDS:=@IPV6 + DEPENDS+=@IPV6 VARIANT:=dhcpv6 endef define Package/dnsmasq-full $(call Package/dnsmasq/Default) TITLE += (with DNSSEC, DHCPv6, Auth DNS, IPset, Conntrack, NO_ID enabled by default) - DEPENDS:=+PACKAGE_dnsmasq_full_dnssec:libnettle \ + DEPENDS+=+PACKAGE_dnsmasq_full_dnssec:libnettle \ +PACKAGE_dnsmasq_full_ipset:kmod-ipt-ipset \ +PACKAGE_dnsmasq_full_conntrack:libnetfilter-conntrack VARIANT:=full @@ -137,7 +138,7 @@ endif MAKE_FLAGS := \ $(TARGET_CONFIGURE_OPTS) \ - CFLAGS="$(TARGET_CFLAGS)" \ + CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \ LDFLAGS="$(TARGET_LDFLAGS)" \ COPTS="$(COPTS)" \ PREFIX="/usr" @@ -150,8 +151,17 @@ define Package/dnsmasq/install $(INSTALL_DATA) ./files/dnsmasq.conf $(1)/etc/dnsmasq.conf $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/dnsmasq.init $(1)/etc/init.d/dnsmasq + $(INSTALL_DIR) $(1)/etc/hotplug.d/dhcp + $(INSTALL_DIR) $(1)/etc/hotplug.d/neigh $(INSTALL_DIR) $(1)/etc/hotplug.d/ntp + $(INSTALL_DIR) $(1)/etc/hotplug.d/tftp $(INSTALL_DATA) ./files/dnsmasqsec.hotplug $(1)/etc/hotplug.d/ntp/25-dnsmasqsec + $(INSTALL_DIR) $(1)/usr/share/dnsmasq + $(INSTALL_DATA) ./files/rfc6761.conf $(1)/usr/share/dnsmasq/ + $(INSTALL_DIR) $(1)/usr/lib/dnsmasq + $(INSTALL_BIN) ./files/dhcp-script.sh $(1)/usr/lib/dnsmasq/dhcp-script.sh + $(INSTALL_DIR) $(1)/usr/share/acl.d + $(INSTALL_DATA) ./files/dnsmasq_acl.json $(1)/usr/share/acl.d/ endef Package/dnsmasq-dhcpv6/install = $(Package/dnsmasq/install) diff --git a/package/network/services/dnsmasq/files/dhcp-script.sh b/package/network/services/dnsmasq/files/dhcp-script.sh new file mode 100755 index 000000000..86032694c --- /dev/null +++ b/package/network/services/dnsmasq/files/dhcp-script.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +[ -f "$USER_DHCPSCRIPT" ] && . "$USER_DHCPSCRIPT" "$@" + +case "$1" in + add) + export ACTION="add" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp + ;; + del) + export ACTION="remove" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp + ;; + old) + export ACTION="update" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp + ;; + arp-add) + export ACTION="add" + export MACADDR="$2" + export IPADDR="$3" + exec /sbin/hotplug-call neigh + ;; + arp-del) + export ACTION="remove" + export MACADDR="$2" + export IPADDR="$3" + exec /sbin/hotplug-call neigh + ;; + tftp) + export ACTION="add" + export TFTP_SIZE="$2" + export TFTP_ADDR="$3" + export TFTP_PATH="$4" + exec /sbin/hotplug-call tftp + ;; +esac diff --git a/package/network/services/dnsmasq/files/dhcp.conf b/package/network/services/dnsmasq/files/dhcp.conf index 362b90a29..360c7d79e 100644 --- a/package/network/services/dnsmasq/files/dhcp.conf +++ b/package/network/services/dnsmasq/files/dhcp.conf @@ -15,7 +15,7 @@ config dnsmasq option leasefile '/tmp/dhcp.leases' option resolvfile '/tmp/resolv.conf.auto' #list server '/mycompany.local/1.2.3.4' - #option nonwildcard 1 + option nonwildcard 1 # bind to & keep track of interfaces #list interface br-lan #list notinterface lo #list bogusnxdomain '64.94.110.11' diff --git a/package/network/services/dnsmasq/files/dnsmasq.init b/package/network/services/dnsmasq/files/dnsmasq.init index b1f9e2e29..014964395 100644 --- a/package/network/services/dnsmasq/files/dnsmasq.init +++ b/package/network/services/dnsmasq/files/dnsmasq.init @@ -8,6 +8,8 @@ PROG=/usr/sbin/dnsmasq ADD_LOCAL_DOMAIN=1 ADD_LOCAL_HOSTNAME=1 +ADD_WAN_FQDN=0 +ADD_LOCAL_FQDN="" BASECONFIGFILE="/var/etc/dnsmasq.conf" BASEHOSTFILE="/tmp/hosts/dhcp" @@ -15,6 +17,10 @@ BASETIMESTAMPFILE="/etc/dnsmasq.time" TRUSTANCHORSFILE="/usr/share/dnsmasq/trust-anchors.conf" TIMEVALIDFILE="/var/state/dnsmasqsec" BASEDHCPSTAMPFILE="/var/run/dnsmasq" +RFC6761FILE="/usr/share/dnsmasq/rfc6761.conf" +DHCPSCRIPT="/usr/lib/dnsmasq/dhcp-script.sh" + +DNSMASQ_DHCP_VER=4 xappend() { local value="$1" @@ -23,22 +29,22 @@ xappend() { } hex_to_hostid() { - local var="$1" - local hex="${2#0x}" # strip optional "0x" prefix + local var="$1" + local hex="${2#0x}" # strip optional "0x" prefix - if [ -n "${hex//[0-9a-fA-F]/}" ]; then - # is invalid hex literal - return 1 - fi + if [ -n "${hex//[0-9a-fA-F]/}" ]; then + # is invalid hex literal + return 1 + fi - # convert into host id - export "$var=$( - printf "%0x:%0x" \ - $(((0x$hex >> 16) % 65536)) \ - $(( 0x$hex % 256)) - )" + # convert into host id + export "$var=$( + printf "%0x:%0x" \ + $(((0x$hex >> 16) % 65536)) \ + $(( 0x$hex % 65536)) + )" - return 0 + return 0 } dhcp_calc() { @@ -83,12 +89,24 @@ log_once() { logger -t dnsmasq "$@" } +has_handler() { + local file + + for file in /etc/hotplug.d/dhcp/* /etc/hotplug.d/tftp/* /etc/hotplug.d/neigh/*; do + [ -f "$file" ] && return 0 + done + + return 1 +} + append_bool() { local section="$1" local option="$2" local value="$3" + local default="$4" local _loctmp - config_get_bool _loctmp "$section" "$option" 0 + [ -z "$default" ] && default="0" + config_get_bool _loctmp "$section" "$option" "$default" [ $_loctmp -gt 0 ] && xappend "$value" } @@ -107,6 +125,10 @@ append_server() { xappend "--server=$1" } +append_rev_server() { + xappend "--rev-server=$1" +} + append_address() { xappend "--address=$1" } @@ -116,12 +138,12 @@ append_ipset() { } append_interface() { - network_get_device ifname "$1" || return + network_get_device ifname "$1" || ifname="$1" xappend "--interface=$ifname" } append_notinterface() { - network_get_device ifname "$1" || return + network_get_device ifname "$1" || ifname="$1" xappend "--except-interface=$ifname" } @@ -137,6 +159,10 @@ append_pxe_service() { xappend "--pxe-service=$1" } +append_interface_name() { + xappend "--interface-name=$1,$2" +} + filter_dnsmasq() { local cfg="$1" func="$2" match_cfg="$3" found_cfg @@ -180,6 +206,7 @@ dhcp_remoteid_add() { } dhcp_circuitid_add() { + # TODO: DHCPV6 does not have circuitid; catch "option6:" local cfg="$1" config_get networkid "$cfg" networkid @@ -212,6 +239,7 @@ dhcp_userclass_add() { } dhcp_vendorclass_add() { + # TODO: DHCPV6 vendor class has stricter definitions; catch? fixup? local cfg="$1" config_get networkid "$cfg" networkid @@ -245,6 +273,7 @@ dhcp_match_add() { dhcp_host_add() { local cfg="$1" + local hosttag nametime addrs duids config_get_bool force "$cfg" force 0 @@ -256,7 +285,9 @@ dhcp_host_add() { config_get name "$cfg" name config_get ip "$cfg" ip - [ -n "$ip" -o -n "$name" ] || return 0 + config_get hostid "$cfg" hostid + + [ -n "$ip" -o -n "$name" -o -n "$hostid" ] || return 0 config_get_bool dns "$cfg" dns 0 [ "$dns" = "1" -a -n "$ip" -a -n "$name" ] && { @@ -264,35 +295,105 @@ dhcp_host_add() { } config_get mac "$cfg" mac + config_get duid "$cfg" duid + config_get tag "$cfg" tag + if [ -n "$mac" ]; then # --dhcp-host=00:20:e0:3b:13:af,192.168.0.199,lap + # many MAC are possible to track a laptop ON/OFF dock macs="" for m in $mac; do append macs "$m" ","; done - else - # --dhcp-host=lap,192.168.0.199 + fi + + if [ $DNSMASQ_DHCP_VER -eq 6 -a -n "$duid" ]; then + # --dhcp-host=id:00:03:00:01:12:00:00:01:02:03,[::beef],lap + # one (virtual) machine gets one DUID per RFC3315 + duids="id:${duid// */}" + fi + + if [ -z "$macs" -a -z "$duids" ]; then + # --dhcp-host=lap,192.168.0.199,[::beef] [ -n "$name" ] || return 0 macs="$name" name="" fi - config_get tag "$cfg" tag + if [ -n "$hostid" ]; then + hex_to_hostid hostid "$hostid" + fi - if [ "$DHCPv6CAPABLE" -eq 1 ]; then - config_get hostid "$cfg" hostid - if [ -n "$hostid" ]; then - hex_to_hostid hostid "$hostid" - fi + tags="" + if [ -n "$tag" ]; then + for t in $tag; do append tags "$t" ",set:"; done fi config_get_bool broadcast "$cfg" broadcast 0 - [ "$broadcast" = "0" ] && broadcast= - config_get leasetime "$cfg" leasetime - xappend "--dhcp-host=$macs${networkid:+,net:$networkid}${broadcast:+,set:needs-broadcast}${tag:+,set:$tag}${ip:+,$ip${hostid:+,[::$hostid]}}${name:+,$name}${leasetime:+,$leasetime}" + [ "$broadcast" = "0" ] && broadcast= || broadcast=",set:needs-broadcast" + + hosttag="${networkid:+,set:${networkid}}${tags:+,set:${tags}}$broadcast" + nametime="${name:+,$name}${leasetime:+,$leasetime}" + + if [ $DNSMASQ_DHCP_VER -eq 6 ]; then + addrs="${ip:+,$ip}${hostid:+,[::$hostid]}" + xappend "--dhcp-host=$macs${duids:+,$duids}$hosttag$addrs$nametime" + else + xappend "--dhcp-host=$macs$hosttag${ip:+,$ip}$nametime" + fi +} + +dhcp_this_host_add() { + local net="$1" + local ifname="$2" + local mode="$3" + local routerstub routername ifdashname + local lanaddr lanaddr6 lanaddrs6 ulaprefix + + if [ "$mode" -gt 0 ] ; then + ifdashname="${ifname//./-}" + routerstub="$( md5sum /etc/os-release )" + routerstub="router-${routerstub// */}" + routername="$( uci_get system @system[0] hostname $routerstub )" + + if [ "$mode" -gt 1 ] ; then + if [ "$mode" -gt 2 ] ; then + if [ "$mode" -gt 3 ] ; then + append_interface_name "$ifdashname.$routername.$DOMAIN" "$ifname" + fi + + append_interface_name "$routername.$DOMAIN" "$ifname" + fi + + # All IP addresses discovered by dnsmasq will be labeled (except fe80::) + append_interface_name "$routername" "$ifname" + + else + # This uses a static host file entry for only limited addresses. + # Use dnsmasq option "--expandhosts" to enable FQDN on host files. + ulaprefix="$(uci_get network @globals[0] ula_prefix)" + network_get_ipaddr lanaddr "$net" + network_get_ipaddrs6 lanaddrs6 "$net" + + if [ -n "$lanaddr" ] ; then + dhcp_domain_add "" "$routername" "$lanaddr" + fi + + if [ -n "$ulaprefix" -a -n "$lanaddrs6" ] ; then + for lanaddr6 in $lanaddrs6 ; do + case "$lanaddr6" in + "${ulaprefix%%:/*}"*) + dhcp_domain_add "" "$routername" "$lanaddr6" + ;; + esac + done + fi + fi + fi } dhcp_tag_add() { + # NOTE: dnsmasq has explicit "option6:" prefix for DHCPv6 so no collisions local cfg="$1" tag="$cfg" @@ -323,6 +424,7 @@ dhcp_mac_add() { } dhcp_boot_add() { + # TODO: BOOTURL is different between DHCPv4 and DHCPv6 local cfg="$1" config_get networkid "$cfg" networkid @@ -345,24 +447,30 @@ dhcp_boot_add() { dhcp_add() { local cfg="$1" + local dhcp6range="::" + local nettag + local tags + config_get net "$cfg" interface [ -n "$net" ] || return 0 - config_get dhcpv4 "$cfg" dhcpv4 - [ "$dhcpv4" != "disabled" ] || return 0 - config_get networkid "$cfg" networkid [ -n "$networkid" ] || networkid="$net" - network_get_subnet subnet "$net" || return 0 network_get_device ifname "$net" || return 0 - network_get_protocol proto "$net" || return 0 [ "$cachelocal" = "0" ] && network_get_dnsserver dnsserver "$net" && { DNS_SERVERS="$DNS_SERVERS $dnsserver" } - append_bool "$cfg" ignore "--no-dhcp-interface=$ifname" && return 0 + append_bool "$cfg" ignore "--no-dhcp-interface=$ifname" && { + # Many ISP do not have useful names for DHCP customers (your WAN). + dhcp_this_host_add "$net" "$ifname" "$ADD_WAN_FQDN" + return 0 + } + + network_get_subnet subnet "$net" || return 0 + network_get_protocol proto "$net" || return 0 # Do not support non-static interfaces for now [ static = "$proto" ] || return 0 @@ -374,35 +482,142 @@ dhcp_add() { config_get_bool force "$cfg" force 0 [ $force -gt 0 ] || dhcp_check "$ifname" || return 0 - config_get start "$cfg" start - config_get limit "$cfg" limit - config_get leasetime "$cfg" leasetime + config_get start "$cfg" start 100 + config_get limit "$cfg" limit 150 + config_get leasetime "$cfg" leasetime 12h config_get options "$cfg" options config_get_bool dynamicdhcp "$cfg" dynamicdhcp 1 - leasetime="${leasetime:-12h}" - start="$(dhcp_calc "${start:-100}")" - limit="${limit:-150}" - [ "$limit" -gt 0 ] && limit=$((limit-1)) - eval "$(ipcalc.sh "${subnet%%/*}" $netmask $start $limit)" - if [ "$dynamicdhcp" = "0" ]; then END="static"; fi - xappend "--dhcp-range=$networkid,$START,$END,$NETMASK,$leasetime${options:+ $options}" + config_get dhcpv4 "$cfg" dhcpv4 + config_get dhcpv6 "$cfg" dhcpv6 - dhcp_option_add "$cfg" "$networkid" + config_get ra "$cfg" ra + config_get ra_management "$cfg" ra_management + config_get ra_preference "$cfg" ra_preference + config_get dns "$cfg" dns + + config_list_foreach "$cfg" "interface_name" append_interface_name "$ifname" + + # Put the router host name on this DHCP served interface address(es) + dhcp_this_host_add "$net" "$ifname" "$ADD_LOCAL_FQDN" + + start="$( dhcp_calc "$start" )" + + add_tag() { + tags="${tags}tag:$1," + } + config_list_foreach "$cfg" tag add_tag + + nettag="${networkid:+set:${networkid},}" + + if [ "$limit" -gt 0 ] ; then + limit=$((limit-1)) + fi + + eval "$(ipcalc.sh "${subnet%%/*}" $netmask $start $limit)" + + if [ "$dynamicdhcp" = "0" ] ; then + END="static" + dhcp6range="::,static" + else + dhcp6range="::1000,::ffff" + fi + + + if [ "$dhcpv4" != "disabled" ] ; then + xappend "--dhcp-range=$tags$nettag$START,$END,$NETMASK,$leasetime${options:+ $options}" + fi + + + if [ $DNSMASQ_DHCP_VER -eq 6 -a "$ra" = "server" ] ; then + # Note: dnsmasq cannot just be a DHCPv6 server (all-in-1) + # and let some other machine(s) send RA pointing to it. + + case $ra_preference in + *high*) + xappend "--ra-param=$ifname,high,0,7200" + ;; + *low*) + xappend "--ra-param=$ifname,low,0,7200" + ;; + *) + # Send UNSOLICITED RA at default interval and live for 2 hours. + # TODO: convert flexible lease time into route life time (only seconds). + xappend "--ra-param=$ifname,0,7200" + ;; + esac + + if [ "$dhcpv6" = "disabled" ] ; then + ra_management="3" + fi + + + case $ra_management in + 0) + # SLACC with DCHP for extended options + xappend "--dhcp-range=$nettag::,constructor:$ifname,ra-stateless,ra-names" + ;; + 2) + # DHCP address and RA only for management redirection + xappend "--dhcp-range=$nettag$dhcp6range,constructor:$ifname,$leasetime" + ;; + 3) + # SLAAC only but dnsmasq attempts to link HOSTNAME, DHCPv4 MAC, and SLAAC + xappend "--dhcp-range=$nettag::,constructor:$ifname,ra-only,ra-names" + ;; + *) + # SLAAC and full DHCP + xappend "--dhcp-range=$nettag$dhcp6range,constructor:$ifname,slaac,ra-names,$leasetime" + ;; + esac + + if [ -n "$dns" ]; then + dnss="" + for d in $dns; do append dnss "[$d]" ","; done + else + dnss="[::]" + fi + + dhcp_option_append "option6:dns-server,$dnss" "$networkid" + fi + + dhcp_option_add "$cfg" "$networkid" 0 + dhcp_option_add "$cfg" "$networkid" 2 } -dhcp_option_add() { - local cfg="$1" +dhcp_option_append() { + local option="$1" local networkid="$2" local force="$3" + xappend "--dhcp-option${force:+-force}=${networkid:+$networkid,}$option" +} + +dhcp_option_add() { + # NOTE: dnsmasq has explicit "option6:" prefix for DHCPv6 so no collisions + local cfg="$1" + local networkid="$2" + local force="$3" + local opt="dhcp_option" + [ "$force" = "0" ] && force= + [ "$force" = "2" ] && opt="dhcp_option_force" - config_get dhcp_option "$cfg" dhcp_option - for o in $dhcp_option; do - xappend "--dhcp-option${force:+-force}=${networkid:+$networkid,}$o" - done + local list_len + config_get list_len "$cfg" "${opt}_LENGTH" + if [ -n "$list_len" ]; then + config_list_foreach "$cfg" "$opt" dhcp_option_append "$networkid" "$force" + else + config_get dhcp_option "$cfg" "$opt" + + [ -n "$dhcp_option" ] && echo "Warning: the 'option $opt' syntax is deprecated, use 'list $opt'" >&2 + + local option + for option in $dhcp_option; do + dhcp_option_append "$option" "$networkid" "$force" + done + fi } dhcp_domain_add() { @@ -507,13 +722,14 @@ dhcp_relay_add() { if [ -z "$interface" ]; then xappend "--dhcp-relay=$local_addr,$server_addr" else - xappend "--dhcp-relay=$local_addr,$server_addr,$interface" + network_get_device ifname "$interface" || return + xappend "--dhcp-relay=$local_addr,$server_addr,$ifname" fi } dnsmasq_start() { - local cfg="$1" disabled + local cfg="$1" disabled resolvfile user_dhcpscript config_get_bool disabled "$cfg" disabled 0 [ "$disabled" -gt 0 ] && return 0 @@ -546,6 +762,41 @@ dnsmasq_start() $PROG --version | grep -osqE "^Compile time options:.* DHCPv6( |$)" && DHCPv6CAPABLE=1 || DHCPv6CAPABLE=0 + + if [ -x /usr/sbin/odhcpd -a -x /etc/init.d/odhcpd ] ; then + local odhcpd_is_main odhcpd_is_enabled + config_get odhcpd_is_main odhcpd maindhcp 0 + /etc/init.d/odhcpd enabled && odhcpd_is_enabled=1 || odhcpd_is_enabled=0 + + + if [ "$odhcpd_is_enabled" -eq 0 -a "$DHCPv6CAPABLE" -eq 1 ] ; then + # DHCP V4 and V6 in DNSMASQ + DNSMASQ_DHCP_VER=6 + elif [ "$odhcpd_is_main" -gt 0 ] ; then + # ODHCPD is doing it all + DNSMASQ_DHCP_VER=0 + else + # You have ODHCPD but use DNSMASQ for DHCPV4 + DNSMASQ_DHCP_VER=4 + fi + + elif [ "$DHCPv6CAPABLE" -eq 1 ] ; then + # DHCP V4 and V6 in DNSMASQ + DNSMASQ_DHCP_VER=6 + else + DNSMASQ_DHCP_VER=4 + fi + + # Allow DHCP/DHCPv6 to be handled by ISC DHCPD + if [ -x /usr/sbin/dhcpd ] ; then + if [ -x /etc/init.d/dhcpd ] ; then + /etc/init.d/dhcpd enabled && DNSMASQ_DHCP_VER=0 + fi + if [ -x /etc/init.d/dhcpd6 -a "$DNSMASQ_DHCP_VER" -gt 0 ] ; then + /etc/init.d/dhcpd6 enabled && DNSMASQ_DHCP_VER=4 + fi + fi + append_bool "$cfg" authoritative "--dhcp-authoritative" append_bool "$cfg" nodaemon "--no-daemon" append_bool "$cfg" domainneeded "--domain-needed" @@ -558,12 +809,11 @@ dnsmasq_start() append_bool "$cfg" localise_queries "--localise-queries" append_bool "$cfg" readethers "--read-ethers" append_bool "$cfg" dbus "--enable-dbus" - append_bool "$cfg" boguspriv "--bogus-priv" append_bool "$cfg" expandhosts "--expand-hosts" config_get tftp_root "$cfg" "tftp_root" - [ -d "$tftp_root" ] && append_bool "$cfg" enable_tftp "--enable-tftp" + [ -n "$tftp_root" ] && mkdir -p "$tftp_root" && append_bool "$cfg" enable_tftp "--enable-tftp" append_bool "$cfg" tftp_no_fail "--tftp-no-fail" - append_bool "$cfg" nonwildcard "--bind-dynamic" + append_bool "$cfg" nonwildcard "--bind-dynamic" 1 append_bool "$cfg" fqdn "--dhcp-fqdn" append_bool "$cfg" proxydnssec "--proxy-dnssec" append_bool "$cfg" localservice "--local-service" @@ -573,7 +823,8 @@ dnsmasq_start() append_bool "$cfg" allservers "--all-servers" append_bool "$cfg" noping "--no-ping" - append_parm "$cfg" dhcpscript "--dhcp-script" + append_parm "$cfg" logfacility "--log-facility" + append_parm "$cfg" cachesize "--cache-size" append_parm "$cfg" dnsforwardmax "--dns-forward-max" append_parm "$cfg" port "--port" @@ -585,6 +836,7 @@ dnsmasq_start() append_parm "$cfg" "domain" "--domain" append_parm "$cfg" "local" "--server" config_list_foreach "$cfg" "server" append_server + config_list_foreach "$cfg" "rev_server" append_rev_server config_list_foreach "$cfg" "address" append_address config_list_foreach "$cfg" "ipset" append_ipset config_list_foreach "$cfg" "interface" append_interface @@ -592,7 +844,6 @@ dnsmasq_start() config_list_foreach "$cfg" "addnhosts" append_addnhosts config_list_foreach "$cfg" "bogusnxdomain" append_bogusnxdomain append_parm "$cfg" "leasefile" "--dhcp-leasefile" "/tmp/dhcp.leases" - append_parm "$cfg" "resolvfile" "--resolv-file" "/tmp/resolv.conf.auto" append_parm "$cfg" "serversfile" "--servers-file" append_parm "$cfg" "tftp_root" "--tftp-root" append_parm "$cfg" "dhcp_boot" "--dhcp-boot" @@ -603,12 +854,21 @@ dnsmasq_start() config_get_bool ADD_LOCAL_DOMAIN "$cfg" add_local_domain 1 config_get_bool ADD_LOCAL_HOSTNAME "$cfg" add_local_hostname 1 + config_get ADD_LOCAL_FQDN "$cfg" add_local_fqdn "" + config_get ADD_WAN_FQDN "$cfg" add_wan_fqdn 0 + + if [ -z "$ADD_LOCAL_FQDN" ] ; then + # maintain support for previous UCI + ADD_LOCAL_FQDN="$ADD_LOCAL_HOSTNAME" + fi config_get_bool readethers "$cfg" readethers [ "$readethers" = "1" -a \! -e "/etc/ethers" ] && touch /etc/ethers - config_get resolvfile $cfg resolvfile - config_get dhcpscript $cfg dhcpscript + config_get user_dhcpscript $cfg dhcpscript + if has_handler || [ -n "$user_dhcpscript" ]; then + xappend "--dhcp-script=$DHCPSCRIPT" + fi config_get leasefile $cfg leasefile "/tmp/dhcp.leases" [ -n "$leasefile" -a \! -e "$leasefile" ] && touch "$leasefile" @@ -621,6 +881,8 @@ dnsmasq_start() [ -n "$resolvfile" -a \! -e "$resolvfile" ] && touch "$resolvfile" fi + [ -n "$resolvfile" ] && xappend "--resolv-file=$resolvfile" + config_get hostsfile "$cfg" dhcphostsfile [ -e "$hostsfile" ] && xappend "--dhcp-hostsfile=$hostsfile" @@ -667,10 +929,11 @@ dnsmasq_start() } dhcp_option_add "$cfg" "" 0 + dhcp_option_add "$cfg" "" 2 xappend "--dhcp-broadcast=tag:needs-broadcast" - xappend "--addn-hosts=$HOSTFILE" + xappend "--addn-hosts=$(dirname $HOSTFILE)" config_get dnsmasqconfdir "$cfg" confdir "/tmp/dnsmasq.d" [ ! -d "$dnsmasqconfdir" ] && mkdir -p $dnsmasqconfdir @@ -700,37 +963,31 @@ dnsmasq_start() config_foreach filter_dnsmasq hostrecord dhcp_hostrecord_add "$cfg" config_foreach filter_dnsmasq relay dhcp_relay_add "$cfg" - # add own hostname - [ $ADD_LOCAL_HOSTNAME -eq 1 ] && { - local lanaddr lanaddr6 - local ulaprefix="$(uci_get network @globals[0] ula_prefix)" - local hostname="$(uci_get system @system[0] hostname Lede)" - - network_get_ipaddr lanaddr "lan" && { - dhcp_domain_add "" "$hostname" "$lanaddr" - } - - [ -n "$ulaprefix" ] && network_get_ipaddrs6 lanaddr6 "lan" && { - for lanaddr6 in $lanaddr6; do - case "$lanaddr6" in - "${ulaprefix%%:/*}"*) - dhcp_domain_add "" "$hostname" "$lanaddr6" - ;; - esac - done - } - } - echo >> $CONFIGFILE_TMP config_foreach filter_dnsmasq srvhost dhcp_srv_add "$cfg" config_foreach filter_dnsmasq mxhost dhcp_mx_add "$cfg" echo >> $CONFIGFILE_TMP - config_get odhcpd_is_active odhcpd maindhcp - if [ "$odhcpd_is_active" != "1" ]; then + config_get_bool boguspriv "$cfg" boguspriv 1 + [ "$boguspriv" -gt 0 ] && { + xappend "--bogus-priv" + [ -r "$RFC6761FILE" ] && xappend "--conf-file=$RFC6761FILE" + } + + if [ "$DNSMASQ_DHCP_VER" -gt 4 ] ; then + # Enable RA feature for when/if it is constructed, + # and RA is selected per interface pool (RA, DHCP, or both), + # but no one (should) want RA broadcast in syslog + config_foreach filter_dnsmasq dhcp dhcp_add "$cfg" + xappend "--enable-ra" + xappend "--quiet-ra" + append_bool "$cfg" quietdhcp "--quiet-dhcp6" + + elif [ "$DNSMASQ_DHCP_VER" -gt 0 ] ; then config_foreach filter_dnsmasq dhcp dhcp_add "$cfg" fi + echo >> $CONFIGFILE_TMP config_foreach filter_dnsmasq cname dhcp_cname_add "$cfg" echo >> $CONFIGFILE_TMP @@ -752,6 +1009,7 @@ dnsmasq_start() procd_open_instance $cfg procd_set_param command $PROG -C $CONFIGFILE -k -x /var/run/dnsmasq/dnsmasq."${cfg}".pid procd_set_param file $CONFIGFILE + [ -n "$user_dhcpscript" ] && procd_set_param env USER_DHCPSCRIPT="$user_dhcpscript" procd_set_param respawn local dnsmasqconffile="/etc/dnsmasq.${cfg}.conf" @@ -760,7 +1018,7 @@ dnsmasq_start() fi procd_add_jail dnsmasq ubus log - procd_add_jail_mount $CONFIGFILE $TRUSTANCHORSFILE $HOSTFILE /etc/passwd /etc/group /etc/TZ /dev/null /dev/urandom $dnsmasqconffile $dnsmasqconfdir $resolvfile $dhcpscript /etc/hosts /etc/ethers $EXTRA_MOUNT + procd_add_jail_mount $CONFIGFILE $TRUSTANCHORSFILE $HOSTFILE $RFC6761FILE /etc/passwd /etc/group /etc/TZ /dev/null /dev/urandom $dnsmasqconffile $dnsmasqconfdir $resolvfile $user_dhcpscript /etc/hosts /etc/ethers /sbin/hotplug-call $EXTRA_MOUNT $DHCPSCRIPT procd_add_jail_mount_rw /var/run/dnsmasq/ $leasefile procd_close_instance diff --git a/package/network/services/dnsmasq/files/dnsmasq_acl.json b/package/network/services/dnsmasq/files/dnsmasq_acl.json new file mode 100644 index 000000000..00ec7d0f0 --- /dev/null +++ b/package/network/services/dnsmasq/files/dnsmasq_acl.json @@ -0,0 +1,4 @@ +{ + "user": "dnsmasq", + "publish": [ "dnsmasq" ] +} diff --git a/package/network/services/dnsmasq/files/dnsmasqsec.hotplug b/package/network/services/dnsmasq/files/dnsmasqsec.hotplug index 5c69314bd..a155eb0f6 100644 --- a/package/network/services/dnsmasq/files/dnsmasqsec.hotplug +++ b/package/network/services/dnsmasq/files/dnsmasqsec.hotplug @@ -1,5 +1,7 @@ #!/bin/sh +. /lib/functions/procd.sh + TIMEVALIDFILE="/var/state/dnsmasqsec" [ "$ACTION" = stratum ] || exit 0 @@ -7,8 +9,6 @@ TIMEVALIDFILE="/var/state/dnsmasqsec" [ -f "$TIMEVALIDFILE" ] || { echo "ntpd says time is valid" >$TIMEVALIDFILE /etc/init.d/dnsmasq enabled && { - pid=$(pidof dnsmasq) - [ "$(readlink /proc/$pid/exe)" = "/usr/sbin/dnsmasq" ] && kill -SIGHUP $pid \ - || /etc/init.d/dnsmasq restart + procd_send_signal dnsmasq } } diff --git a/package/network/services/dnsmasq/files/rfc6761.conf b/package/network/services/dnsmasq/files/rfc6761.conf new file mode 100644 index 000000000..ebc1a1211 --- /dev/null +++ b/package/network/services/dnsmasq/files/rfc6761.conf @@ -0,0 +1,15 @@ +# RFC6761 included configuration file for dnsmasq +# +# includes a list of domains that should not be forwarded to Internet name servers +# to reduce burden on them, asking questions that they won't know the answer to. + +server=/bind/ +server=/example/ +server=/example.com/ +server=/example.org/ +server=/example.net/ +server=/invalid/ +server=/local/ +server=/localhost/ +server=/onion/ +server=/test/ diff --git a/package/network/services/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch b/package/network/services/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch deleted file mode 100644 index 5fc62ffab..000000000 --- a/package/network/services/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/src/dhcp.c -+++ b/src/dhcp.c -@@ -147,7 +147,7 @@ void dhcp_packet(time_t now, int pxe_fd) - ssize_t sz; - int iface_index = 0, unicast_dest = 0, is_inform = 0; - int rcvd_iface_index; -- struct in_addr iface_addr; -+ struct in_addr iface_addr, *addrp = NULL; - struct iface_param parm; - #ifdef HAVE_LINUX_NETWORK - struct arpreq arp_req; -@@ -277,11 +277,9 @@ void dhcp_packet(time_t now, int pxe_fd) - { - ifr.ifr_addr.sa_family = AF_INET; - if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 ) -- iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; -- else - { -- my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name); -- return; -+ addrp = &iface_addr; -+ iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; - } - - for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) -@@ -300,7 +298,7 @@ void dhcp_packet(time_t now, int pxe_fd) - parm.relay_local.s_addr = 0; - parm.ind = iface_index; - -- if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL)) -+ if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, NULL)) - { - /* If we failed to match the primary address of the interface, see if we've got a --listen-address - for a secondary */ -@@ -320,6 +318,12 @@ void dhcp_packet(time_t now, int pxe_fd) - complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm); - } - -+ if (!addrp) -+ { -+ my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name); -+ return; -+ } -+ - if (!iface_enumerate(AF_INET, &parm, complete_context)) - return; - diff --git a/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch b/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch index 61b09d5b2..88e334b0f 100644 --- a/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch +++ b/package/network/services/dnsmasq/patches/110-ipset-remove-old-kernel-support.patch @@ -44,67 +44,22 @@ (buffer = safe_malloc(BUFF_SZ)) && (ipset_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER)) != -1 && (bind(ipset_sock, (struct sockaddr *)&snl, sizeof(snl)) != -1)) -@@ -168,62 +149,16 @@ static int new_add_to_ipset(const char * - } - - --static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int remove) --{ -- socklen_t size; -- struct ip_set_req_adt_get { -- unsigned op; -- unsigned version; -- union { -- char name[IPSET_MAXNAMELEN]; -- uint16_t index; -- } set; -- char typename[IPSET_MAXNAMELEN]; -- } req_adt_get; -- struct ip_set_req_adt { -- unsigned op; -- uint16_t index; -- uint32_t ip; -- } req_adt; -- -- if (strlen(setname) >= sizeof(req_adt_get.set.name)) -- { -- errno = ENAMETOOLONG; -- return -1; -- } -- -- req_adt_get.op = 0x10; -- req_adt_get.version = 3; -- strcpy(req_adt_get.set.name, setname); -- size = sizeof(req_adt_get); -- if (getsockopt(ipset_sock, SOL_IP, 83, &req_adt_get, &size) < 0) -- return -1; -- req_adt.op = remove ? 0x102 : 0x101; -- req_adt.index = req_adt_get.set.index; -- req_adt.ip = ntohl(ipaddr->addr.addr4.s_addr); -- if (setsockopt(ipset_sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0) -- return -1; -- -- return 0; --} -- -- -- - int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove) - { - int af = AF_INET; - - #ifdef HAVE_IPV6 +@@ -217,17 +198,10 @@ int add_to_ipset(const char *setname, co if (flags & F_IPV6) -- { + { af = AF_INET6; - /* old method only supports IPv4 */ - if (old_kernel) -- return -1; -- } +- { +- errno = EAFNOSUPPORT ; +- ret = -1; +- } + } #endif -- return old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove); -+ return new_add_to_ipset(setname, ipaddr, af, remove); - } +- if (ret != -1) +- ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove); ++ ret = new_add_to_ipset(setname, ipaddr, af, remove); - #endif + if (ret == -1) + my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno)); diff --git a/package/network/services/dnsmasq/patches/120-dnsmasq-compile-time-option-NO_ID.patch b/package/network/services/dnsmasq/patches/120-dnsmasq-compile-time-option-NO_ID.patch deleted file mode 100644 index 152d1a7fa..000000000 --- a/package/network/services/dnsmasq/patches/120-dnsmasq-compile-time-option-NO_ID.patch +++ /dev/null @@ -1,149 +0,0 @@ -From f6bea86c78ba9efbd01da3dd2fb18764ec806290 Mon Sep 17 00:00:00 2001 -From: Kevin Darbyshire-Bryant -Date: Wed, 7 Sep 2016 09:35:07 +0100 -Subject: [PATCH] dnsmasq: compile time option NO_ID - -Some consider it good practice to obscure software version numbers to -clients. Compiling with -DNO_ID removes the *.bind info structure. -This includes: version, author, copyright, cachesize, cache insertions, -evictions, misses & hits, auth & servers. - -Signed-off-by: Kevin Darbyshire-Bryant ---- - src/cache.c | 2 ++ - src/config.h | 5 +++++ - src/dnsmasq.h | 4 ++++ - src/option.c | 8 ++++++-- - src/rfc1035.c | 3 ++- - 5 files changed, 19 insertions(+), 3 deletions(-) - ---- a/src/cache.c -+++ b/src/cache.c -@@ -1290,6 +1290,7 @@ void cache_add_dhcp_entry(char *host_nam - } - #endif - -+#ifndef NO_ID - int cache_make_stat(struct txt_record *t) - { - static char *buff = NULL; -@@ -1385,6 +1386,7 @@ int cache_make_stat(struct txt_record *t - *buff = len; - return 1; - } -+#endif - - /* There can be names in the cache containing control chars, don't - mess up logging or open security holes. */ ---- a/src/config.h -+++ b/src/config.h -@@ -120,6 +120,8 @@ HAVE_LOOP - HAVE_INOTIFY - use the Linux inotify facility to efficiently re-read configuration files. - -+NO_ID -+ Don't report *.bind CHAOS info to clients. - NO_IPV6 - NO_TFTP - NO_DHCP -@@ -434,6 +436,9 @@ static char *compile_opts = - "no-" - #endif - "DNSSEC " -+#ifdef NO_ID -+"no-ID " -+#endif - #ifndef HAVE_LOOP - "no-" - #endif ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -286,6 +286,7 @@ struct naptr { - struct naptr *next; - }; - -+#ifndef NO_ID - #define TXT_STAT_CACHESIZE 1 - #define TXT_STAT_INSERTS 2 - #define TXT_STAT_EVICTIONS 3 -@@ -293,6 +294,7 @@ struct naptr { - #define TXT_STAT_HITS 5 - #define TXT_STAT_AUTH 6 - #define TXT_STAT_SERVERS 7 -+#endif - - struct txt_record { - char *name; -@@ -1078,7 +1080,9 @@ void cache_add_dhcp_entry(char *host_nam - struct in_addr a_record_from_hosts(char *name, time_t now); - void cache_unhash_dhcp(void); - void dump_cache(time_t now); -+#ifndef NO_ID - int cache_make_stat(struct txt_record *t); -+#endif - char *cache_get_name(struct crec *crecp); - char *cache_get_cname_target(struct crec *crecp); - struct crec *cache_enumerate(int init); ---- a/src/option.c -+++ b/src/option.c -@@ -657,7 +657,8 @@ static int atoi_check8(char *a, int *res - return 1; - } - #endif -- -+ -+#ifndef NO_ID - static void add_txt(char *name, char *txt, int stat) - { - struct txt_record *r = opt_malloc(sizeof(struct txt_record)); -@@ -670,13 +671,14 @@ static void add_txt(char *name, char *tx - *(r->txt) = len; - memcpy((r->txt)+1, txt, len); - } -- -+ - r->stat = stat; - r->name = opt_string_alloc(name); - r->next = daemon->txt; - daemon->txt = r; - r->class = C_CHAOS; - } -+#endif - - static void do_usage(void) - { -@@ -4515,6 +4517,7 @@ void read_opts(int argc, char **argv, ch - daemon->soa_expiry = SOA_EXPIRY; - daemon->max_port = MAX_PORT; - -+#ifndef NO_ID - add_txt("version.bind", "dnsmasq-" VERSION, 0 ); - add_txt("authors.bind", "Simon Kelley", 0); - add_txt("copyright.bind", COPYRIGHT, 0); -@@ -4527,6 +4530,7 @@ void read_opts(int argc, char **argv, ch - add_txt("auth.bind", NULL, TXT_STAT_AUTH); - #endif - add_txt("servers.bind", NULL, TXT_STAT_SERVERS); -+#endif - - while (1) - { ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1264,6 +1264,7 @@ size_t answer_request(struct dns_header - unsigned long ttl = daemon->local_ttl; - int ok = 1; - log_query(F_CONFIG | F_RRNAME, name, NULL, ""); -+#ifndef NO_ID - /* Dynamically generate stat record */ - if (t->stat != 0) - { -@@ -1271,7 +1272,7 @@ size_t answer_request(struct dns_header - if (!cache_make_stat(t)) - ok = 0; - } -- -+#endif - if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp, - ttl, NULL, - T_TXT, t->class, "t", t->len, t->txt)) diff --git a/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch b/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch index ca5a80669..2f854d490 100644 --- a/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch +++ b/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch @@ -35,13 +35,13 @@ Signed-off-by: Steven Barth + if (difftime(now, base) >= 0 && difftime(timestamp_time, now) <= 0) { /* time already OK, update timestamp, and do key checking from the start. */ - if (utime(daemon->timestamp_file, NULL) == -1) + if (utimes(daemon->timestamp_file, NULL) == -1) @@ -493,7 +500,7 @@ int setup_timestamp(void) close(fd); -- timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */ -+ timestamp_time = timbuf.actime = timbuf.modtime = base; - if (utime(daemon->timestamp_file, &timbuf) == 0) - goto check_and_exit; - } +- timestamp_time = 1420070400; /* 1-1-2015 */ ++ timestamp_time = base; /* 1-1-2015 */ + tv[0].tv_sec = tv[1].tv_sec = timestamp_time; + tv[0].tv_usec = tv[1].tv_usec = 0; + if (utimes(daemon->timestamp_file, tv) == 0) diff --git a/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch b/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch index 19300f7d6..37b11abc1 100644 --- a/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch +++ b/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch @@ -7,7 +7,7 @@ Signed-off-by: Kevin Darbyshire-Bryant --- a/src/dnsmasq.h +++ b/src/dnsmasq.h -@@ -82,7 +82,7 @@ typedef unsigned long long u64; +@@ -88,7 +88,7 @@ typedef unsigned long long u64; #if defined(HAVE_SOLARIS_NETWORK) # include #endif diff --git a/package/network/services/dnsmasq/patches/240-ubus.patch b/package/network/services/dnsmasq/patches/240-ubus.patch new file mode 100644 index 000000000..2d37b5d2f --- /dev/null +++ b/package/network/services/dnsmasq/patches/240-ubus.patch @@ -0,0 +1,126 @@ +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -19,6 +19,8 @@ + + #include "dnsmasq.h" + ++#include ++ + struct daemon *daemon; + + static volatile pid_t pid = 0; +@@ -32,6 +34,62 @@ static void fatal_event(struct event_des + static int read_event(int fd, struct event_desc *evp, char **msg); + static void poll_resolv(int force, int do_reload, time_t now); + ++static struct ubus_context *ubus; ++static struct blob_buf b; ++ ++static struct ubus_object_type ubus_object_type = { ++ .name = "dnsmasq", ++}; ++ ++static struct ubus_object ubus_object = { ++ .name = "dnsmasq", ++ .type = &ubus_object_type, ++}; ++ ++void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name) ++{ ++ if (!ubus || !ubus_object.has_subscribers) ++ return; ++ ++ blob_buf_init(&b, 0); ++ if (mac) ++ blobmsg_add_string(&b, "mac", mac); ++ if (ip) ++ blobmsg_add_string(&b, "ip", ip); ++ if (name) ++ blobmsg_add_string(&b, "name", name); ++ ubus_notify(ubus, &ubus_object, type, b.head, -1); ++} ++ ++static void set_ubus_listeners(void) ++{ ++ if (!ubus) ++ return; ++ ++ poll_listen(ubus->sock.fd, POLLIN); ++ poll_listen(ubus->sock.fd, POLLERR); ++ poll_listen(ubus->sock.fd, POLLHUP); ++} ++ ++static void check_ubus_listeners() ++{ ++ if (!ubus) { ++ ubus = ubus_connect(NULL); ++ if (ubus) ++ ubus_add_object(ubus, &ubus_object); ++ else ++ return; ++ } ++ ++ if (poll_check(ubus->sock.fd, POLLIN)) ++ ubus_handle_event(ubus); ++ ++ if (poll_check(ubus->sock.fd, POLLHUP)) { ++ ubus_free(ubus); ++ ubus = NULL; ++ } ++} ++ + int main (int argc, char **argv) + { + int bind_fallback = 0; +@@ -911,6 +969,7 @@ int main (int argc, char **argv) + set_dbus_listeners(); + #endif + ++ set_ubus_listeners(); + #ifdef HAVE_DHCP + if (daemon->dhcp || daemon->relay4) + { +@@ -1041,6 +1100,8 @@ int main (int argc, char **argv) + check_dbus_listeners(); + #endif + ++ check_ubus_listeners(); ++ + check_dns_listeners(now); + + #ifdef HAVE_TFTP +--- a/Makefile ++++ b/Makefile +@@ -85,7 +85,7 @@ all : $(BUILDDIR) + @cd $(BUILDDIR) && $(MAKE) \ + top="$(top)" \ + build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \ +- build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \ ++ build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) -lubox -lubus" \ + -f $(top)/Makefile dnsmasq + + mostly_clean : +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1397,6 +1397,8 @@ void emit_dbus_signal(int action, struct + # endif + #endif + ++void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name); ++ + /* ipset.c */ + #ifdef HAVE_IPSET + void ipset_init(void); +--- a/src/rfc2131.c ++++ b/src/rfc2131.c +@@ -1621,6 +1621,10 @@ static void log_packet(char *type, void + daemon->namebuff, + string ? string : "", + err ? err : ""); ++ if (!strcmp(type, "DHCPACK")) ++ ubus_event_bcast("dhcp.ack", addr ? inet_ntoa(a) : NULL, daemon->namebuff, string ? string : NULL); ++ else if (!strcmp(type, "DHCPRELEASE")) ++ ubus_event_bcast("dhcp.release", addr ? inet_ntoa(a) : NULL, daemon->namebuff, string ? string : NULL); + } + + static void log_options(unsigned char *start, u32 xid) From abbbbec60af71b312370a059e0b2b3c80078163e Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Fri, 13 Oct 2017 22:37:33 +0800 Subject: [PATCH 05/15] ath10k-ct driver and firmware stable fix --- package/firmware/ath10k-firmware/Makefile | 20 +++++------ package/kernel/ath10k-ct/Makefile | 17 +++++---- .../ath10k-ct/patches/100-kernel_compat.patch | 12 +++---- .../ath10k-ct/patches/110-api_fix.patch | 2 +- .../patches/120-mac80211-4-14-api.patch | 6 ++-- ...te-user-space-firmware-loading-again.patch | 36 +++++++++++++++++++ 6 files changed, 67 insertions(+), 26 deletions(-) create mode 100644 package/kernel/ath10k-ct/patches/130-ath10k-activate-user-space-firmware-loading-again.patch diff --git a/package/firmware/ath10k-firmware/Makefile b/package/firmware/ath10k-firmware/Makefile index 5aac2616d..1ff1340a2 100644 --- a/package/firmware/ath10k-firmware/Makefile +++ b/package/firmware/ath10k-firmware/Makefile @@ -82,38 +82,38 @@ define Download/ct-firmware URL_FILE:=$($(1)_FIRMWARE_FILE_CT) endef -QCA988X_FIRMWARE_FILE_CT:=firmware-2-ct-full-community.bin-19-rc5-lede +QCA988X_FIRMWARE_FILE_CT:=firmware-2-ct-full-community-19.bin.lede define Download/ath10k-firmware-qca988x-ct $(call Download/ct-firmware,QCA988X,) - HASH:=556d6a4df50cd94a229a240d6d1d108ed5910069902f1e0cbb57b02ede27690f + HASH:=bff98f028062dae9fc638c7596aec3c79bf9eddaff65cfacba067f6d72f217cd endef $(eval $(call Download,ath10k-firmware-qca988x-ct)) -QCA9887_FIRMWARE_FILE_CT:=firmware-2-ct-full-community.bin-19-rc5-lede +QCA9887_FIRMWARE_FILE_CT:=firmware-2-ct-full-community-19.bin.lede define Download/ath10k-firmware-qca9887-ct $(call Download/ct-firmware,QCA9887,ath10k-9887) - HASH:=725982694156e0b891dcd1b1b18ba5318fbbe173f4ec9603ff7acbd08f7c4050 + HASH:=95dc106f98672bd9c7d3fe6881ed79ab079cb49b0a995650991b1beaff2b0101 endef $(eval $(call Download,ath10k-firmware-qca9887-ct)) -QCA99X0_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.002 +QCA99X0_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.004 define Download/ath10k-firmware-qca99x0-ct $(call Download/ct-firmware,QCA99X0,ath10k-10-4) - HASH:=e3c77077b47d55219f90816a51bf046f5b40c32be5e96bf629b083d873a879ad + HASH:=993c29fd64bb2a59b86d34f58601a1a48b83b541750bc511f78cc17152829b4d endef $(eval $(call Download,ath10k-firmware-qca99x0-ct)) -QCA9984_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.002 +QCA9984_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.004 define Download/ath10k-firmware-qca9984-ct $(call Download/ct-firmware,QCA9984,ath10k-9984-10-4) - HASH:=610f7747db6b101f4fc21431b776ac640b5977357e5be9aece2349447b9b1d85 + HASH:=d997eed9a8bc6809c01d367759ba8545c10e3be93ea1f33d6d753127ef0f7c5e endef $(eval $(call Download,ath10k-firmware-qca9984-ct)) -QCA9888_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.002 +QCA9888_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.004 define Download/ath10k-firmware-qca9888-ct $(call Download/ct-firmware,QCA9888,ath10k-9888-10-4) - HASH:=f92e7d7968698af7c6f2d76b31b3645589e03839e15838010ce457c635e5aae6 + HASH:=bbaa71bc7dcaa264c5875e86639f174908fed09fbace975e325959d42f3754ff endef $(eval $(call Download,ath10k-firmware-qca9888-ct)) diff --git a/package/kernel/ath10k-ct/Makefile b/package/kernel/ath10k-ct/Makefile index 85fe4eb46..a894773b7 100644 --- a/package/kernel/ath10k-ct/Makefile +++ b/package/kernel/ath10k-ct/Makefile @@ -8,13 +8,18 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/greearb/ath10k-ct.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2017-05-16 -PKG_SOURCE_VERSION:=c048ef0c3eedf99b41bc12b3f4e47ef3d9fab484 -PKG_MIRROR_HASH:=7936293962a10a0da7469759623013fc151019a6a584cfc6416bc0b605bd74d7 +PKG_SOURCE_DATE:=2017-06-13 +PKG_SOURCE_VERSION:=bded1823912549017d819d1796273b3134c3de20 +PKG_MIRROR_HASH:=616174650e12a82edb6b6bd18ac186e2c6a48fdad0082df9d2011ab20940814b PKG_MAINTAINER:=Ben Greear PKG_BUILD_PARALLEL:=1 +# Build the 4.13 ath10k-ct driver version. Other options are "-4.9", or +# leave un-defined for 4.7 kernel. Probably this should match as closely as +# possible to whatever mac80211 backports version is being used. +CT_KVER="-4.13" + STAMP_CONFIGURED_DEPENDS := $(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h include $(INCLUDE_DIR)/kernel.mk @@ -25,8 +30,8 @@ define KernelPackage/ath10k-ct TITLE:=ath10k-ct driver optimized for CT ath10k firmware DEPENDS:=+kmod-mac80211 +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT @PCI_SUPPORT +@KERNEL_RELAY +kmod-hwmon-core FILES:=\ - $(PKG_BUILD_DIR)/ath10k/ath10k_pci.ko \ - $(PKG_BUILD_DIR)/ath10k/ath10k_core.ko + $(PKG_BUILD_DIR)/ath10k$(CT_KVER)/ath10k_pci.ko \ + $(PKG_BUILD_DIR)/ath10k$(CT_KVER)/ath10k_core.ko AUTOLOAD:=$(call AutoLoad,50,mac80211 ath ath10k_core ath10k_pci) endef @@ -75,7 +80,7 @@ define Build/Compile +$(MAKE) $(CT_MAKEDEFS) $(PKG_JOBS) -C "$(LINUX_DIR)" \ ARCH="$(LINUX_KARCH)" \ CROSS_COMPILE="$(TARGET_CROSS)" \ - SUBDIRS="$(PKG_BUILD_DIR)/ath10k" \ + SUBDIRS="$(PKG_BUILD_DIR)/ath10k$(CT_KVER)" \ NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ modules endef diff --git a/package/kernel/ath10k-ct/patches/100-kernel_compat.patch b/package/kernel/ath10k-ct/patches/100-kernel_compat.patch index 58d6b54c5..beb0abf6d 100644 --- a/package/kernel/ath10k-ct/patches/100-kernel_compat.patch +++ b/package/kernel/ath10k-ct/patches/100-kernel_compat.patch @@ -17,7 +17,7 @@ firmware = ar->normal_mode_fw.fw_file.firmware; if (firmware) -@@ -3413,7 +3413,7 @@ int ath10k_debug_register(struct ath10k +@@ -3422,7 +3422,7 @@ int ath10k_debug_register(struct ath10k debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR, ar->debug.debugfs_phy, ar, &fops_nf_cal_period); @@ -28,7 +28,7 @@ &fops_simulate_radar); --- a/ath10k/mac.c +++ b/ath10k/mac.c -@@ -3596,7 +3596,7 @@ static void ath10k_regd_update(struct at +@@ -3604,7 +3604,7 @@ static void ath10k_regd_update(struct at regpair = ar->ath_common.regulatory.regpair; @@ -37,7 +37,7 @@ nl_dfs_reg = ar->dfs_detector->region; wmi_dfs_reg = ath10k_mac_get_dfs_region(nl_dfs_reg); ath10k_dbg(ar, ATH10K_DBG_REGULATORY, -@@ -3630,7 +3630,7 @@ static void ath10k_reg_notifier(struct w +@@ -3638,7 +3638,7 @@ static void ath10k_reg_notifier(struct w ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory); @@ -46,7 +46,7 @@ ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "reg-notifier: dfs region 0x%x\n", request->dfs_region); result = ar->dfs_detector->set_dfs_domain(ar->dfs_detector, -@@ -8925,7 +8925,7 @@ int ath10k_mac_register(struct ath10k *a +@@ -8938,7 +8938,7 @@ int ath10k_mac_register(struct ath10k *a if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) ar->hw->netdev_features = NETIF_F_HW_CSUM; @@ -55,7 +55,7 @@ /* Init ath dfs pattern detector */ ar->ath_common.debug_mask = ATH_DBG_DFS; ar->dfs_detector = dfs_pattern_detector_init(&ar->ath_common, -@@ -8970,7 +8970,7 @@ err_unregister: +@@ -8983,7 +8983,7 @@ err_unregister: ieee80211_unregister_hw(ar->hw); err_dfs_detector_exit: @@ -64,7 +64,7 @@ ar->dfs_detector->exit(ar->dfs_detector); err_free: -@@ -8985,7 +8985,7 @@ void ath10k_mac_unregister(struct ath10k +@@ -8998,7 +8998,7 @@ void ath10k_mac_unregister(struct ath10k { ieee80211_unregister_hw(ar->hw); diff --git a/package/kernel/ath10k-ct/patches/110-api_fix.patch b/package/kernel/ath10k-ct/patches/110-api_fix.patch index 5f7de4a95..9439dd79e 100644 --- a/package/kernel/ath10k-ct/patches/110-api_fix.patch +++ b/package/kernel/ath10k-ct/patches/110-api_fix.patch @@ -1,6 +1,6 @@ --- a/ath10k/htt_rx.c +++ b/ath10k/htt_rx.c -@@ -2497,7 +2497,7 @@ bool ath10k_htt_t2h_msg_handler(struct a +@@ -2514,7 +2514,7 @@ bool ath10k_htt_t2h_msg_handler(struct a u32 freq = __le32_to_cpu(resp->chan_change.freq); ar->tgt_oper_chan = diff --git a/package/kernel/ath10k-ct/patches/120-mac80211-4-14-api.patch b/package/kernel/ath10k-ct/patches/120-mac80211-4-14-api.patch index 032a0bcb7..d58763269 100644 --- a/package/kernel/ath10k-ct/patches/120-mac80211-4-14-api.patch +++ b/package/kernel/ath10k-ct/patches/120-mac80211-4-14-api.patch @@ -51,7 +51,7 @@ break; default: break; -@@ -883,13 +883,10 @@ static void ath10k_htt_rx_h_ppdu(struct +@@ -900,13 +900,10 @@ static void ath10k_htt_rx_h_ppdu(struct /* New PPDU starts so clear out the old per-PPDU status. */ status->freq = 0; status->rate_idx = 0; @@ -69,7 +69,7 @@ status->flag |= RX_FLAG_NO_SIGNAL_VAL; ath10k_htt_rx_h_signal(ar, status, rxd); -@@ -942,7 +939,7 @@ static void ath10k_process_rx(struct ath +@@ -959,7 +956,7 @@ static void ath10k_process_rx(struct ath *status = *rx_status; ath10k_dbg(ar, ATH10K_DBG_DATA, @@ -78,7 +78,7 @@ skb, skb->len, ieee80211_get_SA(hdr), -@@ -950,15 +947,15 @@ static void ath10k_process_rx(struct ath +@@ -967,15 +964,15 @@ static void ath10k_process_rx(struct ath is_multicast_ether_addr(ieee80211_get_DA(hdr)) ? "mcast" : "ucast", (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4, diff --git a/package/kernel/ath10k-ct/patches/130-ath10k-activate-user-space-firmware-loading-again.patch b/package/kernel/ath10k-ct/patches/130-ath10k-activate-user-space-firmware-loading-again.patch new file mode 100644 index 000000000..dc02a9d6e --- /dev/null +++ b/package/kernel/ath10k-ct/patches/130-ath10k-activate-user-space-firmware-loading-again.patch @@ -0,0 +1,36 @@ +From c0cc00f250e19c717fc9cdbdb7f55aaa569c7498 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Thu, 24 Aug 2017 23:06:41 +0200 +Subject: [PATCH] ath10k: activate user space firmware loading again + +In commit 9f5bcfe93315 ("ath10k: silence firmware file probing +warnings") the firmware loading was changed from request_firmware() to +request_firmware_direct() to silence some warnings in case it fails. +request_firmware_direct() directly searches in the file system only and +does not send a hotplug event to user space in case it could not find +the firmware directly. +In LEDE we use a user space script to extract the calibration data from +the flash memory which gets triggered by the hotplug event. This way the +firmware gets extracted from some vendor specific partition when the +driver requests this firmware. This mechanism does not work any more +after this change. + +Fixes: 9f5bcfe93315 ("ath10k: silence firmware file probing warnings") +Signed-off-by: Hauke Mehrtens +Cc: Michal Kazior +Signed-off-by: Kalle Valo +--- + ath10k-4.13/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/ath10k-4.13/core.c ++++ b/ath10k-4.13/core.c +@@ -556,7 +556,7 @@ static const struct firmware *ath10k_fet + dir = "."; + + snprintf(filename, sizeof(filename), "%s/%s", dir, file); +- ret = request_firmware_direct(&fw, filename, ar->dev); ++ ret = request_firmware(&fw, filename, ar->dev); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n", + filename, ret); + From 29e2e0556745cef44ece7b8adabca03d21a1c899 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Fri, 13 Oct 2017 22:42:57 +0800 Subject: [PATCH 06/15] mac80211: update to wireless kernel to 2017-10-06 --- package/kernel/mac80211/Makefile | 13 +- .../patches/002-change_allconfig.patch | 6 +- .../100-remove-cryptoapi-dependencies.patch | 144 ++++++------- .../mac80211/patches/130-disable-fils.patch | 32 +++ ...aes-cmac-switch-to-shash-CMAC-driver.patch | 198 ++++++++++++++++++ .../132-mac80211-remove-cmac-dependency.patch | 10 + ..._hw-issue-external-reset-for-QCA955x.patch | 51 +++-- ...ix-channel-maximum-power-level-test.patch} | 0 ...ower-reduction-for-US-regulatory-do.patch} | 5 +- ...ta-flag-for-buffered-multicast-pack.patch} | 3 +- ...able-wake_tx_queue-for-older-device.patch} | 4 +- .../522-mac80211_configure_antenna_gain.patch | 10 +- .../patches/530-ath9k_extra_leds.patch | 12 +- ...not-set-auto-rate-fallback-on-8188eu.patch | 2 +- ...62-brcmfmac-Disable-power-management.patch | 2 +- 15 files changed, 361 insertions(+), 131 deletions(-) create mode 100644 package/kernel/mac80211/patches/130-disable-fils.patch create mode 100644 package/kernel/mac80211/patches/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch create mode 100644 package/kernel/mac80211/patches/132-mac80211-remove-cmac-dependency.patch rename package/kernel/mac80211/patches/{324-ath9k_hw-fix-channel-maximum-power-level-test.patch => 314-ath9k_hw-fix-channel-maximum-power-level-test.patch} (100%) rename package/kernel/mac80211/patches/{330-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch => 315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch} (91%) rename package/kernel/mac80211/patches/{331-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch => 316-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch} (99%) rename package/kernel/mac80211/patches/{332-ath10k-Revert-disable-wake_tx_queue-for-older-devices.patch => 317-Revert-ath10k-disable-wake_tx_queue-for-older-device.patch} (85%) diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 16f5a0696..424b2ca50 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -10,14 +10,13 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 -PKG_VERSION:=4.14-rc2 +PKG_VERSION:=2017-10-06 PKG_RELEASE:=1 -PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v$(PKG_VERSION)/ -PKG_BACKPORT_VERSION:=-1 -PKG_HASH:=8d1b62e0ea6cc2ffa7e6ae666da201360256e9b74ae651a31842d33625367524 +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_HASH:=194786b7635f36b9ce280fd2319f6a4feeff209175e330ddbcbe789a3b4540a5 -PKG_SOURCE:=backports-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.xz -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION)$(PKG_BACKPORT_VERSION) +PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION) PKG_BUILD_PARALLEL:=1 PKG_MAINTAINER:=Felix Fietkau @@ -102,7 +101,7 @@ define KernelPackage/mac80211 $(call KernelPackage/mac80211/Default) TITLE:=Linux 802.11 Wireless Networking Stack # +kmod-crypto-cmac is a runtime only dependency of net/mac80211/aes_cmac.c - DEPENDS+= +kmod-cfg80211 +kmod-crypto-hash +kmod-crypto-cmac +hostapd-common + DEPENDS+= +kmod-cfg80211 +hostapd-common KCONFIG:=\ CONFIG_AVERAGE=y FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko diff --git a/package/kernel/mac80211/patches/002-change_allconfig.patch b/package/kernel/mac80211/patches/002-change_allconfig.patch index bd5bebfa4..a071ae637 100644 --- a/package/kernel/mac80211/patches/002-change_allconfig.patch +++ b/package/kernel/mac80211/patches/002-change_allconfig.patch @@ -1,6 +1,6 @@ --- a/kconf/conf.c +++ b/kconf/conf.c -@@ -593,40 +593,12 @@ int main(int ac, char **av) +@@ -594,40 +594,12 @@ int main(int ac, char **av) case oldconfig: case listnewconfig: case olddefconfig: @@ -44,7 +44,7 @@ break; --- a/kconf/confdata.c +++ b/kconf/confdata.c -@@ -1169,6 +1169,8 @@ bool conf_set_all_new_symbols(enum conf_ +@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_ } bool has_changed = false; @@ -53,7 +53,7 @@ for_all_symbols(i, sym) { if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) continue; -@@ -1212,8 +1214,6 @@ bool conf_set_all_new_symbols(enum conf_ +@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_ } diff --git a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch index 263be3e20..0febc57b3 100644 --- a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch +++ b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch @@ -43,122 +43,118 @@ - struct aead_request *aead_req; - int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); - u8 *__aad; -- ++ int i; + - aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); - if (!aead_req) - return -ENOMEM; -- -- __aad = (u8 *)aead_req + reqsize; -- memcpy(__aad, aad, CCM_AAD_LEN); -- -- sg_init_table(sg, 3); -- sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); -- sg_set_buf(&sg[1], data, data_len); -- sg_set_buf(&sg[2], mic, mic_len); -- -- aead_request_set_tfm(aead_req, tfm); -- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); -- aead_request_set_ad(aead_req, sg[0].length); -+ int i; - -- crypto_aead_encrypt(aead_req); -- kzfree(aead_req); + crypto_cipher_encrypt_one(tfm, b, b_0); -- return 0; +- __aad = (u8 *)aead_req + reqsize; +- memcpy(__aad, aad, CCM_AAD_LEN); + /* Extra Authenticate-only data (always two AES blocks) */ + for (i = 0; i < AES_BLOCK_SIZE; i++) + aad[i] ^= b[i]; + crypto_cipher_encrypt_one(tfm, b, aad); -+ + +- sg_init_table(sg, 3); +- sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); +- sg_set_buf(&sg[1], data, data_len); +- sg_set_buf(&sg[2], mic, mic_len); + aad += AES_BLOCK_SIZE; -+ + +- aead_request_set_tfm(aead_req, tfm); +- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); +- aead_request_set_ad(aead_req, sg[0].length); + for (i = 0; i < AES_BLOCK_SIZE; i++) + aad[i] ^= b[i]; + crypto_cipher_encrypt_one(tfm, a, aad); -+ + +- crypto_aead_encrypt(aead_req); +- kzfree(aead_req); + /* Mask out bits from auth-only-b_0 */ + b_0[0] &= 0x07; -+ + +- return 0; + /* S_0 is used to encrypt T (= MIC) */ + b_0[14] = 0; + b_0[15] = 0; + crypto_cipher_encrypt_one(tfm, s_0, b_0); -+} -+ + } + +-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +- u8 *data, size_t data_len, u8 *mic, +- size_t mic_len) + +void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, + u8 *data, size_t data_len, u8 *mic, + size_t mic_len) -+{ -+ int i, j, last_len, num_blocks; -+ u8 b[AES_BLOCK_SIZE]; -+ u8 s_0[AES_BLOCK_SIZE]; -+ u8 e[AES_BLOCK_SIZE]; -+ u8 *pos, *cpos; -+ -+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); -+ last_len = data_len % AES_BLOCK_SIZE; -+ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b); -+ -+ /* Process payload blocks */ -+ pos = data; -+ cpos = data; -+ for (j = 1; j <= num_blocks; j++) { -+ int blen = (j == num_blocks && last_len) ? -+ last_len : AES_BLOCK_SIZE; -+ -+ /* Authentication followed by encryption */ -+ for (i = 0; i < blen; i++) -+ b[i] ^= pos[i]; -+ crypto_cipher_encrypt_one(tfm, b, b); -+ -+ b_0[14] = (j >> 8) & 0xff; -+ b_0[15] = j & 0xff; -+ crypto_cipher_encrypt_one(tfm, e, b_0); -+ for (i = 0; i < blen; i++) -+ *cpos++ = *pos++ ^ e[i]; -+ } -+ -+ for (i = 0; i < mic_len; i++) -+ mic[i] = b[i] ^ s_0[i]; - } - --int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, -+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, - u8 *data, size_t data_len, u8 *mic, - size_t mic_len) { - struct scatterlist sg[3]; - struct aead_request *aead_req; - int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); - u8 *__aad; - int err; -- ++ int i, j, last_len, num_blocks; ++ u8 b[AES_BLOCK_SIZE]; ++ u8 s_0[AES_BLOCK_SIZE]; ++ u8 e[AES_BLOCK_SIZE]; ++ u8 *pos, *cpos; + - if (data_len == 0) - return -EINVAL; -- ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); ++ last_len = data_len % AES_BLOCK_SIZE; ++ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b); + - aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); - if (!aead_req) - return -ENOMEM; -- ++ /* Process payload blocks */ ++ pos = data; ++ cpos = data; ++ for (j = 1; j <= num_blocks; j++) { ++ int blen = (j == num_blocks && last_len) ? ++ last_len : AES_BLOCK_SIZE; + - __aad = (u8 *)aead_req + reqsize; - memcpy(__aad, aad, CCM_AAD_LEN); -- ++ /* Authentication followed by encryption */ ++ for (i = 0; i < blen; i++) ++ b[i] ^= pos[i]; ++ crypto_cipher_encrypt_one(tfm, b, b); + - sg_init_table(sg, 3); - sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); - sg_set_buf(&sg[1], data, data_len); - sg_set_buf(&sg[2], mic, mic_len); -- ++ b_0[14] = (j >> 8) & 0xff; ++ b_0[15] = j & 0xff; ++ crypto_cipher_encrypt_one(tfm, e, b_0); ++ for (i = 0; i < blen; i++) ++ *cpos++ = *pos++ ^ e[i]; ++ } + - aead_request_set_tfm(aead_req, tfm); - aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); - aead_request_set_ad(aead_req, sg[0].length); ++ for (i = 0; i < mic_len; i++) ++ mic[i] = b[i] ^ s_0[i]; ++} + +- err = crypto_aead_decrypt(aead_req); +- kzfree(aead_req); ++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len) ++{ + int i, j, last_len, num_blocks; + u8 *pos, *cpos; + u8 a[AES_BLOCK_SIZE]; + u8 b[AES_BLOCK_SIZE]; + u8 s_0[AES_BLOCK_SIZE]; -+ + +- return err; + num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); + last_len = data_len % AES_BLOCK_SIZE; + aes_ccm_prepare(tfm, b_0, aad, s_0, a, b); @@ -185,11 +181,7 @@ + if ((mic[i] ^ s_0[i]) != a[i]) + return -1; + } - -- err = crypto_aead_decrypt(aead_req); -- kzfree(aead_req); -- -- return err; ++ + return 0; } @@ -202,12 +194,12 @@ { - struct crypto_aead *tfm; - int err; -+ struct crypto_cipher *tfm; - +- - tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - return tfm; -- ++ struct crypto_cipher *tfm; + - err = crypto_aead_setkey(tfm, key, key_len); - if (err) - goto free_aead; diff --git a/package/kernel/mac80211/patches/130-disable-fils.patch b/package/kernel/mac80211/patches/130-disable-fils.patch new file mode 100644 index 000000000..1f0358987 --- /dev/null +++ b/package/kernel/mac80211/patches/130-disable-fils.patch @@ -0,0 +1,32 @@ +Disable FILS support, since it pulls in crypto hash support + +--- a/net/mac80211/fils_aead.h ++++ b/net/mac80211/fils_aead.h +@@ -10,7 +10,7 @@ + #ifndef FILS_AEAD_H + #define FILS_AEAD_H + +-#if LINUX_VERSION_IS_GEQ(4,3,0) ++#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */ + int fils_encrypt_assoc_req(struct sk_buff *skb, + struct ieee80211_mgd_assoc_data *assoc_data); + int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata, +--- a/net/mac80211/fils_aead.c ++++ b/net/mac80211/fils_aead.c +@@ -1,4 +1,4 @@ +-#if LINUX_VERSION_IS_GEQ(4,3,0) ++#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */ + /* + * FILS AEAD for (Re)Association Request/Response frames + * Copyright 2016, Qualcomm Atheros, Inc. +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -550,7 +550,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + NL80211_FEATURE_MAC_ON_CREATE | + NL80211_FEATURE_USERSPACE_MPM | + NL80211_FEATURE_FULL_AP_CLIENT_STATE; +-#if LINUX_VERSION_IS_GEQ(4,3,0) ++#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */ + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA); + #endif + diff --git a/package/kernel/mac80211/patches/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch b/package/kernel/mac80211/patches/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch new file mode 100644 index 000000000..f2bee9b05 --- /dev/null +++ b/package/kernel/mac80211/patches/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch @@ -0,0 +1,198 @@ +From: Felix Fietkau +Date: Sat, 7 Oct 2017 09:37:28 +0200 +Subject: [PATCH] Revert "mac80211: aes-cmac: switch to shash CMAC + driver" + +This reverts commit 26717828b75dd5c46e97f7f4a9b937d038bb2852. +Reduces mac80211 dependencies for LEDE + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/aes_cmac.c ++++ b/net/mac80211/aes_cmac.c +@@ -22,50 +22,126 @@ + #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */ + #define AAD_LEN 20 + +-static const u8 zero[CMAC_TLEN_256]; + +-void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, +- const u8 *data, size_t data_len, u8 *mic) ++void gf_mulx(u8 *pad) + { +- SHASH_DESC_ON_STACK(desc, tfm); +- u8 out[AES_BLOCK_SIZE]; ++ int i, carry; + +- desc->tfm = tfm; ++ carry = pad[0] & 0x80; ++ for (i = 0; i < AES_BLOCK_SIZE - 1; i++) ++ pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); ++ pad[AES_BLOCK_SIZE - 1] <<= 1; ++ if (carry) ++ pad[AES_BLOCK_SIZE - 1] ^= 0x87; ++} + +- crypto_shash_init(desc); +- crypto_shash_update(desc, aad, AAD_LEN); +- crypto_shash_update(desc, data, data_len - CMAC_TLEN); +- crypto_shash_finup(desc, zero, CMAC_TLEN, out); ++void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, ++ const u8 *addr[], const size_t *len, u8 *mac, ++ size_t mac_len) ++{ ++ u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; ++ const u8 *pos, *end; ++ size_t i, e, left, total_len; + +- memcpy(mic, out, CMAC_TLEN); ++ memset(cbc, 0, AES_BLOCK_SIZE); ++ ++ total_len = 0; ++ for (e = 0; e < num_elem; e++) ++ total_len += len[e]; ++ left = total_len; ++ ++ e = 0; ++ pos = addr[0]; ++ end = pos + len[0]; ++ ++ while (left >= AES_BLOCK_SIZE) { ++ for (i = 0; i < AES_BLOCK_SIZE; i++) { ++ cbc[i] ^= *pos++; ++ if (pos >= end) { ++ e++; ++ pos = addr[e]; ++ end = pos + len[e]; ++ } ++ } ++ if (left > AES_BLOCK_SIZE) ++ crypto_cipher_encrypt_one(tfm, cbc, cbc); ++ left -= AES_BLOCK_SIZE; ++ } ++ ++ memset(pad, 0, AES_BLOCK_SIZE); ++ crypto_cipher_encrypt_one(tfm, pad, pad); ++ gf_mulx(pad); ++ ++ if (left || total_len == 0) { ++ for (i = 0; i < left; i++) { ++ cbc[i] ^= *pos++; ++ if (pos >= end) { ++ e++; ++ pos = addr[e]; ++ end = pos + len[e]; ++ } ++ } ++ cbc[left] ^= 0x80; ++ gf_mulx(pad); ++ } ++ ++ for (i = 0; i < AES_BLOCK_SIZE; i++) ++ pad[i] ^= cbc[i]; ++ crypto_cipher_encrypt_one(tfm, pad, pad); ++ memcpy(mac, pad, mac_len); + } + +-void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, ++ ++void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, ++ const u8 *data, size_t data_len, u8 *mic) ++{ ++ const u8 *addr[3]; ++ size_t len[3]; ++ u8 zero[CMAC_TLEN]; ++ ++ memset(zero, 0, CMAC_TLEN); ++ addr[0] = aad; ++ len[0] = AAD_LEN; ++ addr[1] = data; ++ len[1] = data_len - CMAC_TLEN; ++ addr[2] = zero; ++ len[2] = CMAC_TLEN; ++ ++ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN); ++} ++ ++void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic) + { +- SHASH_DESC_ON_STACK(desc, tfm); ++ const u8 *addr[3]; ++ size_t len[3]; ++ u8 zero[CMAC_TLEN_256]; + +- desc->tfm = tfm; ++ memset(zero, 0, CMAC_TLEN_256); ++ addr[0] = aad; ++ len[0] = AAD_LEN; ++ addr[1] = data; ++ len[1] = data_len - CMAC_TLEN_256; ++ addr[2] = zero; ++ len[2] = CMAC_TLEN_256; + +- crypto_shash_init(desc); +- crypto_shash_update(desc, aad, AAD_LEN); +- crypto_shash_update(desc, data, data_len - CMAC_TLEN_256); +- crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic); ++ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256); + } + +-struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], +- size_t key_len) ++struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], ++ size_t key_len) + { +- struct crypto_shash *tfm; ++ struct crypto_cipher *tfm; + +- tfm = crypto_alloc_shash("cmac(aes)", 0, 0); ++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + if (!IS_ERR(tfm)) +- crypto_shash_setkey(tfm, key, key_len); ++ crypto_cipher_setkey(tfm, key, key_len); + + return tfm; + } + +-void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm) ++ ++void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) + { +- crypto_free_shash(tfm); ++ crypto_free_cipher(tfm); + } +--- a/net/mac80211/aes_cmac.h ++++ b/net/mac80211/aes_cmac.h +@@ -10,14 +10,13 @@ + #define AES_CMAC_H + + #include +-#include + +-struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], +- size_t key_len); +-void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, ++struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], ++ size_t key_len); ++void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic); +-void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, ++void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic); +-void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm); ++void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); + + #endif /* AES_CMAC_H */ +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -93,7 +93,7 @@ struct ieee80211_key { + } ccmp; + struct { + u8 rx_pn[IEEE80211_CMAC_PN_LEN]; +- struct crypto_shash *tfm; ++ struct crypto_cipher *tfm; + u32 replays; /* dot11RSNAStatsCMACReplays */ + u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ + } aes_cmac; diff --git a/package/kernel/mac80211/patches/132-mac80211-remove-cmac-dependency.patch b/package/kernel/mac80211/patches/132-mac80211-remove-cmac-dependency.patch new file mode 100644 index 000000000..9d185e61e --- /dev/null +++ b/package/kernel/mac80211/patches/132-mac80211-remove-cmac-dependency.patch @@ -0,0 +1,10 @@ +--- a/net/mac80211/Kconfig ++++ b/net/mac80211/Kconfig +@@ -5,7 +5,6 @@ config MAC80211 + depends on CRYPTO + depends on CRYPTO_ARC4 + depends on CRYPTO_AES +- depends on CRYPTO_CMAC + depends on CRC32 + ---help--- + This option enables the hardware independent IEEE 802.11 diff --git a/package/kernel/mac80211/patches/301-ath9k_hw-issue-external-reset-for-QCA955x.patch b/package/kernel/mac80211/patches/301-ath9k_hw-issue-external-reset-for-QCA955x.patch index 5eb69b898..34d7d3b1c 100644 --- a/package/kernel/mac80211/patches/301-ath9k_hw-issue-external-reset-for-QCA955x.patch +++ b/package/kernel/mac80211/patches/301-ath9k_hw-issue-external-reset-for-QCA955x.patch @@ -29,21 +29,6 @@ Signed-off-by: Felix Fietkau - npend = ath9k_hw_numtxpending(ah, i); - if (npend) - break; -- } -- -- if (ah->external_reset && -- (npend || type == ATH9K_RESET_COLD)) { -- int reset_err = 0; -- -- ath_dbg(ath9k_hw_common(ah), RESET, -- "reset MAC via external reset\n"); -- -- reset_err = ah->external_reset(); -- if (reset_err) { -- ath_err(ath9k_hw_common(ah), -- "External reset failed, err=%d\n", -- reset_err); -- return false; + if (type == ATH9K_RESET_COLD) + return true; + @@ -59,35 +44,47 @@ Signed-off-by: Felix Fietkau + for (i = 0; i < AR_NUM_QCU; i++) { + if (ath9k_hw_numtxpending(ah, i)) + return true; - } -+ } -+ ++ } + } + +- if (ah->external_reset && +- (npend || type == ATH9K_RESET_COLD)) { +- int reset_err = 0; + return false; +} -+ + +- ath_dbg(ath9k_hw_common(ah), RESET, +- "reset MAC via external reset\n"); +static bool ath9k_hw_external_reset(struct ath_hw *ah, int type) +{ + int err; -+ + +- reset_err = ah->external_reset(); +- if (reset_err) { +- ath_err(ath9k_hw_common(ah), +- "External reset failed, err=%d\n", +- reset_err); +- return false; +- } + if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type)) + return true; -+ -+ ath_dbg(ath9k_hw_common(ah), RESET, -+ "reset MAC via external reset\n"); - REG_WRITE(ah, AR_RTC_RESET, 1); ++ ath_dbg(ath9k_hw_common(ah), RESET, ++ "reset MAC via external reset\n"); ++ + err = ah->external_reset(); + if (err) { + ath_err(ath9k_hw_common(ah), + "External reset failed, err=%d\n", err); + return false; - } - ++ } ++ + if (AR_SREV_9550(ah)) { + REG_WRITE(ah, AR_RTC_RESET, 0); + udelay(10); -+ } -+ + } + + REG_WRITE(ah, AR_RTC_RESET, 1); + udelay(10); + diff --git a/package/kernel/mac80211/patches/324-ath9k_hw-fix-channel-maximum-power-level-test.patch b/package/kernel/mac80211/patches/314-ath9k_hw-fix-channel-maximum-power-level-test.patch similarity index 100% rename from package/kernel/mac80211/patches/324-ath9k_hw-fix-channel-maximum-power-level-test.patch rename to package/kernel/mac80211/patches/314-ath9k_hw-fix-channel-maximum-power-level-test.patch diff --git a/package/kernel/mac80211/patches/330-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch b/package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch similarity index 91% rename from package/kernel/mac80211/patches/330-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch rename to package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch index d799ab4a6..59e4ddee3 100644 --- a/package/kernel/mac80211/patches/330-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch +++ b/package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch @@ -1,6 +1,7 @@ From: Felix Fietkau Date: Wed, 19 Jul 2017 08:49:31 +0200 -Subject: [PATCH] ath9k: adjust tx power reduction for US regulatory domain +Subject: [PATCH] ath9k: adjust tx power reduction for US regulatory + domain FCC regulatory rules allow for up to 3 dBi antenna gain. Account for this in the EEPROM based tx power reduction code. @@ -16,7 +17,7 @@ Signed-off-by: Felix Fietkau + /* FCC allows maximum antenna gain of 3 dBi */ + if (reg->region == NL80211_DFS_FCC) -+ ant_reduction = max_t(int, ant_reduction - 6, 0); ++ ant_reduction = min_t(int, ant_reduction - 6, 0); + ah->eep_ops->set_txpower(ah, chan, ctl, ant_reduction, new_pwr, test); } diff --git a/package/kernel/mac80211/patches/331-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch b/package/kernel/mac80211/patches/316-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch similarity index 99% rename from package/kernel/mac80211/patches/331-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch rename to package/kernel/mac80211/patches/316-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch index 1e0761eb1..096eb56a2 100644 --- a/package/kernel/mac80211/patches/331-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch +++ b/package/kernel/mac80211/patches/316-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch @@ -1,6 +1,7 @@ From: Felix Fietkau Date: Sun, 23 Jul 2017 14:58:22 +0200 -Subject: [PATCH] ath9k: fix more-data flag for buffered multicast packets +Subject: [PATCH] ath9k: fix more-data flag for buffered multicast + packets The flag needs to be cleared for the last packet in the list, not the first one. Fixes some issues with multicast packet loss for powersave diff --git a/package/kernel/mac80211/patches/332-ath10k-Revert-disable-wake_tx_queue-for-older-devices.patch b/package/kernel/mac80211/patches/317-Revert-ath10k-disable-wake_tx_queue-for-older-device.patch similarity index 85% rename from package/kernel/mac80211/patches/332-ath10k-Revert-disable-wake_tx_queue-for-older-devices.patch rename to package/kernel/mac80211/patches/317-Revert-ath10k-disable-wake_tx_queue-for-older-device.patch index f1bd131f3..5e18f285a 100644 --- a/package/kernel/mac80211/patches/332-ath10k-Revert-disable-wake_tx_queue-for-older-devices.patch +++ b/package/kernel/mac80211/patches/317-Revert-ath10k-disable-wake_tx_queue-for-older-device.patch @@ -1,7 +1,7 @@ -From 59f8c22bf1749c4a2b5947bfaebc677c259a1ad6 Mon Sep 17 00:00:00 2001 From: dave taht Date: Wed, 5 Oct 2016 20:09:15 -0700 -Subject: [PATCH 5/7] Revert "ath10k: disable wake_tx_queue for older devices" +Subject: [PATCH] Revert "ath10k: disable wake_tx_queue for older + devices" This reverts commit 4ca1807815aa6801aaced7fdefa9edacc2521767 in the hope that we've fixed all the performance problems now. diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch index 01de325b9..72857a0db 100644 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -36,9 +36,9 @@ u8 ps_dtim_period; --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -2139,6 +2139,9 @@ enum nl80211_commands { - * the driver or is not needed (because roaming used the Fast Transition - * protocol). +@@ -2149,6 +2149,9 @@ enum nl80211_commands { + * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT. + * @NL80211_ATTR_PORT_AUTHORIZED: (reserved) * + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce + * transmit power to stay within regulatory limits. u32, dBi. @@ -46,7 +46,7 @@ * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -2565,6 +2568,8 @@ enum nl80211_attrs { +@@ -2575,6 +2578,8 @@ enum nl80211_attrs { NL80211_ATTR_PMKR0_NAME, NL80211_ATTR_PORT_AUTHORIZED, @@ -137,7 +137,7 @@ }; /* policy for the key attributes */ -@@ -2378,6 +2379,20 @@ static int nl80211_set_wiphy(struct sk_b +@@ -2395,6 +2396,20 @@ static int nl80211_set_wiphy(struct sk_b if (result) return result; } diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch index 8ea2f79a2..9084ea7db 100644 --- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch +++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch @@ -103,7 +103,8 @@ + GFP_KERNEL); + if (!led) + return -ENOMEM; -+ + +- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); + led->gpio = gpio = (struct gpio_led *) (led + 1); + _name = (char *) (led->gpio + 1); + @@ -116,8 +117,7 @@ + ret = ath_add_led(sc, led); + if (unlikely(ret < 0)) + kfree(led); - -- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); ++ + return ret; } @@ -125,11 +125,11 @@ { - if (!sc->led_registered) - return; -+ struct ath_led *led; - +- - ath_led_brightness(&sc->led_cdev, LED_OFF); - led_classdev_unregister(&sc->led_cdev); -- ++ struct ath_led *led; + - ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin); + while (!list_empty(&sc->leds)) { + led = list_first_entry(&sc->leds, struct ath_led, list); diff --git a/package/kernel/mac80211/patches/653-0043-rtl8xxxu-Do-not-set-auto-rate-fallback-on-8188eu.patch b/package/kernel/mac80211/patches/653-0043-rtl8xxxu-Do-not-set-auto-rate-fallback-on-8188eu.patch index c69de5b0a..1047625de 100644 --- a/package/kernel/mac80211/patches/653-0043-rtl8xxxu-Do-not-set-auto-rate-fallback-on-8188eu.patch +++ b/package/kernel/mac80211/patches/653-0043-rtl8xxxu-Do-not-set-auto-rate-fallback-on-8188eu.patch @@ -39,7 +39,7 @@ Signed-off-by: Jes Sorensen .adda_2t_path_on_a = 0x04db25a4, --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c -@@ -1655,6 +1655,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops = +@@ -1658,6 +1658,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops = .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), .has_s0s1 = 0, .gen2_thermal_meter = 1, diff --git a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch index 7c1841b77..43f8fbf67 100644 --- a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch +++ b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2849,6 +2849,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip +@@ -2838,6 +2838,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip * preference in cfg struct to apply this to * FW later while initializing the dongle */ From 02d192142392c12faad545cc573c7f041c5d0a53 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Fri, 13 Oct 2017 22:49:38 +0800 Subject: [PATCH 07/15] mt76: update to the latest version --- package/kernel/mt76/Makefile | 6 +- .../mt76/patches/001-mac80211-4-14-api.patch | 86 ------------------- 2 files changed, 3 insertions(+), 89 deletions(-) delete mode 100644 package/kernel/mt76/patches/001-mac80211-4-14-api.patch diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 01b5f5286..3428ea1f7 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2017-09-10 -PKG_SOURCE_VERSION:=d5e945e9b2ee8f52581c1a6978097cf30c39cfd9 -PKG_MIRROR_HASH:=276eb2eea7b5ae64424292c5d955a8543fd3e39a2125b8046a30a519be76f3c9 +PKG_SOURCE_DATE:=2017-10-12 +PKG_SOURCE_VERSION:=37654d704772512065cd28b007342758c2a0f14a +PKG_MIRROR_HASH:=487ca40ed4e1ffe015dabc76c0a84782602d84f5b08c9c86cc6c892cb499623b PKG_MAINTAINER:=Felix Fietkau PKG_BUILD_PARALLEL:=1 diff --git a/package/kernel/mt76/patches/001-mac80211-4-14-api.patch b/package/kernel/mt76/patches/001-mac80211-4-14-api.patch deleted file mode 100644 index 6cff15b19..000000000 --- a/package/kernel/mt76/patches/001-mac80211-4-14-api.patch +++ /dev/null @@ -1,86 +0,0 @@ ---- a/mt76x2_mac.c -+++ b/mt76x2_mac.c -@@ -46,7 +46,7 @@ mt76x2_mac_process_rate(struct ieee80211 - case MT_PHY_TYPE_CCK: - if (idx >= 8) { - idx -= 8; -- status->flag |= RX_FLAG_SHORTPRE; -+ status->enc_flags |= RX_ENC_FLAG_SHORTPRE; - } - - if (idx >= 4) -@@ -55,16 +55,16 @@ mt76x2_mac_process_rate(struct ieee80211 - status->rate_idx = idx; - return; - case MT_PHY_TYPE_HT_GF: -- status->flag |= RX_FLAG_HT_GF; -+ status->enc_flags |= RX_ENC_FLAG_HT_GF; - /* fall through */ - case MT_PHY_TYPE_HT: -- status->flag |= RX_FLAG_HT; -+ status->encoding = RX_ENC_HT; - status->rate_idx = idx; - break; - case MT_PHY_TYPE_VHT: -- status->flag |= RX_FLAG_VHT; -+ status->encoding = RX_ENC_VHT; - status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx); -- status->vht_nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1; -+ status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1; - break; - default: - WARN_ON(1); -@@ -72,22 +72,22 @@ mt76x2_mac_process_rate(struct ieee80211 - } - - if (rate & MT_RXWI_RATE_LDPC) -- status->flag |= RX_FLAG_LDPC; -+ status->enc_flags |= RX_ENC_FLAG_LDPC; - - if (rate & MT_RXWI_RATE_SGI) -- status->flag |= RX_FLAG_SHORT_GI; -+ status->enc_flags |= RX_ENC_FLAG_SHORT_GI; - - if (rate & MT_RXWI_RATE_STBC) -- status->flag |= 1 << RX_FLAG_STBC_SHIFT; -+ status->enc_flags |= 1 << RX_ENC_FLAG_STBC_SHIFT; - - switch (FIELD_GET(MT_RXWI_RATE_BW, rate)) { - case MT_PHY_BW_20: - break; - case MT_PHY_BW_40: -- status->flag |= RX_FLAG_40MHZ; -+ status->bw = RATE_INFO_BW_40; - break; - case MT_PHY_BW_80: -- status->vht_flag |= RX_VHT_FLAG_80MHZ; -+ status->bw = RATE_INFO_BW_80; - break; - default: - break; ---- a/mt7603_mac.c -+++ b/mt7603_mac.c -@@ -411,19 +411,19 @@ mt7603_mac_fill_rx(struct mt7603_dev *de - break; - case MT_PHY_TYPE_HT_GF: - case MT_PHY_TYPE_HT: -- status->flag |= RX_FLAG_HT; -+ status->encoding = RX_ENC_HT; - break; - case MT_PHY_TYPE_VHT: -- status->flag |= RX_FLAG_VHT; -+ status->encoding = RX_ENC_VHT; - break; - default: - WARN_ON(1); - } - - if (rxdg0 & MT_RXV1_HT_SHORT_GI) -- status->flag |= RX_FLAG_SHORT_GI; -+ status->enc_flags |= RX_ENC_FLAG_SHORT_GI; - -- status->flag |= RX_FLAG_STBC_MASK * -+ status->enc_flags |= RX_ENC_FLAG_STBC_MASK * - FIELD_GET(MT_RXV1_HT_STBC, rxdg0); - - status->rate_idx = i; From de8c536beffe0e35f87e1c0c81611600f35e9ddd Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Fri, 13 Oct 2017 22:54:05 +0800 Subject: [PATCH 08/15] kernel: add fix for bgmac with BCM B50212E B1 PHY --- ...-master-mode-for-BCM54210E-and-B5021.patch | 50 +++++++++++++++++ ...-support-new-device-flag-for-setting.patch | 54 +++++++++++++++++++ .../hack-4.9/773-bgmac-add-srab-switch.patch | 2 +- ...-master-mode-for-BCM54210E-and-B5021.patch | 50 +++++++++++++++++ ...ick-Broadcom-drivers-updates-from-v4.patch | 3 +- ...ck-Broadcom-drivers-updates-from-v4.patch} | 12 ++++- ...ick-Broadcom-drivers-updates-from-v4.patch | 37 +++++++++++++ .../773-bgmac-add-srab-switch.patch | 2 +- 8 files changed, 204 insertions(+), 6 deletions(-) create mode 100644 target/linux/generic/backport-4.9/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch create mode 100644 target/linux/generic/backport-4.9/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch create mode 100644 target/linux/generic/pending-4.4/073-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch rename target/linux/generic/pending-4.4/{078-0004-net-phy-pick-Broadcom-drivers-updates-from-net-next-.patch => 078-0004-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch} (93%) create mode 100644 target/linux/generic/pending-4.4/078-0006-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch diff --git a/target/linux/generic/backport-4.9/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch b/target/linux/generic/backport-4.9/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch new file mode 100644 index 000000000..c371e6355 --- /dev/null +++ b/target/linux/generic/backport-4.9/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 +@@ -159,13 +159,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.9/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch b/target/linux/generic/backport-4.9/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch new file mode 100644 index 000000000..334c44469 --- /dev/null +++ b/target/linux/generic/backport-4.9/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 +@@ -59,6 +59,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/hack-4.9/773-bgmac-add-srab-switch.patch b/target/linux/generic/hack-4.9/773-bgmac-add-srab-switch.patch index c865177c2..e6ad0a51d 100644 --- a/target/linux/generic/hack-4.9/773-bgmac-add-srab-switch.patch +++ b/target/linux/generic/hack-4.9/773-bgmac-add-srab-switch.patch @@ -14,7 +14,7 @@ Signed-off-by: Hauke Mehrtens --- a/drivers/net/ethernet/broadcom/bgmac-bcma.c +++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c -@@ -230,6 +230,7 @@ static int bgmac_probe(struct bcma_devic +@@ -236,6 +236,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; diff --git a/target/linux/generic/pending-4.4/073-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch b/target/linux/generic/pending-4.4/073-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch new file mode 100644 index 000000000..27cd660b5 --- /dev/null +++ b/target/linux/generic/pending-4.4/073-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 +@@ -159,13 +159,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 = bgmac->mii_bus->phy_map[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/pending-4.4/078-0003-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch b/target/linux/generic/pending-4.4/078-0003-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch index bf8818976..1d943d605 100644 --- a/target/linux/generic/pending-4.4/078-0003-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch +++ b/target/linux/generic/pending-4.4/078-0003-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch @@ -1,6 +1,5 @@ From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Subject: [PATCH 1/2] net: phy: cherry-pick Broadcom drivers updates from - v4.10-rc1 +Subject: [PATCH] net: phy: cherry-pick Broadcom drivers updates from v4.10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/target/linux/generic/pending-4.4/078-0004-net-phy-pick-Broadcom-drivers-updates-from-net-next-.patch b/target/linux/generic/pending-4.4/078-0004-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch similarity index 93% rename from target/linux/generic/pending-4.4/078-0004-net-phy-pick-Broadcom-drivers-updates-from-net-next-.patch rename to target/linux/generic/pending-4.4/078-0004-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch index 794753ffa..269c4e724 100644 --- a/target/linux/generic/pending-4.4/078-0004-net-phy-pick-Broadcom-drivers-updates-from-net-next-.patch +++ b/target/linux/generic/pending-4.4/078-0004-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch @@ -1,10 +1,18 @@ From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Subject: [PATCH 2/2] net: phy: pick Broadcom drivers updates from net-next for - 4.11 +Subject: [PATCH] net: phy: cherry-pick Broadcom drivers updates from v4.11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +This includes following upstream commits: +62e13097c46c net: phy: broadcom: rehook BCM54612E specific init +0fc9ae107669 net: phy: broadcom: add support for BCM54210E +5e7bfa6cb0a9 net: phy: bcm-phy-lib: clean up remaining AUXCTL register defines +8293c7bcdef1 net: phy: broadcom: drop duplicated define for RGMII SKEW delay +85b4685da52f net: phy: broadcom: use auxctl reading helper in BCM54612E code +039a7b8592ab net: phy: bcm7xxx: Implement EGPHY workaround for 7278 +582d0ac397ca net: phy: bcm7xxx: Add entry for BCM7278 + Signed-off-by: Rafał Miłecki --- diff --git a/target/linux/generic/pending-4.4/078-0006-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch b/target/linux/generic/pending-4.4/078-0006-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch new file mode 100644 index 000000000..c39995da7 --- /dev/null +++ b/target/linux/generic/pending-4.4/078-0006-net-phy-cherry-pick-Broadcom-drivers-updates-from-v4.patch @@ -0,0 +1,37 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] net: phy: cherry-pick Broadcom drivers updates from v4.15 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This includes following upstream commits: +2355a6546a05 net: phy: broadcom: support new device flag for setting master mode + +Signed-off-by: Rafał Miłecki +--- + +--- 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 +@@ -59,6 +59,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/pending-4.4/773-bgmac-add-srab-switch.patch b/target/linux/generic/pending-4.4/773-bgmac-add-srab-switch.patch index 5e358c38c..b3cb08723 100644 --- a/target/linux/generic/pending-4.4/773-bgmac-add-srab-switch.patch +++ b/target/linux/generic/pending-4.4/773-bgmac-add-srab-switch.patch @@ -78,7 +78,7 @@ Signed-off-by: Hauke Mehrtens struct bgmac *bgmac_alloc(struct device *dev); --- a/drivers/net/ethernet/broadcom/bgmac-bcma.c +++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c -@@ -230,6 +230,7 @@ static int bgmac_probe(struct bcma_devic +@@ -236,6 +236,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; From ca5177545ca6324dbb6b9c55d9ef9a6db73de7dc Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Fri, 13 Oct 2017 23:03:00 +0800 Subject: [PATCH 09/15] fix luci-app-kcptun makefile --- package/lean/luci-app-kcptun/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/lean/luci-app-kcptun/Makefile b/package/lean/luci-app-kcptun/Makefile index c569e5c94..fcdc65d47 100644 --- a/package/lean/luci-app-kcptun/Makefile +++ b/package/lean/luci-app-kcptun/Makefile @@ -20,7 +20,7 @@ define Package/$(PKG_NAME)/conffiles /etc/config/kcptun endef -include $(TOPDIR)/feeds/luci.mk +include $(TOPDIR)/feeds/luci/luci.mk define Package/$(PKG_NAME)/postinst #!/bin/sh From 0b130e4e18114569d4603485b91bb748b310772d Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sat, 14 Oct 2017 13:09:10 +0800 Subject: [PATCH 10/15] update packages source to 17.01.3 --- include/version.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/version.mk b/include/version.mk index b078516dd..561ab5952 100644 --- a/include/version.mk +++ b/include/version.mk @@ -40,7 +40,7 @@ VERSION_NICK:=$(call qstrip_escape,$(CONFIG_VERSION_NICK)) VERSION_NICK:=$(if $(VERSION_NICK),$(VERSION_NICK),$(RELEASE)) VERSION_REPO:=$(call qstrip_escape,$(CONFIG_VERSION_REPO)) -VERSION_REPO:=$(if $(VERSION_REPO),$(VERSION_REPO),http://downloads.lede-project.org/releases/17.01.2) +VERSION_REPO:=$(if $(VERSION_REPO),$(VERSION_REPO),http://downloads.lede-project.org/releases/17.01.3) VERSION_DIST:=$(call qstrip_escape,$(CONFIG_VERSION_DIST)) VERSION_DIST:=$(if $(VERSION_DIST),$(VERSION_DIST),LEDE) From 53eada2a47f61ee4445315a2adffc0c6f726960e Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sat, 14 Oct 2017 13:16:17 +0800 Subject: [PATCH 11/15] dnsmasq: add listen_address parameter --- package/network/services/dnsmasq/Makefile | 2 +- package/network/services/dnsmasq/files/dnsmasq.init | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index 33644e8e5..dd9df245a 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq PKG_VERSION:=2.78 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/ diff --git a/package/network/services/dnsmasq/files/dnsmasq.init b/package/network/services/dnsmasq/files/dnsmasq.init index 014964395..3d3d83334 100644 --- a/package/network/services/dnsmasq/files/dnsmasq.init +++ b/package/network/services/dnsmasq/files/dnsmasq.init @@ -142,6 +142,10 @@ append_interface() { xappend "--interface=$ifname" } +append_listenaddress() { + xappend "--listen-address=$1" +} + append_notinterface() { network_get_device ifname "$1" || ifname="$1" xappend "--except-interface=$ifname" @@ -835,6 +839,7 @@ dnsmasq_start() append_parm "$cfg" "maxport" "--max-port" append_parm "$cfg" "domain" "--domain" append_parm "$cfg" "local" "--server" + config_list_foreach "$cfg" "listen_address" append_listenaddress config_list_foreach "$cfg" "server" append_server config_list_foreach "$cfg" "rev_server" append_rev_server config_list_foreach "$cfg" "address" append_address From 21846b9d088431e80c7169e54816a0d2292375e9 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sat, 14 Oct 2017 13:17:48 +0800 Subject: [PATCH 12/15] mac80211: fix tx power regression for ath9k --- ...5-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch b/package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch index 59e4ddee3..78083517b 100644 --- a/package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch +++ b/package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau + /* FCC allows maximum antenna gain of 3 dBi */ + if (reg->region == NL80211_DFS_FCC) -+ ant_reduction = min_t(int, ant_reduction - 6, 0); ++ ant_reduction = max_t(int, ant_reduction - 6, 0); + ah->eep_ops->set_txpower(ah, chan, ctl, ant_reduction, new_pwr, test); } From 301df3d43149fb5cecc7dfe0d236e36786083924 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sat, 14 Oct 2017 13:19:52 +0800 Subject: [PATCH 13/15] kernel: bump 4.4 to 4.4.92 --- include/kernel-version.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/kernel-version.mk b/include/kernel-version.mk index eb41da3d2..405e5fd52 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -3,11 +3,11 @@ LINUX_RELEASE?=1 LINUX_VERSION-3.18 = .71 -LINUX_VERSION-4.4 = .91 +LINUX_VERSION-4.4 = .92 LINUX_VERSION-4.9 = .54 LINUX_KERNEL_HASH-3.18.71 = 5abc9778ad44ce02ed6c8ab52ece8a21c6d20d21f6ed8a19287b4a38a50c1240 -LINUX_KERNEL_HASH-4.4.91 = cb9d2b8c1afe58414de5bc7d65429cc9f5f37c80fc229d0e83c55c5c3c254ffb +LINUX_KERNEL_HASH-4.4.92 = 53f8cd8b024444df0f242f8e6ab5147b0b009d7a30e8b2ed3854e8d17937460d LINUX_KERNEL_HASH-4.9.54 = 651005db6efbce4fcd607415ebd697dd8d2f5a2abc2c632b11ece03a1a210fc5 ifdef KERNEL_PATCHVER From b182dd2f63f2ba6e8a8ddc0fd0ccf55c72f95b78 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sat, 14 Oct 2017 13:35:16 +0800 Subject: [PATCH 14/15] add he-6in4 package to auto-update he 6in4 tunnel --- package/lean/he-6in4/Makefile | 58 +++++++++++++++++++ .../files/root/etc/hotplug.d/iface/60-6in4 | 12 ++++ 2 files changed, 70 insertions(+) create mode 100644 package/lean/he-6in4/Makefile create mode 100644 package/lean/he-6in4/files/root/etc/hotplug.d/iface/60-6in4 diff --git a/package/lean/he-6in4/Makefile b/package/lean/he-6in4/Makefile new file mode 100644 index 000000000..8dcb6978c --- /dev/null +++ b/package/lean/he-6in4/Makefile @@ -0,0 +1,58 @@ +# +# Copyright (C) 2015 OpenWrt-dist +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=he-6in4 +PKG_VERSION:=1.0 +PKG_RELEASE:=1 + +PKG_LICENSE:=GPLv3 +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=ghostry + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/he-6in4 + SECTION:=ipv6 + CATEGORY:=Gmod + SUBMENU:=Network + TITLE:=Dynamic Update he.net of ip + PKGARCH:=all + DEPENDS:=+luci-proto-ipv6 +6in4 +curl +endef + +define Package/he-6in4/description + Dynamic Update he.net of ip +endef + +define Build/Prepare +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/he-6in4/postinst +#!/bin/sh +if [ -z "$${IPKG_INSTROOT}" ]; then + chmod 755 /etc/hotplug.d/iface/60-6in4 >/dev/null 2>&1 +fi +exit 0 +endef + +define Package/he-6in4/install + $(INSTALL_DIR) $(1)/etc/hotplug.d/iface + $(INSTALL_BIN) ./files/root/etc/hotplug.d/iface/60-6in4 $(1)/etc/hotplug.d/iface/60-6in4 +endef + + +$(eval $(call BuildPackage,he-6in4)) diff --git a/package/lean/he-6in4/files/root/etc/hotplug.d/iface/60-6in4 b/package/lean/he-6in4/files/root/etc/hotplug.d/iface/60-6in4 new file mode 100644 index 000000000..007806083 --- /dev/null +++ b/package/lean/he-6in4/files/root/etc/hotplug.d/iface/60-6in4 @@ -0,0 +1,12 @@ +#!/bin/sh +. /lib/functions.sh +if [ "$ACTION" != "ifup" ]; then + exit +fi +config_load network +config_get tunnelid $INTERFACE tunnelid +config_get username $INTERFACE username +config_get password $INTERFACE password +if [ "$tunnelid" != "" ]; then + curl -k -u "$username":"$password" https://ipv4.tunnelbroker.net/nic/update?hostname=$tunnelid +fi From d8ecfd786bf410e8fa7c5f66b86712cb6550fe5a Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sat, 14 Oct 2017 13:43:04 +0800 Subject: [PATCH 15/15] add luci-theme-atmaterial package --- package/lean/luci-theme-atmaterial/Makefile | 14 + .../luci-static/atmaterial/css/style.css | 1744 +++++++++++++++++ .../htdocs/luci-static/atmaterial/favicon.ico | Bin 0 -> 2462 bytes .../fonts/Roboto-Medium-webfont.woff | Bin 0 -> 70200 bytes .../fonts/Roboto-Regular-webfont.woff | Bin 0 -> 68776 bytes .../atmaterial/fonts/advancedtomato.eot | Bin 0 -> 8480 bytes .../atmaterial/fonts/advancedtomato.svg | 53 + .../atmaterial/fonts/advancedtomato.ttf | Bin 0 -> 8288 bytes .../atmaterial/fonts/advancedtomato.woff | Bin 0 -> 6272 bytes .../luci-static/atmaterial/fonts/font.eot | Bin 0 -> 1912 bytes .../luci-static/atmaterial/fonts/font.svg | 16 + .../luci-static/atmaterial/fonts/font.ttf | Bin 0 -> 1748 bytes .../luci-static/atmaterial/fonts/font.woff | Bin 0 -> 1824 bytes .../luci-static/atmaterial/js/jquery.min.js | 6 + .../luci-static/atmaterial/js/script.js | 236 +++ .../htdocs/luci-static/atmaterial/logo.png | Bin 0 -> 2224 bytes .../luasrc/view/themes/atmaterial/footer.htm | 51 + .../luasrc/view/themes/atmaterial/header.htm | 238 +++ .../etc/uci-defaults/30-luci-theme-atmaterial | 7 + 19 files changed, 2365 insertions(+) create mode 100644 package/lean/luci-theme-atmaterial/Makefile create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/css/style.css create mode 100755 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/favicon.ico create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/Roboto-Medium-webfont.woff create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/Roboto-Regular-webfont.woff create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.eot create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.svg create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.ttf create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.woff create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.eot create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.svg create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.ttf create mode 100644 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.woff create mode 100755 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/js/jquery.min.js create mode 100755 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/js/script.js create mode 100755 package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/logo.png create mode 100755 package/lean/luci-theme-atmaterial/luasrc/view/themes/atmaterial/footer.htm create mode 100755 package/lean/luci-theme-atmaterial/luasrc/view/themes/atmaterial/header.htm create mode 100644 package/lean/luci-theme-atmaterial/root/etc/uci-defaults/30-luci-theme-atmaterial diff --git a/package/lean/luci-theme-atmaterial/Makefile b/package/lean/luci-theme-atmaterial/Makefile new file mode 100644 index 000000000..d0ab1cc0c --- /dev/null +++ b/package/lean/luci-theme-atmaterial/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2008-2014 The LuCI Team +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Advanced Tomato Material +LUCI_DEPENDS:= + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/css/style.css b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/css/style.css new file mode 100644 index 000000000..50ae8660c --- /dev/null +++ b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/css/style.css @@ -0,0 +1,1744 @@ +/** + * Material is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI + * + * luci-theme-material + * Copyright 2015 Lutty Yang + * + * Have a bug? Please create an issue here on GitHub! + * https://github.com/LuttyYang/luci-theme-material/issues + * + * luci-theme-bootstrap: + * Copyright 2008 Steven Barth + * Copyright 2008 Jo-Philipp Wich + * Copyright 2012 David Menting + * + * MUI: + * https://github.com/muicss/mui + * + * Licensed to the public under the Apache License 2.0 + */ + +/* + * Font generate by Icomoon + */ + +@font-face { + font-family: 'Roboto'; + src: local('Roboto Medium'), local('Roboto-Medium'), url('../fonts/Roboto-Medium-webfont.woff') format('woff'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: 'Roboto'; + src: local('Roboto'), local('Roboto Regular'), local('Roboto-Regular'), url('../fonts/Roboto-Regular-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'icomoon'; + src: url('../fonts/font.eot'); + src: url('../fonts/font.eot') format('embedded-opentype'), + url('../fonts/font.ttf') format('truetype'), + url('../fonts/font.woff') format('woff'), + url('../fonts/font.svg') format('svg'); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "advancedtomato"; + src:url("../fonts/advancedtomato.eot"); + src:url("../fonts/advancedtomato.eot?#iefix") format("embedded-opentype"), + url("../fonts/advancedtomato.woff") format("woff"), + url("../fonts/advancedtomato.ttf") format("truetype"), + url("../fonts/advancedtomato.svg#advancedtomato") format("svg"); + font-weight: normal; + font-style: normal; + +} +.cbi-button-up, +.cbi-button-down, +.cbi-value-helpicon, +.showSide, +.main > .loading > span { + font-family: 'icomoon', Roboto !important; + font-size:10px; + speak: none; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-family: Roboto, 'Microsoft Yahei' !important; + font-weight: 500; + line-height: 1.1; + color: inherit; + clear:both; +} + + +html { + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +html, body { + margin: 0px; + padding: 0px; + height: 100%; + font-family: Roboto, 'Microsoft Yahei' !important; + font-size:10pt; + line-height: 150%; + color:#76838f; + /*min-width: 960px;*/ +} + +body div { + line-height:150%; +} + +a { + color: #76838f; + text-decoration: none; +} + +em {font-style:normal !important;} + +select { + padding: 0.36rem 0.8rem; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; +} + +select, +input { + color: #76838f; + padding: 6px 10px; + margin: 0; + height: 34px; + line-height: normal; + font-size: 10pt; + font-family: "Roboto", sans-serif, Helvetica, Arial, sans-serif; + border: 1px solid #e4eaec; + background-color: #fff; + transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + -webkit-transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + outline-style: none; + vertical-align: baseline; + border-radius: 3px; +} + +select:not([multiple="multiple"]):focus, +input:focus { + border-color: #0099CC; +} + +select[multiple="multiple"] { + height: auto; +} + +code { + color: #0099CC; +} + +abbr { + color: #333; + text-decoration: underline; + cursor: help; +} + +hr{ + margin: 1rem 0; + border-color: #EEE; + opacity: 0.1; +} + +header, .main { + width: 100%; + position: absolute; +} + +header { + height: 60px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); + transition: box-shadow .2s; + float: left; + position: fixed; + z-index: 101; +} + +footer { + text-align: right; + padding: 1rem; + color: #aaa; + font-size: 11px; + text-shadow: 0px 0px 2px #BBB; +} + +footer > a { + color: #aaa; + text-decoration: none; +} + +.main { + top: 4rem; + bottom: 0rem; + position: relative; + height: 100%; + height: calc(100% - 4rem); +} + +.main > .loading { + position: fixed; + width: 100%; + height: 100%; + z-index: 1000; + display: block; + background-color: rgb(240, 240, 240); + top: 0; +} + +.main > .loading > span { + display: block; + text-align: center; + margin-top: 2rem; + color: #888; + font-size: 14px; +} + +.main > .loading > span > .loading-img:before { + content: "\e603"; +} + +.main > .loading > span > .loading-img { + animation: anim-rotate 2s infinite linear; + margin-right: 0.2rem; + display: inline-block; +} + +@keyframes anim-rotate { + 0% { + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + } + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +.main-left { + float: left; + top: 4rem; + width: 17rem; + bottom: 0rem; + background-color: #222222; + + overflow-x: auto; + position: fixed; +} + +.main-right { + width: 85%; + width: calc(100% - 17rem); + float: right; + height: 100%; + background-color: #f1f4f5; +} + +.main-right > #maincontent { + background-color: #f1f4f5; +} + +.pull-right { + float: right; + margin-top:10px; + margin-right:10px; +} + +.pull-right span { + font-size:11px !important; +} + +.pull-left { + float: left; +} + +header { + background: #fff; + color: white; +} + +header > .container { +margin:0; +padding:0; +} + +header > .container > .brand { + font-size: 28px; + line-height:60px; + color: white; + cursor: default; + background: #0099CC; + display:block; + width:17rem; + padding-right: 10px; + height:60px; + text-align:center; + float:left; + font-weight:600; + letter-spacing:3px; +} +header > .container > a[class="brand"]:after { + content:"®"; + font-size:14px; + font-family:Tahoma; + position: absolute; + top:-10px; + font-weight:normal !important; +} +.warning { + background-color: #FF7D60 !important; + color: #FFF; +} + +.errorbox, +.alert-message { + margin: 5px 0 0 0; + padding: 2rem; + border: 0; + font-weight: normal; + font-style: normal; + line-height: 1; + font-family: inherit; + min-width: inherit; + overflow: auto; + border-radius: 0; + background-color: #FFF; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); +} + +.errorbox { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} + +.error { + color: red; +} + +#maincontent > .container > div:nth-child(1).alert-message.warning > a { + font: inherit; + overflow: visible; + text-transform: none; + display: inline-block; + margin-bottom: 0; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + min-width: 6rem; + padding: 0.5rem 1rem; + font-size: 14px; + line-height: 1.42857143; + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; + margin-top: 2rem; + text-decoration: inherit; +} + +.main > .main-left > .nav { + margin-top: 2rem; + font-size: 11pt; +} + +.main > .main-left > .nav > li a { + color: #969ba0; + display: block; +} + +.main > .main-left > .nav > li:nth-last-child(1) { + font-size: 11pt; + height:40px; +} + +.main > .main-left > .nav > li { + cursor: pointer; +} + +.main > .main-left > .nav > .slide { + padding: 0; +} +.main > .main-left > .nav > .slide > a[data-title="Status"]:before { + content: "\e026"; + display: inline-block; + top: -1px; + left:-10px; + position: relative; + vertical-align: middle; + display: inline-block; + font-family: "advancedtomato" !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.main > .main-left > .nav > .slide > a:before { + display: inline-block; + top: -1px; + left:-10px; + position: relative; + vertical-align: middle; + display: inline-block; + font-family: "advancedtomato" !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} + + +.main > .main-left > .nav > .slide > a[data-title="Status"]:before { + content: "\e026"; +} + +.main > .main-left > .nav > .slide > a[data-title="System"]:before { + content: "\e00a"; +} + +.main > .main-left > .nav > .slide > a[data-title="Network"]:before { + content: "\e00e"; +} +.main > .main-left > .nav > .slide > a[data-title="Usbapps"]:before { + content: "\e00b"; +} +.main > .main-left > .nav > .slide > a[data-title="Services"]:before { + content: "\e01b"; +} +.main > .main-left > .nav > .slide > a[data-title="NAS"]:before { + content: "\e00b"; +} + +.main > .main-left > .nav > li > a[data-title="Logout"] { + padding-left:36px; + line-height:40px; +} +.main > .main-left > .nav > li > a[data-title="Logout"]:before { + content: "\e005"; + display: inline-block; + top: -1px; + left:-10px; + position: relative; + vertical-align: middle; + display: inline-block; + font-family: "advancedtomato" !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} + +.main > .main-left > .nav > li > a[data-title="Reboot"] { + padding-left:36px; + line-height:40px; +} +.main > .main-left > .nav > li > a[data-title="Reboot"]:before { + content: "\e004"; + display: inline-block; + top: -1px; + left:-10px; + position: relative; + vertical-align: middle; + display: inline-block; + font-family: "advancedtomato" !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.main > .main-left > .nav > .slide > ul { + display: none; + list-style:dotted; +} + +.main > .main-left > .nav > .slide > .menu { + display: block; + padding: 10px 35px; + text-decoration: none; + cursor: default; +} + +.main > .main-left > .nav > li:hover, +.main > .main-left > .nav > .slide > .menu:hover { + background: #333; +} + +.main > .main-left > .nav > .slide:hover { + background: none; +} +.slide-menu { + overflow:hidden; + } +.main > .main-left > .nav > .slide > .slide-menu > li { + padding: 6px 50px; + font-size:12px !important; + position: relative; +} + +.slide-menu li:before { + content: ""; + left: 30px; + top: -15px; + bottom: 15px; + position: absolute; + display: block; + width: 1px; + border-left: 1px dashed #606c77; + z-index: 1; +} + +.main > .main-left > .nav > .slide > .slide-menu > .active { + background-color: #1a1a1a; +} + +.main > .main-left > .nav > .slide > .slide-menu > li > a { + position: relative; + display: block; + color: #969ba0; + text-shadow: 0px 1px 3px #222; + vertical-align: middle; +} +.slide-menu li a:before { + content: ""; + left: -20px; + top: 10px; + position: absolute; + display: block; + width: 15px; + border-bottom: 1px dashed #606c77; + z-index: 1; +} + +.main > .main-left > .nav > .slide > .slide-menu > .active > a { + color: white; +} + +.main > .main-left > .nav > .slide > .slide-menu > li:hover { + background: #333; +} + +.main > .main-left > .nav > .slide > .slide-menu > .active:hover { + background-color: #333; + cursor: hand; +} + +li { + list-style-type: none; +} + +#maincontent > .container { + margin:40px 40px 40px 50px; +} + +h1 { + font-size: 20px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +h2 { + margin: 15px 0 0 0; + font-size: 16px; + padding-bottom: 10px; + padding-left: 5px; +} + +h3 { + margin: 5px 0 0 0; + font-size: 10pt; + padding-bottom: 10px; +} + +h4 { + +} + +label { +display: inline-block; + padding: 0 10px; + vertical-align: middle; +} +fieldset { + margin: 10px 0 0 0; + padding: 2rem; + border: 0; + font-weight: normal; + font-style: normal; + line-height: 1; + font-family: inherit; + + min-width: inherit; + overflow-x: hidden; + overflow-y: hidden; + + border-radius: 0; + background-color: #FFF; + box-shadow: 0 1px 1px rgba(0,0,0,.05); + border-radius: 4px; + -webkit-overflow-scrolling: touch; +} + +fieldset > legend { + display: none !important; +} + +fieldset > fieldset { + margin: 0; + padding: 0; + border: none; + box-shadow: none; +} + +.panel-title { + width: 100%; + display: block; + line-height: 1; + color: #76838f; + font-size: 10pt; + padding-bottom: 10px; +} + +table { + border-spacing: 0; + border-collapse: collapse; + width: 100%; + border: 1px solid #eee; +} + +table > tbody > tr > td, table > tbody > tr > th, table > tfoot > tr > td, table > tfoot > tr > th, table > thead > tr > td, table > thead > tr > th { + padding: 12px; + line-height: 1.42857143; + border-top: 1px dashed #EEE; + + white-space: nowrap; +} + +.cbi-section-table-cell { + text-align: center; +} + +.cbi-section-table-row { + text-align: center; +} + +fieldset > table > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} + +/* fix progress bar */ +#swaptotal > div, +#swapfree > div, +#memfree > div, +#membuff > div, +#conns > div, +#memtotal > div { + width: 100% !important; + border-color:#ccc !important; + height:20px !important; + color:#76838f !important; +} + +#swaptotal > div > div, +#swapfree > div > div, +#memfree > div > div, +#membuff > div > div, +#conns > div > div, +#memtotal > div > div { + height: 1.4rem !important; + background-color: #e4eaec !important; +} + +/* fix multiple table */ + +table table { + border: none; +} + +.cbi-value-field table { + border: none; +} + +td > table > tbody > tr > td { + border: none; +} + +.cbi-value-field > table > tbody > tr > td { + border: none; +} + +/* button style */ + +.cbi-button { + -webkit-appearance: none; + text-transform: uppercase; + color: #fff; + background-color: #337ab7; + transition: all 0.2s ease-in-out; + display: inline-block; + padding: 0.2rem 1rem; + border: none; + border-radius: 0.2rem; + cursor: pointer; + -ms-touch-action: manipulation; + touch-action: manipulation; + background-image: none; + text-align: center; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + font-size: 10pt; + width: auto !important; +} + +.cbi-button:hover, +.cbi-button:focus, +.cbi-button:active { + color: rgba(0, 0, 0, 0.87); + outline: 0; + text-decoration: none; + color: rgba(0, 0, 0, 0.87); +} + +.cbi-button:hover, +.cbi-button:focus { + box-shadow: 0 1px 1px rgba(0,0,0,.05); +} + +.cbi-button:active { + box-shadow: 0 1px 1px rgba(0,0,0,.05); +} + +.cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: 0.60; + box-shadow: none; +} + +form.inline + form.inline, +.cbi-button + .cbi-button { + margin-left: 0.6rem; +} + +.cbi-button-reset, +.cbi-input-remove { + color: #fff !important; + background-color: #617486 !important; +} + +.cbi-input-find, +.cbi-input-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-find, +.cbi-input-reload, +.cbi-button-reload { + color: #fff !important; + background-color: #337ab7 !important; + border-color: #2e6da4 !important; +} + +.cbi-input-apply, +.cbi-button-apply, +.cbi-button-edit { + color: #fff !important; + background-color: #cc181e; +} + +.cbi-input-reset, +.cbi-button-remove { + color: #fff !important; +background: #617486; +} + +.a-to-btn { + text-decoration: none; +} + +/* table */ + +.tabs { + padding-left: 0.5rem; + background-color: #FFFFFF; +} + +.cbi-tabmenu > li, +.tabs > li { + display: inline-block; + padding: 0.9rem 0rem; +} + +.cbi-tabmenu > li > a, +.tabs > li > a { + text-decoration: none; + color: #76838f; + padding: 0.9rem 1.5rem; +} + +.tabs > li[class~="active"], +.tabs > li:hover { + cursor: pointer; + border-bottom: 3px solid red; +} + +.tabs > li[class~="active"] > a { +} + +.tabs > li:hover { + border-bottom: 0.18751rem solid #C9C9C9; +} + +.cbi-tabmenu { + border-top: 1px solid #e4eaec; + border-left: 1px solid #e4eaec; + border-right: 1px solid #e4eaec; + background-color: #F7F7F7; +} + +.cbi-tabmenu > li:hover { + background-color: #F1F1F1; +} + +.cbi-tabmenu > li[class~="cbi-tab"] { + background-color: white; +} + + +.cbi-section-node-tabbed { + padding: 0; + margin-top: 0; + border-bottom: 1px solid #e4eaec; + border-left: 1px solid #e4eaec; + border-right: 1px solid #e4eaec; +} + +.cbi-tabcontainer { + clear:both; +} +.cbi-tabcontainer > .cbi-value:nth-of-type(2n) { + background-color: #f9f9f9; +} + +.cbi-value-field, +.cbi-value-description { + display: table-cell; +} + +.cbi-value-helpicon > img { + display: none; +} + +.cbi-value-helpicon:before { + content: "\f059"; +} + +.cbi-value-description { + font-size: small; + opacity: 0.5; + padding: 0.5rem 0 0 0; +} + +.cbi-value-title { + word-wrap: break-word; + line-height:150%; + vertical-align: middle; + padding:6px 10px; + width: 23rem; + float: left; + text-align: right; + display: table-cell; +} + +.cbi-value { + padding: 5px; + vertical-align: middle; + display: inline-block; + width: 100%; + border-top:1px dashed #e4eaec; +} + +.cbi-section-table-descr > .cbi-section-table-cell, +.cbi-section-table-titles > .cbi-section-table-cell { + border: none; +} + +.cbi-rowstyle-2 { + background-color: #fcfdfd; +} + +.cbi-rowstyle-2 .cbi-button-up, +.cbi-rowstyle-2 .cbi-button-down{ + background-color: #FFF !important; +} + +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto !important; +} + +/* desc */ +.cbi-section-descr, +.cbi-map-descr { + margin-bottom:10px; + padding-left:5px; + font-size: small; +} + +/* luci */ + +.hidden { + display: none +} + +.left { + text-align: left !important; +} + +.right { + text-align: right !important; +} + +.inline { + display: inline; +} + +.cbi-page-actions { + text-align: right; +} + +/* input */ +.cbi-value input[type="password"], +.cbi-value input[type="text"] { + min-width: 15rem; +} + +/* select */ +.cbi-value-field .cbi-input-select { + min-width: 15rem; +} + +.ifacebadge { + display: inline-flex; + padding: 0.5rem 1rem; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.ifacebadge > img { + float: right; + margin-left: 0.3rem; +} + +/*textarea*/ + +.cbi-input-textarea { + color: #76838f; + padding: 6px 10px; + margin: 0; + line-height: normal; + font-size: 10pt; + font-family: "Roboto", sans-serif, Helvetica, Arial, sans-serif; + border: 1px solid #e4eaec; + background-color: #fff; + transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + -webkit-transition: color 150ms ease, border-color 150ms ease, opacity 150ms ease; + outline-style: none; + vertical-align: baseline; + border-radius: 3px; +} + +#syslog { + width: 100%; + min-height: 15rem; + padding: 1rem; + font-size: small; + color: #5F5F5F; + + margin-bottom: 20px; + border-radius: 0; + background-color: #FFF; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + border: none; +} + +/* change */ +#wan4_i, #wan6_i { +width:50px !important; +} + +.uci-change-list { + font-family: monospace; +} + +.uci-change-list ins, +.uci-change-legend-label ins { + text-decoration: none; + border: 1px solid #00FF00; + background-color: #CCFFCC; + display: block; + padding: 2px; +} + +.uci-change-list del, +.uci-change-legend-label del { + text-decoration: none; + border: 1px solid #FF0000; + background-color: #FFCCCC; + display: block; + font-style: normal; + padding: 2px; +} + +.uci-change-list var, +.uci-change-legend-label var { + text-decoration: none; + border: 1px solid #CCCCCC; + background-color: #EEEEEE; + display: block; + font-style: normal; + padding: 2px; +} + +.uci-change-list var ins, +.uci-change-list var del { + border: none; + white-space: pre; + font-style: normal; + padding: 0px; +} + +.uci-change-legend { + padding: 5px; +} + +.uci-change-legend-label { + width: 150px; + float: left; +} + +.uci-change-legend-label > ins, +.uci-change-legend-label > del, +.uci-change-legend-label > var { + float: left; + margin-right: 4px; + width: 10px; + height: 10px; + display: block; +} + +.uci-change-legend-label var ins, +.uci-change-legend-label var del { + line-height: 6px; + border: none; +} + +.uci-change-list var, +.uci-change-list del, +.uci-change-list ins { + padding: 0.5rem; +} + +/* other fix */ +#iwsvg, +#iwsvg2, +#bwsvg { + border: 1px solid #e4eaec !important; + border-top: none !important; +} + +.ifacebox { + border: 1px solid #e4eaec; + background-color: #f9f9f9; +} + +.ifacebox strong { + color:#f7f7f7; +} + +.cbi-image-button { + margin: 5px 10px; +} + +.zonebadge { + padding: 0.2rem 0.5rem; + display: inline-block; + cursor: pointer; +} + +.zonebadge > .ifacebadge { + padding: 0.2rem 1rem; + margin: 0.3rem; + border: 1px solid #6C6C6C; +} + +.zonebadge > input[type="text"] { + padding: 0.16rem 1rem; + min-width: 10rem; + margin-top: 0.3rem; +} + +.cbi-value-field .cbi-input-checkbox, +.cbi-value-field .cbi-input-radio { + vertical-align: middle; +} + +.cbi-section-table-row > .cbi-value-field .cbi-input-select { + min-width: 7rem; +} + +.cbi-section-create > .cbi-button-add { + margin: 0.5rem; +} + +div.cbi-value var, td.cbi-value-field var { + font-style: italic; + color: #0069D6; +} + +small { + font-size: small; + white-space: normal; +} + +.cbi-button-up, +.cbi-button-down { + display: inline-block; + min-width: 0; + padding: 0.2rem 0.3rem; + font-size: 10pt; +} + +.cbi-optionals { + padding: 1rem 1rem 0 1rem; + border-top: 1px solid #CCC; +} + +#diag-rc-output > pre { + background-color: #f5f5f5; + display: block; + padding: 8.5px; + margin: 0 0 18px; + line-height: 1.5rem; + -moz-border-radius: 3px; + white-space: pre-wrap; + word-wrap: break-word; + font-size: 10pt; + color: #76838f; +} + +input[name="ping"], +input[name="traceroute"], +input[name="nslookup"] { + width: 80%; +} + +header > .container > .pull-right > * { + position: relative; + top: 0.45rem; + cursor: pointer; +} + +#xhr_poll_status > .label.success { + background-color: #14CE14; +} + +.label { + padding: 0.3rem 0.8rem; + font-size: 10pt; + font-weight: bold; + color: #ffffff !important; + text-transform: uppercase; + white-space: nowrap; + background-color: #bfbfbf; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + text-shadow: none; + text-decoration: none; +} + +.notice { + background-color: #5BC0DE; +} + +.showSide:before { + display:none; + color:#76838f; + content: "\e029"; + font-family: "advancedtomato" !important; + font-weight: normal !important; + font-size:14px; + top: 18px; + left:10px; + position: relative; + vertical-align: middle; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.darkMask { + width: 100%; + height: 100%; + position: fixed; + background-color: rgba(0, 0, 0, 0.56); + content: ""; + z-index: 99; + display: none; +} + +/* fix Main Login*/ +.node-main-login > .main > .main-left { + display: none; +} + +.node-main-login > .main > .main-right { + width: 100%; +} + +.node-main-login > .main fieldset { + padding: 5px; + margin-bottom: 1rem; + display: inline; + background: none; + border: none; + box-shadow: none; + overflow: hidden; +} + +.node-main-login > .main .cbi-value-title { + width: 7rem; +} + +.node-main-login > .main #maincontent { + + text-align: center; +} + +.node-main-login > .main .container { + display: inline-block; + padding: 2rem 4rem; + margin-top: 2rem !important; + background-color: #FFF; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + text-align: left; +} + +.node-main-login > .main form > div:nth-last-child(1) { + float: right; +} + +.node-main-login > .main .cbi-value { + display: block; +} + +.node-main-login > .main .cbi-value > * { + display: inline-block !important; +} + +.node-main-login > .main .cbi-input-user, +.node-main-login > .main .cbi-input-password { + min-width: 15rem; +} + +.node-main-login footer { + bottom: 0; + position: absolute; + width: 100%; +} + +/* fix status overview */ + +.node-status-overview > .main fieldset:nth-child(4) td:nth-child(2) { + white-space: normal; +} + +/* fix status processes */ + +.node-status-processes > .main table tr td:nth-child(3) { + white-space: normal; +} + +.node-status-iptables > .main div > .cbi-map > form { + margin: 2rem 2rem 0 0; +} + +.cbi-map fieldset h3 { + padding:10px 0; + } + +.cbi-map fieldset ul li { + background:#f7f7f7; + margin-right:0 !important; +} +/* fix system reboot */ + +.node-system-reboot > .main > .main-right p, +.node-system-reboot > .main > .main-right h3 { +} + +/* fix Services Network Shares*/ +.node-services-samba > .main .cbi-tabcontainer:nth-child(3) .cbi-value-title { + margin-bottom: 1rem; +} + +.node-services-samba > .main .cbi-tabcontainer:nth-child(3) .cbi-value-field { + display: list-item; +} + +.node-services-samba > .main .cbi-tabcontainer:nth-child(3) .cbi-value-description { + padding-top: 1rem; + line-height:150%; +} + +/* fix System Software*/ +.node-system-packages > .main table tr td:nth-child(1) { + width: auto !important; +} + +.node-system-packages > .main table tr td:nth-last-child(1) { + white-space: normal; + font-size: small; + color: #76838f; +} + +.node-system-packages > .main .cbi-tabmenu > li > a, .tabs > li > a { + padding: 0.5rem 1rem; +} + +.node-system-packages > .main .cbi-value > pre { + background-color: #eee; + padding: 0.5rem; + overflow: auto; +} + +.cbi-tabmenu + .cbi-section { + margin-top: 0; +} + +/* fix network firewall*/ +.node-network-firewall > .main .cbi-section-table-row > .cbi-value-field .cbi-input-select { + min-width: 4rem; +} + +.node-status-iptables fieldset, +.node-system-packages fieldset, +.node-system-flashops fieldset { + margin-top: 0; +} + +.node-status-iptables .cbi-tabmenu, +.node-system-packages .cbi-tabmenu, +.node-system-flashops .cbi-tabmenu { + border: none; +} + +#cbi-firewall-redirect table *, +#cbi-network-switch_vlan table *, +#cbi-firewall-zone table *{ + font-size: small; +} + +#cbi-firewall-redirect table input[type="text"], +#cbi-network-switch_vlan table input[type="text"], +#cbi-firewall-zone table input[type="text"]{ + width: 5rem; +} + +#cbi-firewall-redirect table select, +#cbi-network-switch_vlan table select, +#cbi-firewall-zone table select{ + min-width: 3.5rem; +} + + +/* language fix */ +body.lang_pl.node-main-login .cbi-value-title { + width: 12rem; +} + + +@media screen and (max-width: 1600px) { + .main-left { + /*width: calc(0% + 15rem);*/ + } + + .main-right { + width: calc(100% - 15rem); + } + + .cbi-button { + padding: 0.3rem 0.6rem; + font-size: 1rem; + line-height: 1.5; + } + + header > .container > .pull-right > * { + top: 0.35rem; + } + + .label { + padding: 0.2rem 0.6rem; + } + + .cbi-value-title { + width: 15rem; + padding-right: 0.6rem; + } + + fieldset { + padding: 1rem; + } + + .cbi-input-textarea { + font-size: small; + } + + .node-status-iptables > .main fieldset li > a { + padding: 0.3rem 0.6rem; + } +} + +@media screen and (max-width: 1280px) { + header { + /*height: 3.5rem;*/ + } + + header > .container { + /*margin-top: 0.25rem;*/ + } + + .main { + top: 3.5rem; + height: calc(100% - 3.5rem); + } + + .main-left { + width: calc(0% + 17rem); + top: 3.5rem; + height: calc(100% - 3.5rem); + } + + .main-right { + width: calc(100% - 17rem); + } + + .cbi-tabmenu > li > a, .tabs > li > a { + padding: 0.2rem 0.5rem; + } + + .panel-title { + font-size: 1.3rem; + padding-bottom: 1rem; + } + + table { + font-size: 0.8rem !important; + width: 100% !important; + } + + .main > .main-left > .nav > li, + .main > .main-left > .nav > li a, + .main > .main-left > .nav > .slide > .menu { + font-size: 1.1rem; + } + + .main > .main-left > .nav > .slide > .slide-menu > li > a { + font-size: 0.9rem; + } +} + +@media screen and (max-width: 992px) { + + header { + height: 3.5rem; + } + + header > .container > .brand { + font-size: 18px; + height: 3.5rem; + line-height: 3.5rem; + width: calc(0% + 15rem); + /*width: initial;*/ + padding-left: 5px; + padding-right: 20px; + } + + .main-left { + width: 0; + position: fixed; + z-index: 100; + } + + .main-right { + width: 100%; + } + + .showSide { + margin: 0; + padding: 0; + display: inline-block; + position: absolute; + width: 100%; + height: 100%; + } + + .showSide:before { + content: "\e20e"; + font-size: 1.7rem; + } + + .node-main-login .showSide { + display: none !important; + } + + .cbi-value-title { + width: 9rem; + padding-right: 1rem; + } + + .node-network-diagnostics > .main .cbi-map fieldset > div * { + width: 100% !important; + } + + .node-network-diagnostics > .main .cbi-map fieldset > div input[type="text"] { + margin: 3rem 0 0 0 !important; + } + + .node-network-diagnostics > .main .cbi-map fieldset > div:nth-child(4) input[type="text"] { + margin: 0 !important; + } + + .node-network-diagnostics > .main .cbi-map fieldset > div select, + .node-network-diagnostics > .main .cbi-map fieldset > div input[type="button"] { + margin: 1rem 0 0 0; + } + + .node-network-diagnostics > .main .cbi-map fieldset > div { + width: 100% !important; + } + + #diag-rc-output > pre { + font-size: 1.2rem; + } + + .node-main-login > .main .cbi-value-title { + text-align: left; + } +} + +@media screen and (max-width: 480px) { + fieldset { + padding: 1rem; + margin: 1rem 0 0 0; + overflow-x: auto; + } + + .tabs { + margin: 0 -1rem; + } + + #maincontent > .container { + margin: 0 1rem 1.5rem 1rem; + } + + .main > .main-left > .nav > .slide > .menu { + font-size: 1.3rem; + } + + .main > .main-left > .nav > .slide > .slide-menu > li > a { + font-size: 1.1rem; + } + + .cbi-value-title { + width: 100%; + min-width: 0rem !important; + display: block; + margin-top: 1rem; + margin-bottom: 0.5rem; + text-align: left; + } + + .cbi-value-field, .cbi-value-description { + width: 100%; + } + + .cbi-value > .cbi-value-field { + display: inline-block; + } + + .cbi-tabmenu > li, .tabs > li { + padding: 0.6rem 0rem; + } + + .cbi-tabmenu > li > a, .tabs > li > a { + padding: 0.2rem 0.3rem; + font-size: 0.9rem; + } + + .cbi-page-actions > div > input { + display: none; + } + + .node-main-login > .main .container { + padding: 0.5rem 1rem 2rem 1rem; + } + + .node-main-login > .main .cbi-value { + padding: 0; + } + + .node-main-login > .main form > div:nth-last-child(1) { + margin-top: 2rem; + } + + .node-main-login > .main .cbi-value-title { + width: 100% !important; + font-size: 1.2rem; + } + + .node-main-login > .main fieldset { + margin: 0; + padding: 0.5rem; + } + + h2 { + font-size: 2rem; + } + + .tabs > li > a { + font-size: 0.9rem; + } + + select, + input { + font-size: 0.9rem; + } + + .mobile-hide { + display: none; + } + + .panel-title { + font-size: 1.4rem; + padding-bottom: 1rem; + } + + .node-system-packages > .main .cbi-value.cbi-value-last > div { + width: 100% !important; + } + + .node-system-packages > .main .cbi-value .cbi-value-field input { + width: 100%; + } + + .node-status-iptables > .main div > .cbi-map > form { + position: static !important; + margin: 0 0 2rem 0; + padding: 2rem; + border: 0; + font-weight: normal; + font-style: normal; + line-height: 1; + font-family: inherit; + min-width: inherit; + overflow-x: auto; + overflow-y: hidden; + border-radius: 0; + background-color: #FFF; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + -webkit-overflow-scrolling: touch; + } + + .node-status-iptables > .main div > .cbi-map > form input[type="submit"]{ + width: 100% !important; + margin: 0; + } + + .node-status-iptables > .main div > .cbi-map > form input[type="submit"] + input[type="submit"]{ + margin-top: 1rem; + } +} + +@media screen and (min-width: 992px) { + .cbi-value input[type="password"], + .cbi-value input[type="text"] { + min-width: 20rem; + } + + .cbi-value-field .cbi-input-select { + min-width: 20rem; + } +} + +@media screen and (min-width: 1280px) { + .cbi-value input[type="password"], + .cbi-value input[type="text"] { + min-width: 22rem; + } + + .cbi-value-field .cbi-input-select { + min-width: 22rem; + } +} + +@media screen and (min-width: 1600px) { + .cbi-value input[type="password"], + .cbi-value input[type="text"] { + min-width: 25rem; + } + + .cbi-value-field .cbi-input-select { + min-width: 25rem; + } +} diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/favicon.ico b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..b407d18455773a185059628e632e60c06d6eb858 GIT binary patch literal 2462 zcmcJR&yEaH6o*e6F|iOUG9fZOLP&@Rv5;U2&*0w!;0>@EGb?OJyuet^Lm<@5WC)%> zkg%GqrA0^izRtZ-om6$ws{JP4+;h*l=U2CGb=OQpkDs}@;CDYB?~d3X5yyd4oCfnl zQEO2_{uO*pd}Hi_UInNEw%|dE&oM3}4l_=IeJ4P#cTj-Wx)0ajZQ?p(S9uM+zd!+R z;6|ck+y`BBl4j4l?(e>39j4{~8n1hh&!;5zKDx>?*ZVTOhx+rKXD`V97nvAJBYkDKK6(zC8zOb&vd$Aubw;!E%;jrG`CeXYHE z=rxJ-*noU4#^$Cay}a-2Z#-@P|G9s^3nko27HrO^a0Qz7YtEW$Tsx_D(r^bpz%#fCM-#^8thvUu|04Hz3ZB4A*hmvOF=_Uh3l-%EGlBRqt87^TcB!2LW2|K51tM-tY}S#!-Qm>ahj$|IU(b`hS!7WmH3|G(t-zctsm zwo%LJk~7t>=v9Lu#>!e5Gf}NnqiiyV!O~(3E&xaWo8#PG*^VF8qxilw8$V<3F#iYk Cvy_7X literal 0 HcmV?d00001 diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/Roboto-Medium-webfont.woff b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/Roboto-Medium-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..9024faeb8f52376392077cb7f343b072e318daa4 GIT binary patch literal 70200 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 literal 0 HcmV?d00001 diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/Roboto-Regular-webfont.woff b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/Roboto-Regular-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..5413a37ee0c57147ef81660849eebd5c3531cdaf GIT binary patch literal 68776 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 literal 0 HcmV?d00001 diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.eot b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.eot new file mode 100644 index 0000000000000000000000000000000000000000..f85324aacd32146dc3f40b9fae97c20273f43bd0 GIT binary patch literal 8480 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 literal 0 HcmV?d00001 diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.svg b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.svg new file mode 100644 index 000000000..a4ae739ac --- /dev/null +++ b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.svg @@ -0,0 +1,53 @@ + + + +Generated by Fontastic.me + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.ttf b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0f59478d517233be2269d3e7f719649444b101d6 GIT binary patch literal 8288 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

?Nv5>2jM{^Uow~~U2 z`fzo)GCGE)?>72xE#XEGcMrRl-4&3W!(@U?cH_c5_ujRCF*jC5;eRzC?D*wZYkx1V zX`Q3NzyjAOI4$R-kxm8<3oNoJf>U^hViYHr5|ktl|6!#lO>LB+cIu!`%2F5QC{Nu~ zpdRX_B9*8Qr%?kmNJH9vi+8OV9UTqRu`sQKX*Ep8!?YHr^)S66Os@>nRbje1Os@&k zHLY|koM$YYXDpm&ESzU79Dghvf2A}-by%cC7ic%Xk(1{{V>3wP64N literal 0 HcmV?d00001 diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.woff b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/advancedtomato.woff new file mode 100644 index 0000000000000000000000000000000000000000..42512481990775135c4da591e761b1b51c408234 GIT binary patch literal 6272 zcmZX2Wl$VW@a4kdy7=M*4H7g!kU(&k;1XbQT|BV31&7Vz9-P497J>u`L4yFMd7nwk&etsyV3p`)V#0Dyx5xPWJ4Cc-mAGETQJE&ziwA_kYe?@>9O&lbyA>)wA|rKJI4-0qynA?4CscfCBBA(>;S3 z?Jdfs9n=%{tT8`xoo9T&qCwk-n!}#+Q9SDajQ;_bCcxPoYW=JQKl9_~J!Wo=J{7sT zcz8bd`y31SuO0>f5P$;9{%C-mtTUBSHFJ)1rjnJV@25e1&r}*OAN4!$XCAyj%FO~R zw17)ZSjD^k+Gt95O84se>8N_T>bQi$&h8tAmB(VVI%(qjLZvwDzSSX`LNK3)g|h~o zh`>|1w1T+6$rsvjeuvt;4$FdJH9b` zFb)kC4Q?A4_Ug30Q!L~!&=xfaD;xJ8%c-ypsX!*>sH#PKx2mnP&9P13ScCb}L(`(W zN^_=Rl}$?dNm{w_?f-uY5kjh&JkArjgz)7{>EH`kPk^m*^@6B{^ZHQHpgwY}9|m6wWEn0A;|Q4DN(-x|gojT%O|9zILg#40z() zFgFK^W+_V#swIq;)T% zF%pWyc^F|nb&E*9RGB#?WJ#$Pp((Wx!_1m_04H%tlgAh-s0M4 z=k(iKKSKKD>(FcDwZm`Ra>AsIzBb2+8@=umw`Gny{T7E~+!OSC?I9NaXwStM)H6Md zLJ$SXfUIJ^biJ(Y}*mYO_ZlBvF&4b6Awtkc_ zD%mGD-QKrHl@->oWrdxik!xPr@FjIp*~n8{Z$jBYiKVPamQSvY^2_D!eMRsQ_N#n0 zYg0vREoC*1n?Ch~&uuD(Y#BuL?|R{gge(yr;y5X3a#_>FBoNydki%e~w`zXE>a~BB z3kR8WK)@4hZ7P9Eqi#3Ih>C$=&Vlc#49qv5`Z={KL>L=ME$k(L-0vq_ppauN_~Un`B{!{9PEm#k1`*QG>P4%RZFz2jxryn6uy{?iM3YH*}rLKS`bV= z67<69-u#DpBH2tz*v5%?l%FPY8g|2?)#$5~*j78Og7m?i@{blxJc+V6db4@=E!BAO z+$6|ec>Bg0w41=e(4u=*a+r3F99JFC>Jzr;D)?J?C?n(EUAkavibY*gMF4`t!9b8@ zWBWcUTlyD?6lo`jt1Hn>11kujOS{DPYVsRCh2THWF?3@gbnQPrDGK+hpSjlC-*_xc z>91@*jrgDSWC)n4UX8@fWBR!RfBfD1?mkeUj>Uq6rIOgtN#V)6xAmylH}}f$Gq&(P;%!*^K!rV)M4>QVbF!L7{!!PW>yxzs1!vOgYZ@TU3H9W$y7dWHf$XvuXviy)Ll=Qa?}seOYQem;(} z)POVwO;>y~3(GL5A56*SxZ|lH_+IX#VVb8>H^p^Ous29hHt{t&&i#Fa7d{^TAtz0P z;?XS!LFIA{7jEN%Y}Vkx0@TFgD%7N=u9VPk2rAu@Q{h+<%@b*3$4^CjDHXfd^qqR7 zuIK1j9UN-87WUC^`lOPbJ90~tx~$rz^z)zfjdP3PWzjm@hpv9US?sWpYxVOzd?%rV zun!Sgp+fwz*b^CwwcCC=)&T}{GWN!IpQVI62d7#Y?A<8!+b{N{x2PSB2$i} z+lthQivDD4^C^byLDi||_myL+K~KVeo1OF#lKZ~u6LOXT!%QCJBb5OKg(>0+6dv4G z`FV&nOQ)nsE2ohA)p0cy3dvg7ZyDYheL6LUTEsSWq03-Qp-ARdZg_E_b!d18UiRYk zxq!kzzUAoO_L!1W#kXHiiF;Z3SlP(jYFbW7xk3o0ymQ*P(C<@VjRqHT?k?Y*);! zh2hsDt}Q+LV?OWUziG*Hb zzCGh?E zG;a3j`D$TOKojiQztGVk`MUqFf}hdA!Tsmude>LwY#%oztxPrF)Onq_`)4gJyAwPx zR2TIN#1A_n?`Pp~@CtXrS3PlR2jN0>h13dX2ReyAqa0QHfII);ag(~14(}UHlB{9! zZ1p5@zsoYsugN?0w40h{E1CQ9dK!DXW&=>p?_NYYZn*3WoMJsjB}FXvERC-q9)>exIrC~LU9(8i_{=^u4!iKoy{v&#EF zu$}IIdUi|Xp1qaRa9!<()7!y-(TT#DaDq_I`~1G`k8%5w1dO-(%H~R)6c_S-g)-o6 zYa*T^J#jQC=X znQwIG(#ul@?MQnpoS~jtF|+L`0n)-Tj9I;u}#tyalsYdfjtnoJ$xFM-BHKGluwOnycrUWm)Ddn^+TW^( zd!p@fci!M=+!LQzunUj0^BOU4xu9p76a#+<869Ah&s>x9FL zEY`$ismHkqE9aNC*@lo%lADO| z+hkSg#0aC$-dqt*G0aK*UNwru)+Te$4{YyisEOkEx=sD0MdT6zmo!HBpt2r6do-2TuqV?Vwoiu*Fu9@;l>EH{ zeH6frR`dvXTk=thBjZ;ad5TKv-~er+i>?kjNZEAL9zN1aXWy(pz#+WsVXJE)Z?k-o ztbr{wuKaIUtj{-y@~V0-&2)0*oEmzf<&?8#;ww2+l6H6KO!t5u`I_Qy0&E;a>>jAB zi=c3_<@hmOep>b8J3AF>5eCNb6ExZK)g%f@*meKUgn{e`K4a~KDokChx%c(7j5V%% z6XE?5qL-ic{Ahn7%MT9pyB$gwfRU?X$4il~rE6=nFrr}ura^1rGbmT@II!9qUZ|>0 zl~LJzM=H~qb|U#WQ{^WTC@!ex;Aat6zP$PD^0*0#TvXAUmOU0P%(B-{@P1!yZ&X5S zVIC^4XO^`4p;<=WY&$02F{TvALX|h7j~X*R8$ZrwQci+?{&D-4dn$4Dudz@f@Z`s5 z$uIZIYQn=gev@h^!w<0i*@V|WCN$g=m|y5l$T92)qstAMuo(7IM->U_6uh53nS9A# z$8L9P9Nz31t?WbQc_$3uc+?2S6_1P4Nk&1$r2v+TCtceeZkYxzD3W)Wf3=#EU($Rm zo$tr-L-12kP30>pXx91?l>?`2>({a0yM;6*)-3=iD1IHE9>3NqaaScludHenhd?8O zss(9|UV)`AysAsvt5A9@T_s8yhynjOUS%5*5w-FCn`5E6{o@SLN+({?IV7xuH}8(K zK$ToiUlQOEC49W-DGG;+dBfpZs2yd2j%xy?Nl&soJ8k8qW~?=-==MZO4PjiOSS$7b z)&iU}R$r2~=-Ht6j!=Bg7(|V%boI~2^0w#-u0q?t0r&*Wn2v@rLOM@j*i;=-yRsdt zrLjhYbddNug-&rTA=fA8yo>K$Ihd`=sdRLUid0mysn9HU{PZknOj85mKym|4A7r^> zd`jL{dv-G!7&IKh^6cFes~mOXhA|V-+S$ca-pc8 zJ~j1fR{IgX!yjv0uJn4jQWv&rxo6%IWvtoA0Qi>9Q5#^5LgujSxCzQ{~0o|UNNcsI|7TXf%4VUxw$Vlg>`JwfSDVmd;2 zBF;N2fY%4f`mlLXCe27KL-i0dGjO#EQ^kNjb>kuV+1GEripY_^l0)_qw7Ni%Olf@l^-np>s4+aN!ANNA)c!j3!scL&Xd``)!H4J7kC~ z1Si7qwkwA%wKI}%3AN&+-8!Q|e0vG+RdpRs3o!YL{N{8=Wo<;x={3u*VP5vd;erkj z?^f?6tyG1Otx=7<7U8iw6&+0-XLtj7WyH6){hQU#Mac+YqnaHY7{g zm!JzEglOA_UR(9=KB0ua=}Ub6(1c}MLLd+;Kedvy9-j!vk6LdB5_uPR4oQe-0+f`RBP&A znDzPl0PiM%%jfZ6fwh5TN}g?5t|*ZjtDa0I>Tid$7x~PSJtP!b?#>_Bzh8_^AdYLF zdI;rg@Rk1S|G7uNI)Y5YapM-+&hIL~7u+f5bIbvLc%laaNhA%j!%$RF0O0S~MF00p zEC8r)StFjF9)qmbZ6Q|g&{Y9udT4_G&6CBvAPD9K09}%@WI%NcievSVzd$@($#>>A zD8$#S%NWVocGYF*T#M`L%*6c_G?~=I@DMq)=6oCNa|u%U6lG>F8&;q4;-vd08A5tV zaa(&JnUan3Pk>N zxkWBx3cK`TX{IX^cb(wj!}nNxiEsf??=`yR(^rdqI%<&j8$Ty4F%_JNT&=z^ItA1Q?(7TEK!5wo z6n9Z#;v|$gj$o=7XkT+F@lCjn@xIjL=Wc%T+nh0Qy%cFOR|_ZnhSzQqIr|10qs4Qz z@*Y;(zthaliPQ)%S7BNI^k8W<+&7Uv+X9=%tS&F`uUaEiI?#~$-)C*}4kHfF?)kF8 H0qFk=!5PYt literal 0 HcmV?d00001 diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.eot b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.eot new file mode 100644 index 0000000000000000000000000000000000000000..9e6ffc9b826cb39a58e56359d6b8b922a4b07364 GIT binary patch literal 1912 zcmah~Ur1Y582`?_x%Vc~T>r!*OpT4P8o`m;m_K$==`c84Z6{8{+A(HKZlhvuY>cgr zKFA)%(1*FfM*FnUZZIZ{J&ZBvpfZF#Y)@lIVSRG2hwi1Y4#u`F`<;8QXe6-ja?bgE zzwN>ij! zo>pmzGE@TNr8Jlltw75)0Xj=z>Nm6}M}y=6>u7^S>VN6wGm(a7S2vh%P-e4*%<|74 z-T45bcKGFdW@Q;|Bm8Z&_WaWN)fd`ZeusaHNO&->WpYaP$#+CHu8YruP`(wvhyN-3 z)ANP$nqL?8;r{@?cd3}o2=nYs_)p+_3z@ZLe9%0RR1ZI(XA0Ww7af1Ye-<&`S}v}X zF;AHMCGRIuyn~rYh<#h&Z+ypW*>5z!99(zI7^Yoq=ZPL)7I!PVbY4V3=V9`>F2E}z z8jskHKC=}KRXf?}74Xf-hKS{56ga3mP!HbyReXH8^0ZRngTXngI9B<^|Cj$y|Mga> z;R}pA9?uwniV?%;hGTu$Jc)CL^hp0d9A5GarZvNJ<6ufi3Gpco?d=T-GZmvH1`UH| zm}{8N!4f`UZ>U1NTNno5ddx?}-q;a0gdKdb1FJ*sPETj7DTdm^s|}H!LSzj^@e}6Xo3K zXf!%Jyy+jD4Tn>yMB=%*RO-r=RBGa)o-oe4%#d}+m|4=Q~$QQ44QKuG~z>i4Xv1q8Lj|COk&su!m zB#R{CF*mpnCZx!x7-pM@8!0(V$8jZ+b@ar1M!vd&d^FFaIShFeNRsTjU4j|Sd#3{Z zXChnUcGm@);*d_c-5qUSPhEZ6>5dLdQtxVZJDg384u_&VOeQt$##&BG!nEAl4Grj% zf?bkj$zHI_k|f*NMx?LL=UZ2u=WI$ybv3ANugm3X>D=4hK9vL(>`jZV6X?ab{kvf)^jN}pSC8R2xdumC)3 zVG%fPVH@zOg(aM_9t+FhFId=#{kw^X%;o^2qQ}GnaNfcq@UVq#z&9-{;jj-_SO!03 zVJAiDPgt_+pY=D^L-I_h!b%DZS?d0}MTT%Y6XQicBm D*A6pu literal 0 HcmV?d00001 diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.svg b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.svg new file mode 100644 index 000000000..d38d057da --- /dev/null +++ b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.svg @@ -0,0 +1,16 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + \ No newline at end of file diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.ttf b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.ttf new file mode 100644 index 0000000000000000000000000000000000000000..84669323e9ddfdca80c91416b6d4fe31ea1829ab GIT binary patch literal 1748 zcmah}U1%d!6h3n&Gn1cY`jbCwn>0i)RYHn=Nd(_}VjX(rt? z-ECzbiVq^~gR7wIJ}Ik$SP&mXgcU4O@Ijw^C=2dW1t0Wf!4*VZ<9BDKw5tWraPR%j zch0@%%sF?41R`?L28k4Z?)j66)(&?+m@hHriq*pM5AWT1he+s#-Y6GVma(=$zlqge zURuBMOt<$}=(mX2y^2;SDaD815ZSn2x&lJ^TKpFJN6=4Hs*Sav&i0^x2YqmLYKX+Z zh4)?i>i(NQi4QI{A2plC?(n|zF-~ay82lsnd+=JP)cPs*9gSyfz$B1>-K|G#j3{&3 za6R<@9}b5+fwX3MZ5)CURiZq_(cRrqHrq5-65u1iXN>y@0f&$Yu-(xnaWfkO;Qq)* z#NF5yH`q4b*n#elr`Ok;YENPI@o7V(M{qI++s^0z-kX`(%jfy~2$ZLw_^~)dT}1uS z0rN>EGwI<(fDgaVtH^j5jW5RI*{t6`F;QxqJJ%>pOeB+IW1GQ|xmYZh%VeIK&*d&( z&gJGW%*>3B-$2WWnmaZ^=Q=5cP!W|W1*=Ev4Ne;?! z)Dy)zd{P0UUVRb1o7d6YhB`8mB)e{xAja}mPdI)uu{C9PpS39tsmJ39b@_d+maY?_ zkmb_i?(jIA?QIT+qTJ7BHSPLZNy|dC(%N+m=)h}3M^?w~_ggCg@Q$N?gdbxG{B zx-Tq&<|jJo3a&GkgUE(rO)7n2#T7^aXXe0w=PWD&r!8y)UbV1p!rv)lfjj9+m((_t< zWuc~rPsQT+HZ`i#3LId-Ij1N_@nd%#OHOO$)ulomK{X`0N=sCr`mvsqHN6ooYr0l1 zG_+E9emy)@ter=0F`6`DHxRvyV{{{<0yVIfz|GS-<|*R^&YLfQ9MQz1E%`702g#=) A_5c6? literal 0 HcmV?d00001 diff --git a/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.woff b/package/lean/luci-theme-atmaterial/htdocs/luci-static/atmaterial/fonts/font.woff new file mode 100644 index 0000000000000000000000000000000000000000..00cf84ea037c9748eba8fced0acff7dd29c12b2f GIT binary patch literal 1824 zcmah~U1%d!6h3z*Gn1dq^e2DXHffq}n?fO*P4m+=ZK*U=>UMvqZE#n_rpav5(j>cS zx@~12iVq^~gR7vpPs*;oSP-8?SivF%AM{D2EZCG7&Rrx~vs#LD8 z6G>0NAK>b*2>Z*`Jo2P*_+G9;iM>+Jt)s5=Jp7=pDwQg^vIY+G*{fXdJZt;odUXZ8 zDo8Q&L?BVT%Wji|-tGur!++fv+0Qh@Y&`XZu+|ff4#$ZeUJ-X2yEHCB!7-gTOi&;6 zDnMO`aoh#Vv%1Jayytdm1tWk99y$)y!#92uA6{uZZZr@haQ1(2tnt17cmHqxn;lZi z$L30U;t9iuVRnmN#h?YE)H%Ji~}l4#fh3$L$@8 zB@^+8(AyRp6H=J9PPd>@Tz*hhgR$y%{W5Pf*FI~Y9^ z+n%yI&s!9m)a`NwI=vppsm{}ZfSGd2+3vF0+gfclML9^PHEnIZprs*NVSP;l`k-u; zWLdJ7t+FJ^R<;=%9Q64%RQoxL5>}lps>|ziI$L`}{T`#RqrJ^xmt|E|ogPm| zCrxYtUNy0VFSW^2&zRUw zae99-UoBUw6a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; + +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("