]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
ath79: add support for kernel 5.4
authorDavid Bauer <mail@david-bauer.net>
Sun, 8 Dec 2019 20:44:23 +0000 (21:44 +0100)
committerKoen Vandeputte <koen.vandeputte@ncentric.com>
Fri, 28 Feb 2020 16:50:46 +0000 (17:50 +0100)
Signed-off-by: David Bauer <mail@david-bauer.net>
[refreshed]
Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
* Sync the patches with the changes done for kernel 4.19
* Use KERNEL_TESTING_PATCHVER
* Refresh the configuration
* Fix multiple compile bugs in the patches
* Only add own ag71xx files for kernel 4.19 and use upstream version for
  5.4.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
56 files changed:
target/linux/apm821xx/patches-5.4/111-crypto-crypto4xx-reduce-memory-fragmentation.patch
target/linux/apm821xx/patches-5.4/112-crypto-crypto4xx-use-GFP_KERNEL-for-big-allocations.patch
target/linux/apm821xx/patches-5.4/201-add-amcc-apollo3g-support.patch
target/linux/apm821xx/patches-5.4/202-add-netgear-wndr4700-support.patch
target/linux/apm821xx/patches-5.4/301-fix-memory-map-wndr4700.patch
target/linux/apm821xx/patches-5.4/801-usb-xhci-add-firmware-loader-for-uPD720201-and-uPD72.patch
target/linux/apm821xx/patches-5.4/802-usb-xhci-force-msi-renesas-xhci.patch
target/linux/apm821xx/patches-5.4/803-hwmon-tc654-add-detection-routine.patch
target/linux/apm821xx/patches-5.4/804-hwmon-tc654-add-thermal_cooling-device.patch
target/linux/apm821xx/patches-5.4/900-powerpc-bootwrapper-force-gzip-as-mkimage-s-compress.patch
target/linux/ath79/Makefile
target/linux/ath79/config-5.4 [new file with mode: 0644]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/Kconfig [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Kconfig with 100% similarity]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/Makefile [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile with 100% similarity]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/ag71xx.h [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h with 100% similarity]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c with 100% similarity]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c with 100% similarity]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c with 100% similarity]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c with 100% similarity]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c with 100% similarity]
target/linux/ath79/files-4.19/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c [moved from target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c with 100% similarity]
target/linux/ath79/generic/config-default
target/linux/ath79/nand/config-default
target/linux/ath79/patches-5.4/0002-watchdog-ath79-fix-maximum-timeout.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0003-leds-add-reset-controller-based-driver.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0004-phy-add-ath79-usb-phys.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0005-usb-add-more-OF-quirk-properties.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0008-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0011-MIPS-ath79-select-the-PINCTRL-subsystem.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0017-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0018-MIPS-pci-ar71xx-convert-to-OF.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0019-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0020-MIPS-pci-ar724x-convert-to-OF.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0032-MIPS-ath79-sanitize-symbols.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0033-spi-ath79-drop-pdata-support.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0034-MIPS-ath79-ath9k-exports.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0036-GPIO-add-named-gpio-exports.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0036-MIPS-ath79-remove-irq-code-from-pci.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0037-missing-registers.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0038-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0039-MIPS-ath79-export-UART1-reference-clock.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/004-register_gpio_driver_earlier.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0051-spi-add-driver-for-ar934x-spi-controller.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/0060-serial-ar933x_uart-set-UART_CS_-RX-TX-_READY_ORIDE.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/404-mtd-cybertan-trx-parser.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/405-mtd-tp-link-partition-parser.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/408-mtd-redboot_partition_scan.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/425-at803x-allow-sgmii-aneg-override.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/430-drivers-link-spi-before-mtd.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/440-mtd-ar934x-nand-driver.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/900-mdio_bitbang_ignore_ta_value.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch [new file with mode: 0644]
target/linux/ath79/patches-5.4/910-unaligned_access_hacks.patch [new file with mode: 0644]
target/linux/ath79/tiny/config-default

index 72f8825cb718c859e3bf54ffb91a3df70679d999..4d23b8816aa4e6c10bf12788ea6068454d0addc0 100644 (file)
@@ -28,11 +28,9 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  drivers/crypto/amcc/crypto4xx_core.c | 27 +++++++++++++--------------
  1 file changed, 13 insertions(+), 14 deletions(-)
 
-diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
-index 7d6b695c4ab3..3ce5f0a24cbc 100644
 --- a/drivers/crypto/amcc/crypto4xx_core.c
 +++ b/drivers/crypto/amcc/crypto4xx_core.c
-@@ -286,7 +286,8 @@ static u32 crypto4xx_build_gdr(struct crypto4xx_device *dev)
+@@ -286,7 +286,8 @@ static u32 crypto4xx_build_gdr(struct cr
  
  static inline void crypto4xx_destroy_gdr(struct crypto4xx_device *dev)
  {
@@ -42,7 +40,7 @@ index 7d6b695c4ab3..3ce5f0a24cbc 100644
                          sizeof(struct ce_gd) * PPC4XX_NUM_GD,
                          dev->gdr, dev->gdr_pa);
  }
-@@ -354,13 +355,6 @@ static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev)
+@@ -354,13 +355,6 @@ static u32 crypto4xx_build_sdr(struct cr
  {
        int i;
  
@@ -56,7 +54,7 @@ index 7d6b695c4ab3..3ce5f0a24cbc 100644
        dev->scatter_buffer_va =
                dma_alloc_coherent(dev->core_dev->device,
                        PPC4XX_SD_BUFFER_SIZE * PPC4XX_NUM_SD,
-@@ -368,6 +362,13 @@ static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev)
+@@ -368,6 +362,13 @@ static u32 crypto4xx_build_sdr(struct cr
        if (!dev->scatter_buffer_va)
                return -ENOMEM;
  
@@ -70,7 +68,7 @@ index 7d6b695c4ab3..3ce5f0a24cbc 100644
        for (i = 0; i < PPC4XX_NUM_SD; i++) {
                dev->sdr[i].ptr = dev->scatter_buffer_pa +
                                  PPC4XX_SD_BUFFER_SIZE * i;
-@@ -1439,15 +1440,14 @@ static int crypto4xx_probe(struct platform_device *ofdev)
+@@ -1439,16 +1440,15 @@ static int crypto4xx_probe(struct platfo
        spin_lock_init(&core_dev->lock);
        INIT_LIST_HEAD(&core_dev->dev->alg_list);
        ratelimit_default_init(&core_dev->dev->aead_ratelimit);
@@ -83,14 +81,15 @@ index 7d6b695c4ab3..3ce5f0a24cbc 100644
 +              goto err_build_sdr;
  
        rc = crypto4xx_build_gdr(core_dev->dev);
--      if (rc)
+       if (rc)
 -              goto err_build_pdr;
 -
 -      rc = crypto4xx_build_sdr(core_dev->dev);
-       if (rc)
+-      if (rc)
                goto err_build_sdr;
  
-@@ -1493,7 +1493,6 @@ static int crypto4xx_probe(struct platform_device *ofdev)
+       /* Init tasklet for bottom half processing */
+@@ -1493,7 +1493,6 @@ err_iomap:
  err_build_sdr:
        crypto4xx_destroy_sdr(core_dev->dev);
        crypto4xx_destroy_gdr(core_dev->dev);
@@ -98,6 +97,3 @@ index 7d6b695c4ab3..3ce5f0a24cbc 100644
        crypto4xx_destroy_pdr(core_dev->dev);
        kfree(core_dev->dev);
  err_alloc_dev:
--- 
-2.25.0.rc0
-
index 4fc988c1ecf297c2d20254906a20372a0fa8f4c1..6668c3a91d8b7eb67ca43964177129770d7f15e8 100644 (file)
@@ -17,11 +17,9 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  drivers/crypto/amcc/crypto4xx_core.c | 12 ++++++------
  1 file changed, 6 insertions(+), 6 deletions(-)
 
-diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
-index 3ce5f0a24cbc..981de43ea5e2 100644
 --- a/drivers/crypto/amcc/crypto4xx_core.c
 +++ b/drivers/crypto/amcc/crypto4xx_core.c
-@@ -169,7 +169,7 @@ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev)
+@@ -169,7 +169,7 @@ static u32 crypto4xx_build_pdr(struct cr
        int i;
        dev->pdr = dma_alloc_coherent(dev->core_dev->device,
                                      sizeof(struct ce_pd) * PPC4XX_NUM_PD,
@@ -30,7 +28,7 @@ index 3ce5f0a24cbc..981de43ea5e2 100644
        if (!dev->pdr)
                return -ENOMEM;
  
-@@ -185,13 +185,13 @@ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev)
+@@ -185,13 +185,13 @@ static u32 crypto4xx_build_pdr(struct cr
        dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device,
                                   sizeof(union shadow_sa_buf) * PPC4XX_NUM_PD,
                                   &dev->shadow_sa_pool_pa,
@@ -46,7 +44,7 @@ index 3ce5f0a24cbc..981de43ea5e2 100644
        if (!dev->shadow_sr_pool)
                return -ENOMEM;
        for (i = 0; i < PPC4XX_NUM_PD; i++) {
-@@ -277,7 +277,7 @@ static u32 crypto4xx_build_gdr(struct crypto4xx_device *dev)
+@@ -277,7 +277,7 @@ static u32 crypto4xx_build_gdr(struct cr
  {
        dev->gdr = dma_alloc_coherent(dev->core_dev->device,
                                      sizeof(struct ce_gd) * PPC4XX_NUM_GD,
@@ -55,7 +53,7 @@ index 3ce5f0a24cbc..981de43ea5e2 100644
        if (!dev->gdr)
                return -ENOMEM;
  
-@@ -358,14 +358,14 @@ static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev)
+@@ -358,14 +358,14 @@ static u32 crypto4xx_build_sdr(struct cr
        dev->scatter_buffer_va =
                dma_alloc_coherent(dev->core_dev->device,
                        PPC4XX_SD_BUFFER_SIZE * PPC4XX_NUM_SD,
@@ -72,6 +70,3 @@ index 3ce5f0a24cbc..981de43ea5e2 100644
        if (!dev->sdr)
                return -ENOMEM;
  
--- 
-2.25.0.rc0
-
index 18f4c72de89630978cb264f1ffd2a1bddd9184a5..e1889540947edc239f3869ac0e57745a45ece976 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/powerpc/platforms/44x/Kconfig
 +++ b/arch/powerpc/platforms/44x/Kconfig
-@@ -131,6 +131,17 @@ config CANYONLANDS
+@@ -121,6 +121,17 @@ config CANYONLANDS
        help
          This option enables support for the AMCC PPC460EX evaluation board.
  
@@ -20,7 +20,7 @@
        depends on 44x
 --- a/arch/powerpc/platforms/44x/ppc44x_simple.c
 +++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
-@@ -50,6 +50,7 @@ machine_device_initcall(ppc44x_simple, p
+@@ -47,6 +47,7 @@ machine_device_initcall(ppc44x_simple, p
   * board.c file for it rather than adding it to this list.
   */
  static char *board[] __initdata = {
index 536a74ef00474c1ad023e161e7f10e4e6db5a162..b0619852b964ef48c44070574aa95c16f5a3bcc3 100644 (file)
@@ -10,7 +10,7 @@
  obj-$(CONFIG_WARP)    += warp.o
 --- a/arch/powerpc/platforms/44x/Kconfig
 +++ b/arch/powerpc/platforms/44x/Kconfig
-@@ -260,6 +260,19 @@ config ICON
+@@ -243,6 +243,19 @@ config ICON
        help
          This option enables support for the AMCC PPC440SPe evaluation board.
  
index 6eb04b2c25167d9b77a8fc55cc93130b102cb9e8..9c0ed35cf1c7733271994ba78c79d048ead706dc 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/powerpc/platforms/4xx/pci.c
 +++ b/arch/powerpc/platforms/4xx/pci.c
-@@ -1905,9 +1905,9 @@ static void __init ppc4xx_configure_pcie
+@@ -1904,9 +1904,9 @@ static void __init ppc4xx_configure_pcie
                 * if it works
                 */
                out_le32(mbase + PECFG_PIM0LAL, 0x00000000);
index 0bc4b2c65b59bb7e62c17baa1db1a204136dd27a..0ccbc22f1c55ddd0c5e1f12032fb387fb5ad92c9 100644 (file)
@@ -48,7 +48,7 @@ Signed-off-by: Vinod Koul <vkoul@kernel.org>
  
  #include "xhci.h"
  #include "xhci-trace.h"
-@@ -48,6 +50,44 @@
+@@ -56,6 +58,44 @@
  #define PCI_DEVICE_ID_AMD_PROMONTORYA_1                       0x43bc
  #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI              0x1142
  
@@ -93,7 +93,7 @@ Signed-off-by: Vinod Koul <vkoul@kernel.org>
  static const char hcd_name[] = "xhci_hcd";
  
  static struct hc_driver __read_mostly xhci_pci_hc_driver;
-@@ -262,6 +302,873 @@ static void xhci_pme_acpi_rtd3_enable(st
+@@ -281,6 +321,873 @@ static void xhci_pme_acpi_rtd3_enable(st
  static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
  #endif /* CONFIG_ACPI */
  
@@ -967,7 +967,7 @@ Signed-off-by: Vinod Koul <vkoul@kernel.org>
  /* called during probe() after chip reset completes */
  static int xhci_pci_setup(struct usb_hcd *hcd)
  {
-@@ -300,6 +1207,27 @@ static int xhci_pci_probe(struct pci_dev
+@@ -319,6 +1226,27 @@ static int xhci_pci_probe(struct pci_dev
        struct hc_driver *driver;
        struct usb_hcd *hcd;
  
@@ -995,7 +995,7 @@ Signed-off-by: Vinod Koul <vkoul@kernel.org>
        driver = (struct hc_driver *)id->driver_data;
  
        /* Prevent runtime suspending between USB-2 and USB-3 initialization */
-@@ -361,6 +1289,16 @@ static void xhci_pci_remove(struct pci_d
+@@ -383,6 +1311,16 @@ static void xhci_pci_remove(struct pci_d
  {
        struct xhci_hcd *xhci;
  
@@ -1011,8 +1011,8 @@ Signed-off-by: Vinod Koul <vkoul@kernel.org>
 +
        xhci = hcd_to_xhci(pci_get_drvdata(dev));
        xhci->xhc_state |= XHCI_STATE_REMOVING;
-       if (xhci->shared_hcd) {
-@@ -484,6 +1422,11 @@ static int xhci_pci_resume(struct usb_hc
+@@ -510,6 +1448,11 @@ static int xhci_pci_resume(struct usb_hc
        if (pdev->vendor == PCI_VENDOR_ID_INTEL)
                usb_enable_intel_xhci_ports(pdev);
  
index a745ea6f44a263aa8e5ca806b49521319856af6c..e095610f61b82a2b977142c8efb442b8d1cb680b 100644 (file)
@@ -13,7 +13,7 @@ produce a noisy warning.
 
 --- a/drivers/usb/host/xhci-pci.c
 +++ b/drivers/usb/host/xhci-pci.c
-@@ -215,6 +215,7 @@ static void xhci_pci_quirks(struct devic
+@@ -272,6 +272,7 @@ static void xhci_pci_quirks(struct devic
            pdev->device == 0x0015) {
                xhci->quirks |= XHCI_RESET_ON_RESUME;
                xhci->quirks |= XHCI_ZERO_64B_REGS;
@@ -23,7 +23,7 @@ produce a noisy warning.
                xhci->quirks |= XHCI_RESET_ON_RESUME;
 --- a/drivers/usb/host/xhci.c
 +++ b/drivers/usb/host/xhci.c
-@@ -422,10 +422,14 @@ static int xhci_try_enable_msi(struct us
+@@ -423,10 +423,14 @@ static int xhci_try_enable_msi(struct us
                free_irq(hcd->irq, hcd);
        hcd->irq = 0;
  
@@ -43,9 +43,9 @@ produce a noisy warning.
                hcd->msi_enabled = 1;
 --- a/drivers/usb/host/xhci.h
 +++ b/drivers/usb/host/xhci.h
-@@ -1876,6 +1876,7 @@ struct xhci_hcd {
-       /* support xHCI 0.96 spec USB2 software LPM */
-       unsigned                sw_lpm_support:1;
+@@ -1874,6 +1874,7 @@ struct xhci_hcd {
+       struct xhci_hub         usb2_rhub;
+       struct xhci_hub         usb3_rhub;
        /* support xHCI 1.0 spec USB2 hardware LPM */
 +#define XHCI_FORCE_MSI                (1 << 24)
        unsigned                hw_lpm_support:1;
index f8b30ae1b33cf1ab87431867cbfed39b23899f6f..f0ed5a7cffb444396740c37fa97f9a672e3df655 100644 (file)
@@ -13,7 +13,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
 
 --- a/drivers/hwmon/tc654.c
 +++ b/drivers/hwmon/tc654.c
-@@ -64,6 +64,11 @@ enum tc654_regs {
+@@ -55,6 +55,11 @@ enum tc654_regs {
  /* Register data is read (and cached) at most once per second. */
  #define TC654_UPDATE_INTERVAL         HZ
  
@@ -25,7 +25,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  struct tc654_data {
        struct i2c_client *client;
  
-@@ -497,6 +502,29 @@ static const struct i2c_device_id tc654_
+@@ -482,6 +487,29 @@ static const struct i2c_device_id tc654_
        {}
  };
  
@@ -55,7 +55,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  MODULE_DEVICE_TABLE(i2c, tc654_id);
  
  static struct i2c_driver tc654_driver = {
-@@ -505,6 +533,7 @@ static struct i2c_driver tc654_driver =
+@@ -490,6 +518,7 @@ static struct i2c_driver tc654_driver =
                   },
        .probe = tc654_probe,
        .id_table = tc654_id,
index c3c6870faba2f719e1631906aed17a2a8b4636c4..a7b0a58f7c0870f1d24ab7fee9750719126c2261 100644 (file)
@@ -11,8 +11,6 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  drivers/hwmon/tc654.c | 103 +++++++++++++++++++++++++++++++++++-------
  1 file changed, 86 insertions(+), 17 deletions(-)
 
-diff --git a/drivers/hwmon/tc654.c b/drivers/hwmon/tc654.c
-index c7939b7c417b..66e6bbe795a5 100644
 --- a/drivers/hwmon/tc654.c
 +++ b/drivers/hwmon/tc654.c
 @@ -15,6 +15,7 @@
@@ -33,7 +31,7 @@ index c7939b7c417b..66e6bbe795a5 100644
  };
  
  /* helper to grab and cache data, at most one time per second */
-@@ -367,36 +371,30 @@ static ssize_t pwm_mode_store(struct device *dev, struct device_attribute *da,
+@@ -367,36 +371,30 @@ static ssize_t pwm_mode_store(struct dev
  static const int tc654_pwm_map[16] = { 77,  88, 102, 112, 124, 136, 148, 160,
                                      172, 184, 196, 207, 219, 231, 243, 255};
  
@@ -80,7 +78,7 @@ index c7939b7c417b..66e6bbe795a5 100644
        mutex_lock(&data->update_lock);
  
        if (val == 0)
-@@ -416,6 +414,22 @@ static ssize_t pwm_store(struct device *dev, struct device_attribute *da,
+@@ -416,6 +414,22 @@ static ssize_t pwm_store(struct device *
  
  out:
        mutex_unlock(&data->update_lock);
@@ -103,7 +101,7 @@ index c7939b7c417b..66e6bbe795a5 100644
        return ret < 0 ? ret : count;
  }
  
-@@ -447,6 +461,47 @@ static struct attribute *tc654_attrs[] = {
+@@ -447,6 +461,47 @@ static struct attribute *tc654_attrs[] =
  
  ATTRIBUTE_GROUPS(tc654);
  
@@ -151,7 +149,7 @@ index c7939b7c417b..66e6bbe795a5 100644
  /*
   * device probe and removal
   */
-@@ -478,7 +533,21 @@ static int tc654_probe(struct i2c_client *client,
+@@ -478,7 +533,21 @@ static int tc654_probe(struct i2c_client
        hwmon_dev =
            devm_hwmon_device_register_with_groups(dev, client->name, data,
                                                   tc654_groups);
@@ -174,6 +172,3 @@ index c7939b7c417b..66e6bbe795a5 100644
  }
  
  static const struct i2c_device_id tc654_id[] = {
--- 
-2.24.0
-
index c6bb6c5f1a237a32ee4534fed28b0a7e02dcc345..c2cc632693cd3ac60a3655d8c36a258d9d211225 100644 (file)
@@ -16,8 +16,6 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  arch/powerpc/boot/Makefile | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
-diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
-index dfbd7f22eef5..0bdef8e5f362 100644
 --- a/arch/powerpc/boot/Makefile
 +++ b/arch/powerpc/boot/Makefile
 @@ -254,7 +254,7 @@ compressor-$(CONFIG_KERNEL_LZO) := lzo
@@ -29,6 +27,3 @@ index dfbd7f22eef5..0bdef8e5f362 100644
                $(CROSSWRAP) $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) \
                vmlinux
  
--- 
-2.24.0
-
index cfdf8c87e5317aa5354f06c76cfaa31cded124a5..e50ad2297b016807017841718b8c238922478162 100644 (file)
@@ -9,6 +9,7 @@ SUBTARGETS:=generic nand tiny
 FEATURES:=ramdisk
 
 KERNEL_PATCHVER:=4.19
+KERNEL_TESTING_PATCHVER:=5.4
 
 include $(INCLUDE_DIR)/target.mk
 
diff --git a/target/linux/ath79/config-5.4 b/target/linux/ath79/config-5.4
new file mode 100644 (file)
index 0000000..3f7f26a
--- /dev/null
@@ -0,0 +1,250 @@
+CONFIG_64BIT_TIME=y
+CONFIG_AG71XX=y
+CONFIG_AR8216_PHY=y
+CONFIG_AR8216_PHY_LEDS=y
+CONFIG_ARCH_32BIT_OFF_T=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN=y
+CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y
+CONFIG_ARCH_HAS_DMA_WRITE_COMBINE=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_RESET_CONTROLLER=y
+CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y
+CONFIG_ARCH_HAS_UNCACHED_SEGMENT=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_MMAP_RND_BITS_MAX=15
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_ARCH_USE_MEMREMAP_PROT=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ATH79=y
+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,jffs2"
+CONFIG_CMDLINE_BOOL=y
+# CONFIG_CMDLINE_OVERRIDE is not set
+CONFIG_COMMON_CLK=y
+# CONFIG_COMMON_CLK_BOSTON is not set
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_CPU_GENERIC_DUMP_TLB=y
+CONFIG_CPU_HAS_LOAD_STORE_LR=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_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_CPU_SUPPORTS_MSA=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_DECLARE_COHERENT=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NONCOHERENT_CACHE_SYNC=y
+CONFIG_DTC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_EFI_EARLYCON=y
+CONFIG_ETHERNET_PACKET_MANGLE=y
+CONFIG_FIXED_PHY=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_AUTOSELECT=y
+CONFIG_FONT_SUPPORT=y
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_LIB_ASHLDI3=y
+CONFIG_GENERIC_LIB_ASHRDI3=y
+CONFIG_GENERIC_LIB_CMPDI2=y
+CONFIG_GENERIC_LIB_LSHRDI3=y
+CONFIG_GENERIC_LIB_UCMPDI2=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_74X164=y
+CONFIG_GPIO_ATH79=y
+CONFIG_GPIO_GENERIC=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_ARCH_COMPILER_H=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_ASM_MODVERSIONS=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FAST_GUP=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_VDSO=y
+CONFIG_HAVE_IDE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_PCI=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_RSEQ=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_IMAGE_CMDLINE_HACK=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_MIPS_CPU=y
+CONFIG_IRQ_WORK=y
+CONFIG_KASAN_STACK=1
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_RESET is not set
+CONFIG_LIBFDT=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_GPIO=y
+CONFIG_MEMFD_CREATE=y
+CONFIG_MFD_SYSCON=y
+CONFIG_MIGRATION=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 is not set
+CONFIG_MIPS_CMDLINE_FROM_DTB=y
+# CONFIG_MIPS_ELF_APPENDED_DTB is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_MIPS_NO_APPENDED_DTB is not set
+CONFIG_MIPS_RAW_APPENDED_DTB=y
+CONFIG_MIPS_SPRAM=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+CONFIG_MTD_PARSER_CYBERTAN=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPLIT_LZMA_FW=y
+CONFIG_MTD_SPLIT_SEAMA_FW=y
+CONFIG_MTD_SPLIT_TPLINK_FW=y
+CONFIG_MTD_SPLIT_UIMAGE_FW=y
+CONFIG_MTD_TPLINK_PARTS=y
+CONFIG_MTD_VIRT_CONCAT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_NVMEM=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_KOBJ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_PCI=y
+CONFIG_PCI_AR71XX=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_PHY_AR7100_USB is not set
+# CONFIG_PHY_AR7200_USB is not set
+# CONFIG_PHY_ATH79_USB is not set
+CONFIG_PINCTRL=y
+CONFIG_RATIONAL=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_RESET_ATH79=y
+CONFIG_RESET_CONTROLLER=y
+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_SERIAL_MCTRL_GPIO=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SPI=y
+CONFIG_SPI_AR934X=y
+CONFIG_SPI_ATH79=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+# CONFIG_SPI_RB4XX 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_TARGET_ISA_REV=2
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TINY_SRCU=y
+CONFIG_UBSAN_ALIGNMENT=y
+CONFIG_UNIX_SCM=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USE_OF=y
index 6cd1518e3ac8657a9687b07ba1c07fc85e118e2e..a15a1d897281a0cbbf82224b24461d0ce2f9e2e1 100644 (file)
@@ -1,4 +1,5 @@
 CONFIG_AT803X_PHY=y
+CONFIG_BCM_NET_PHYLIB=y
 CONFIG_BROADCOM_PHY=y
 CONFIG_GPIO_WATCHDOG=y
 CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y
@@ -7,8 +8,8 @@ CONFIG_IP17XX_PHY=y
 CONFIG_LEDS_RESET=y
 CONFIG_MARVELL_PHY=y
 CONFIG_MICREL_PHY=y
-CONFIG_MTD_REDBOOT_PARTS=y
 CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-3
+CONFIG_MTD_REDBOOT_PARTS=y
 CONFIG_MTD_SPLIT_EVA_FW=y
 CONFIG_MTD_SPLIT_MINOR_FW=y
 CONFIG_PHY_AR7100_USB=y
index b03f977a07f63c90374a17159d75363d50b14d38..50bc55079432b2ac6b90a815f9c7df9f999d89d3 100644 (file)
@@ -1,19 +1,26 @@
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_AR934X=y
+CONFIG_CRC16=y
+CONFIG_CRYPTO_ACOMP2=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_HASH_INFO=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
 CONFIG_MTD_NAND_CORE=y
-CONFIG_MTD_NAND_ECC=y
 CONFIG_MTD_SPI_NAND=y
 CONFIG_MTD_SPLIT_MINOR_FW=y
 CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_BLOCK=y
-CONFIG_MTD_UBI_WL_THRESHOLD=4096
 CONFIG_MTD_UBI_BEB_LIMIT=20
+CONFIG_MTD_UBI_BLOCK=y
 # CONFIG_MTD_UBI_FASTMAP is not set
 # CONFIG_MTD_UBI_GLUEBI is not set
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
 # CONFIG_PCI_AR71XX is not set
-# CONFIG_PHY_AR7100_USB is not set
 CONFIG_PHY_AR7200_USB=y
+CONFIG_SGL_ALLOC=y
 CONFIG_UBIFS_FS=y
 CONFIG_UBIFS_FS_ADVANCED_COMPR=y
 CONFIG_UBIFS_FS_LZO=y
 CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_ZSTD is not set
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_ZLIB_INFLATE=y
diff --git a/target/linux/ath79/patches-5.4/0002-watchdog-ath79-fix-maximum-timeout.patch b/target/linux/ath79/patches-5.4/0002-watchdog-ath79-fix-maximum-timeout.patch
new file mode 100644 (file)
index 0000000..495721f
--- /dev/null
@@ -0,0 +1,32 @@
+From 5f5c9858af167f842ee8df053920b98387a71af1 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 5 Mar 2018 11:41:25 +0100
+Subject: [PATCH 02/27] watchdog: 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 <john@phrozen.org>
+---
+ drivers/watchdog/ath79_wdt.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/watchdog/ath79_wdt.c
++++ b/drivers/watchdog/ath79_wdt.c
+@@ -111,10 +111,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/ath79/patches-5.4/0003-leds-add-reset-controller-based-driver.patch b/target/linux/ath79/patches-5.4/0003-leds-add-reset-controller-based-driver.patch
new file mode 100644 (file)
index 0000000..3249e1e
--- /dev/null
@@ -0,0 +1,186 @@
+From ecbd9c87f073f097d9fe56390353e64e963e866a Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 10:03:03 +0100
+Subject: [PATCH 03/27] leds: add reset-controller based driver
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/leds/Kconfig      |  11 ++++
+ drivers/leds/Makefile     |   1 +
+ drivers/leds/leds-reset.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 149 insertions(+)
+ create mode 100644 drivers/leds/leds-reset.c
+
+--- a/drivers/leds/Kconfig
++++ b/drivers/leds/Kconfig
+@@ -823,6 +823,17 @@ config LEDS_LM36274
+         Say Y to enable the LM36274 LED driver for TI LMU devices.
+         This supports the LED device LM36274.
++config LEDS_RESET
++      tristate "LED support for reset-controller API"
++      depends on LEDS_CLASS
++      depends on RESET_CONTROLLER
++      help
++        This option enables support for LEDs connected to pins driven by reset
++        controllers. Yes, DNI actual built HW like that.
++
++        To compile this driver as a module, choose M here: the module
++        will be called leds-reset.
++
+ comment "LED Triggers"
+ source "drivers/leds/trigger/Kconfig"
+--- /dev/null
++++ b/drivers/leds/leds-reset.c
+@@ -0,0 +1,140 @@
++/*
++ * Copyright (C) 2018 John Crispin <john@phrozen.org>
++ *
++ * 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 <linux/err.h>
++#include <linux/reset.h>
++#include <linux/kernel.h>
++#include <linux/leds.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++
++struct reset_led_data {
++      struct led_classdev cdev;
++      struct reset_control *rst;
++};
++
++static inline struct reset_led_data *
++                      cdev_to_reset_led_data(struct led_classdev *led_cdev)
++{
++      return container_of(led_cdev, struct reset_led_data, cdev);
++}
++
++static void reset_led_set(struct led_classdev *led_cdev,
++      enum led_brightness value)
++{
++      struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev);
++
++      if (value == LED_OFF)
++              reset_control_assert(led_dat->rst);
++      else
++              reset_control_deassert(led_dat->rst);
++}
++
++struct reset_leds_priv {
++      int num_leds;
++      struct reset_led_data leds[];
++};
++
++static inline int sizeof_reset_leds_priv(int num_leds)
++{
++      return sizeof(struct reset_leds_priv) +
++              (sizeof(struct reset_led_data) * num_leds);
++}
++
++static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct fwnode_handle *child;
++      struct reset_leds_priv *priv;
++      int count, ret;
++
++      count = device_get_child_node_count(dev);
++      if (!count)
++              return ERR_PTR(-ENODEV);
++
++      priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL);
++      if (!priv)
++              return ERR_PTR(-ENOMEM);
++
++      device_for_each_child_node(dev, child) {
++              struct reset_led_data *led = &priv->leds[priv->num_leds];
++              struct device_node *np = to_of_node(child);
++
++              ret = fwnode_property_read_string(child, "label", &led->cdev.name);
++              if (!led->cdev.name) {
++                      fwnode_handle_put(child);
++                      return ERR_PTR(-EINVAL);
++              }
++              led->rst = __of_reset_control_get(np, NULL, 0, 0, 0, true);
++              if (IS_ERR(led->rst))
++                      return ERR_PTR(-EINVAL);
++
++              fwnode_property_read_string(child, "linux,default-trigger",
++                                              &led->cdev.default_trigger);
++
++              led->cdev.brightness_set = reset_led_set;
++              ret = devm_led_classdev_register(&pdev->dev, &led->cdev);
++              if (ret < 0)
++                      return ERR_PTR(ret);
++              led->cdev.dev->of_node = np;
++              priv->num_leds++;
++      }
++
++      return priv;
++}
++
++static const struct of_device_id of_reset_leds_match[] = {
++      { .compatible = "reset-leds", },
++      {},
++};
++
++MODULE_DEVICE_TABLE(of, of_reset_leds_match);
++
++static int reset_led_probe(struct platform_device *pdev)
++{
++      struct reset_leds_priv *priv;
++
++      priv = reset_leds_create(pdev);
++      if (IS_ERR(priv))
++              return PTR_ERR(priv);
++
++      platform_set_drvdata(pdev, priv);
++
++      return 0;
++}
++
++static void reset_led_shutdown(struct platform_device *pdev)
++{
++      struct reset_leds_priv *priv = platform_get_drvdata(pdev);
++      int i;
++
++      for (i = 0; i < priv->num_leds; i++) {
++              struct reset_led_data *led = &priv->leds[i];
++
++              if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN))
++                      reset_led_set(&led->cdev, LED_OFF);
++      }
++}
++
++static struct platform_driver reset_led_driver = {
++      .probe          = reset_led_probe,
++      .shutdown       = reset_led_shutdown,
++      .driver         = {
++              .name   = "leds-reset",
++              .of_match_table = of_reset_leds_match,
++      },
++};
++
++module_platform_driver(reset_led_driver);
++
++MODULE_AUTHOR("John Crispin <john@phrozen.org>");
++MODULE_DESCRIPTION("reset controller LED driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:leds-reset");
+--- a/drivers/leds/Makefile
++++ b/drivers/leds/Makefile
+@@ -85,6 +85,7 @@ obj-$(CONFIG_LEDS_LM3601X)           += leds-lm36
+ obj-$(CONFIG_LEDS_TI_LMU_COMMON)      += leds-ti-lmu-common.o
+ obj-$(CONFIG_LEDS_LM3697)             += leds-lm3697.o
+ obj-$(CONFIG_LEDS_LM36274)            += leds-lm36274.o
++obj-$(CONFIG_LEDS_RESET)              += leds-reset.o
+ # LED SPI Drivers
+ obj-$(CONFIG_LEDS_CR0014114)          += leds-cr0014114.o
diff --git a/target/linux/ath79/patches-5.4/0004-phy-add-ath79-usb-phys.patch b/target/linux/ath79/patches-5.4/0004-phy-add-ath79-usb-phys.patch
new file mode 100644 (file)
index 0000000..7956edb
--- /dev/null
@@ -0,0 +1,332 @@
+From 08c9d6ceef01893678a5d2e8a15517c745417f21 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 10:04:05 +0100
+Subject: [PATCH 04/27] phy: add ath79 usb phys
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/phy/Kconfig          |  16 ++++++
+ drivers/phy/Makefile         |   2 +
+ drivers/phy/phy-ar7100-usb.c | 124 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/phy/phy-ar7200-usb.c | 108 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 250 insertions(+)
+ create mode 100644 drivers/phy/phy-ar7100-usb.c
+ create mode 100644 drivers/phy/phy-ar7200-usb.c
+
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -24,6 +24,22 @@ config GENERIC_PHY_MIPI_DPHY
+         Provides a number of helpers a core functions for MIPI D-PHY
+         drivers to us.
++config PHY_AR7100_USB
++      tristate "Atheros AR7100 USB PHY driver"
++      depends on ATH79 || COMPILE_TEST
++      default y if USB_EHCI_HCD_PLATFORM
++      select PHY_SIMPLE
++      help
++        Enable this to support the USB PHY on Atheros AR7100 SoCs.
++
++config PHY_AR7200_USB
++      tristate "Atheros AR7200 USB PHY driver"
++      depends on ATH79 || COMPILE_TEST
++      default y if USB_EHCI_HCD_PLATFORM
++      select PHY_SIMPLE
++      help
++        Enable this to support the USB PHY on Atheros AR7200 SoCs.
++
+ config PHY_LPC18XX_USB_OTG
+       tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
+       depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
+--- a/drivers/phy/Makefile
++++ b/drivers/phy/Makefile
+@@ -4,6 +4,8 @@
+ #
+ obj-$(CONFIG_GENERIC_PHY)             += phy-core.o
++obj-$(CONFIG_PHY_AR7100_USB)          += phy-ar7100-usb.o
++obj-$(CONFIG_PHY_AR7200_USB)          += phy-ar7200-usb.o
+ obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY)   += phy-core-mipi-dphy.o
+ obj-$(CONFIG_PHY_LPC18XX_USB_OTG)     += phy-lpc18xx-usb-otg.o
+ obj-$(CONFIG_PHY_XGENE)                       += phy-xgene.o
+--- /dev/null
++++ b/drivers/phy/phy-ar7100-usb.c
+@@ -0,0 +1,140 @@
++/*
++ * Copyright (C) 2018 John Crispin <john@phrozen.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/phy/phy.h>
++#include <linux/delay.h>
++#include <linux/reset.h>
++#include <linux/of_gpio.h>
++
++#include <asm/mach-ath79/ath79.h>
++#include <asm/mach-ath79/ar71xx_regs.h>
++
++struct ar7100_usb_phy {
++      struct reset_control    *rst_phy;
++      struct reset_control    *rst_host;
++      struct reset_control    *rst_ohci_dll;
++      void __iomem            *io_base;
++      struct phy              *phy;
++      int                     gpio;
++};
++
++static int ar7100_usb_phy_power_off(struct phy *phy)
++{
++      struct ar7100_usb_phy *priv = phy_get_drvdata(phy);
++      int err = 0;
++
++      err |= reset_control_assert(priv->rst_host);
++      err |= reset_control_assert(priv->rst_phy);
++      err |= reset_control_assert(priv->rst_ohci_dll);
++
++      return err;
++}
++
++static int ar7100_usb_phy_power_on(struct phy *phy)
++{
++      struct ar7100_usb_phy *priv = phy_get_drvdata(phy);
++      int err = 0;
++
++      err |= ar7100_usb_phy_power_off(phy);
++      mdelay(100);
++      err |= reset_control_deassert(priv->rst_ohci_dll);
++      err |= reset_control_deassert(priv->rst_phy);
++      err |= reset_control_deassert(priv->rst_host);
++      mdelay(500);
++      iowrite32(0xf0000, priv->io_base + AR71XX_USB_CTRL_REG_CONFIG);
++      iowrite32(0x20c00, priv->io_base + AR71XX_USB_CTRL_REG_FLADJ);
++
++      return err;
++}
++
++static const struct phy_ops ar7100_usb_phy_ops = {
++      .power_on       = ar7100_usb_phy_power_on,
++      .power_off      = ar7100_usb_phy_power_off,
++      .owner          = THIS_MODULE,
++};
++
++static int ar7100_usb_phy_probe(struct platform_device *pdev)
++{
++      struct phy_provider *phy_provider;
++      struct resource *res;
++      struct ar7100_usb_phy *priv;
++
++      priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      priv->io_base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(priv->io_base))
++              return PTR_ERR(priv->io_base);
++
++      priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy");
++      if (IS_ERR(priv->rst_phy)) {
++              dev_err(&pdev->dev, "phy reset is missing\n");
++              return PTR_ERR(priv->rst_phy);
++      }
++
++      priv->rst_host = devm_reset_control_get(&pdev->dev, "usb-host");
++      if (IS_ERR(priv->rst_host)) {
++              dev_err(&pdev->dev, "host reset is missing\n");
++              return PTR_ERR(priv->rst_host);
++      }
++
++      priv->rst_ohci_dll = devm_reset_control_get(&pdev->dev, "usb-ohci-dll");
++      if (IS_ERR(priv->rst_ohci_dll)) {
++              dev_err(&pdev->dev, "ohci-dll reset is missing\n");
++              return PTR_ERR(priv->rst_host);
++      }
++
++      priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7100_usb_phy_ops);
++      if (IS_ERR(priv->phy)) {
++              dev_err(&pdev->dev, "failed to create PHY\n");
++              return PTR_ERR(priv->phy);
++      }
++
++      priv->gpio = of_get_gpio(pdev->dev.of_node, 0);
++      if (priv->gpio >= 0) {
++              int ret = devm_gpio_request(&pdev->dev, priv->gpio, dev_name(&pdev->dev));
++
++              if (ret) {
++                      dev_err(&pdev->dev, "failed to request gpio\n");
++                      return ret;
++              }
++              gpio_export_with_name(priv->gpio, 0, dev_name(&pdev->dev));
++              gpio_set_value(priv->gpio, 1);
++      }
++
++      phy_set_drvdata(priv->phy, priv);
++
++      phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
++
++
++      return PTR_ERR_OR_ZERO(phy_provider);
++}
++
++static const struct of_device_id ar7100_usb_phy_of_match[] = {
++      { .compatible = "qca,ar7100-usb-phy" },
++      {}
++};
++MODULE_DEVICE_TABLE(of, ar7100_usb_phy_of_match);
++
++static struct platform_driver ar7100_usb_phy_driver = {
++      .probe  = ar7100_usb_phy_probe,
++      .driver = {
++              .of_match_table = ar7100_usb_phy_of_match,
++              .name           = "ar7100-usb-phy",
++      }
++};
++module_platform_driver(ar7100_usb_phy_driver);
++
++MODULE_DESCRIPTION("ATH79 USB PHY driver");
++MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/phy/phy-ar7200-usb.c
+@@ -0,0 +1,135 @@
++/*
++ * Copyright (C) 2015 Alban Bedel <albeu@free.fr>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/phy/phy.h>
++#include <linux/reset.h>
++#include <linux/of_gpio.h>
++
++struct ar7200_usb_phy {
++      struct reset_control    *rst_phy;
++      struct reset_control    *rst_phy_analog;
++      struct reset_control    *suspend_override;
++      struct phy              *phy;
++      int                     gpio;
++};
++
++static int ar7200_usb_phy_power_on(struct phy *phy)
++{
++      struct ar7200_usb_phy *priv = phy_get_drvdata(phy);
++      int err = 0;
++
++      if (priv->suspend_override)
++              err = reset_control_assert(priv->suspend_override);
++      if (priv->rst_phy)
++              err |= reset_control_deassert(priv->rst_phy);
++      if (priv->rst_phy_analog)
++              err |= reset_control_deassert(priv->rst_phy_analog);
++
++      return err;
++}
++
++static int ar7200_usb_phy_power_off(struct phy *phy)
++{
++      struct ar7200_usb_phy *priv = phy_get_drvdata(phy);
++      int err = 0;
++
++      if (priv->suspend_override)
++              err = reset_control_deassert(priv->suspend_override);
++      if (priv->rst_phy)
++              err |= reset_control_assert(priv->rst_phy);
++      if (priv->rst_phy_analog)
++              err |= reset_control_assert(priv->rst_phy_analog);
++
++      return err;
++}
++
++static const struct phy_ops ar7200_usb_phy_ops = {
++      .power_on       = ar7200_usb_phy_power_on,
++      .power_off      = ar7200_usb_phy_power_off,
++      .owner          = THIS_MODULE,
++};
++
++static int ar7200_usb_phy_probe(struct platform_device *pdev)
++{
++      struct phy_provider *phy_provider;
++      struct ar7200_usb_phy *priv;
++
++      priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy");
++      if (IS_ERR(priv->rst_phy)) {
++              dev_err(&pdev->dev, "phy reset is missing\n");
++              return PTR_ERR(priv->rst_phy);
++      }
++
++      priv->rst_phy_analog = devm_reset_control_get_optional(
++              &pdev->dev, "usb-phy-analog");
++      if (IS_ERR(priv->rst_phy_analog)) {
++              if (PTR_ERR(priv->rst_phy_analog) == -ENOENT)
++                      priv->rst_phy_analog = NULL;
++              else
++                      return PTR_ERR(priv->rst_phy_analog);
++      }
++
++      priv->suspend_override = devm_reset_control_get_optional(
++              &pdev->dev, "usb-suspend-override");
++      if (IS_ERR(priv->suspend_override)) {
++              if (PTR_ERR(priv->suspend_override) == -ENOENT)
++                      priv->suspend_override = NULL;
++              else
++                      return PTR_ERR(priv->suspend_override);
++      }
++
++      priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7200_usb_phy_ops);
++      if (IS_ERR(priv->phy)) {
++              dev_err(&pdev->dev, "failed to create PHY\n");
++              return PTR_ERR(priv->phy);
++      }
++
++      priv->gpio = of_get_gpio(pdev->dev.of_node, 0);
++      if (priv->gpio >= 0) {
++              int ret = devm_gpio_request(&pdev->dev, priv->gpio, dev_name(&pdev->dev));
++
++              if (ret) {
++                      dev_err(&pdev->dev, "failed to request gpio\n");
++                      return ret;
++              }
++              gpio_export_with_name(priv->gpio, 0, dev_name(&pdev->dev));
++              gpio_set_value(priv->gpio, 1);
++      }
++
++      phy_set_drvdata(priv->phy, priv);
++
++      phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
++
++      return PTR_ERR_OR_ZERO(phy_provider);
++}
++
++static const struct of_device_id ar7200_usb_phy_of_match[] = {
++      { .compatible = "qca,ar7200-usb-phy" },
++      {}
++};
++MODULE_DEVICE_TABLE(of, ar7200_usb_phy_of_match);
++
++static struct platform_driver ar7200_usb_phy_driver = {
++      .probe  = ar7200_usb_phy_probe,
++      .driver = {
++              .of_match_table = ar7200_usb_phy_of_match,
++              .name           = "ar7200-usb-phy",
++      }
++};
++module_platform_driver(ar7200_usb_phy_driver);
++
++MODULE_DESCRIPTION("ATH79 USB PHY driver");
++MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/ath79/patches-5.4/0005-usb-add-more-OF-quirk-properties.patch b/target/linux/ath79/patches-5.4/0005-usb-add-more-OF-quirk-properties.patch
new file mode 100644 (file)
index 0000000..83033a1
--- /dev/null
@@ -0,0 +1,24 @@
+From 2201818e5bd33f389beceb3943fdfcf5a698fc5b Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 10:01:43 +0100
+Subject: [PATCH 05/27] usb: add more OF/quirk properties
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/usb/host/ehci-platform.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -159,6 +159,11 @@ static int ehci_platform_probe(struct pl
+       ehci = hcd_to_ehci(hcd);
+       if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
++              of_property_read_u32(dev->dev.of_node, "caps-offset", &pdata->caps_offset);
++
++              if (of_property_read_bool(dev->dev.of_node, "has-synopsys-hc-bug"))
++                      pdata->has_synopsys_hc_bug = 1;
++
+               if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
+                       ehci->big_endian_mmio = 1;
diff --git a/target/linux/ath79/patches-5.4/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-5.4/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch
new file mode 100644 (file)
index 0000000..ceda511
--- /dev/null
@@ -0,0 +1,168 @@
+From f3eacff2310a60348a755c50a8da6fc251fc8587 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 09:55:13 +0100
+Subject: [PATCH 07/33] irqchip/irq-ath79-intc: add irq cascade driver for
+ QCA9556 SoCs
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/irqchip/Makefile         |   1 +
+ drivers/irqchip/irq-ath79-intc.c | 142 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 143 insertions(+)
+ create mode 100644 drivers/irqchip/irq-ath79-intc.c
+
+--- a/drivers/irqchip/Makefile
++++ b/drivers/irqchip/Makefile
+@@ -4,6 +4,7 @@ obj-$(CONFIG_IRQCHIP)                  += irqchip.o
+ obj-$(CONFIG_AL_FIC)                  += irq-al-fic.o
+ obj-$(CONFIG_ALPINE_MSI)              += irq-alpine-msi.o
+ obj-$(CONFIG_ATH79)                   += irq-ath79-cpu.o
++obj-$(CONFIG_ATH79)                   += irq-ath79-intc.o
+ obj-$(CONFIG_ATH79)                   += irq-ath79-misc.o
+ obj-$(CONFIG_ARCH_BCM2835)            += irq-bcm2835.o
+ obj-$(CONFIG_ARCH_BCM2835)            += irq-bcm2836.o
+--- /dev/null
++++ b/drivers/irqchip/irq-ath79-intc.c
+@@ -0,0 +1,142 @@
++/*
++ *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
++ *
++ *  Copyright (C) 2018 John Crispin <john@phrozen.org>
++ *
++ *  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 <linux/interrupt.h>
++#include <linux/irqchip.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/irqdomain.h>
++
++#include <asm/irq_cpu.h>
++#include <asm/mach-ath79/ath79.h>
++#include <asm/mach-ath79/ar71xx_regs.h>
++
++#define ATH79_MAX_INTC_CASCADE        3
++
++struct ath79_intc {
++      struct irq_chip chip;
++      u32 irq;
++      u32 pending_mask;
++      u32 int_status;
++      u32 irq_mask[ATH79_MAX_INTC_CASCADE];
++      u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE];
++};
++
++static void ath79_intc_irq_handler(struct irq_desc *desc)
++{
++      struct irq_domain *domain = irq_desc_get_handler_data(desc);
++      struct ath79_intc *intc = domain->host_data;
++      u32 pending;
++
++      pending = ath79_reset_rr(intc->int_status);
++      pending &= intc->pending_mask;
++
++      if (pending) {
++              int i;
++
++              for (i = 0; i < domain->hwirq_max; i++)
++                      if (pending & intc->irq_mask[i]) {
++                              if (intc->irq_wb_chan[i] != 0xffffffff)
++                                      ath79_ddr_wb_flush(intc->irq_wb_chan[i]);
++                              generic_handle_irq(irq_find_mapping(domain, i));
++                      }
++      } else {
++              spurious_interrupt();
++      }
++}
++
++static void ath79_intc_irq_enable(struct irq_data *d)
++{
++      struct ath79_intc *intc = d->domain->host_data;
++      enable_irq(intc->irq);
++}
++
++static void ath79_intc_irq_disable(struct irq_data *d)
++{
++      struct ath79_intc *intc = d->domain->host_data;
++      disable_irq(intc->irq);
++}
++
++static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
++{
++      struct ath79_intc *intc = d->host_data;
++
++      irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq);
++
++      return 0;
++}
++
++static const struct irq_domain_ops ath79_irq_domain_ops = {
++      .xlate = irq_domain_xlate_onecell,
++      .map = ath79_intc_map,
++};
++
++static int __init ath79_intc_of_init(
++      struct device_node *node, struct device_node *parent)
++{
++      struct irq_domain *domain;
++      struct ath79_intc *intc;
++      int cnt, cntwb, i, err;
++
++      cnt = of_property_count_u32_elems(node, "qca,pending-bits");
++      if (cnt > ATH79_MAX_INTC_CASCADE)
++              panic("Too many INTC pending bits\n");
++
++      intc = kzalloc(sizeof(*intc), GFP_KERNEL);
++      if (!intc)
++              panic("Failed to allocate INTC memory\n");
++      intc->chip = dummy_irq_chip;
++      intc->chip.name = "INTC";
++      intc->chip.irq_disable = ath79_intc_irq_disable;
++      intc->chip.irq_enable = ath79_intc_irq_enable;
++
++      if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) {
++              panic("Missing address of interrupt status register\n");
++      }
++
++      of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt);
++      for (i = 0; i < cnt; i++) {
++              intc->pending_mask |= intc->irq_mask[i];
++              intc->irq_wb_chan[i] = 0xffffffff;
++      }
++
++      cntwb = of_count_phandle_with_args(
++              node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells");
++
++      for (i = 0; i < cntwb; i++) {
++              struct of_phandle_args args;
++              u32 irq = i;
++
++              of_property_read_u32_index(
++                      node, "qca,ddr-wb-channel-interrupts", i, &irq);
++              if (irq >= ATH79_MAX_INTC_CASCADE)
++                      continue;
++
++              err = of_parse_phandle_with_args(
++                      node, "qca,ddr-wb-channels",
++                      "#qca,ddr-wb-channel-cells",
++                      i, &args);
++              if (err)
++                      return err;
++
++              intc->irq_wb_chan[irq] = args.args[0];
++      }
++
++      intc->irq = irq_of_parse_and_map(node, 0);
++      if (!intc->irq)
++              panic("Failed to get INTC IRQ");
++
++      domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc);
++      irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain);
++
++      return 0;
++}
++IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc",
++              ath79_intc_of_init);
diff --git a/target/linux/ath79/patches-5.4/0008-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch b/target/linux/ath79/patches-5.4/0008-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch
new file mode 100644 (file)
index 0000000..13117d9
--- /dev/null
@@ -0,0 +1,23 @@
+From e029f998594f151008ecbfa024e2957edd2a5189 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 09:58:19 +0100
+Subject: [PATCH 08/33] irqchip/irq-ath79-cpu: drop !OF init helper
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/irqchip/irq-ath79-cpu.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+--- a/drivers/irqchip/irq-ath79-cpu.c
++++ b/drivers/irqchip/irq-ath79-cpu.c
+@@ -85,10 +85,3 @@ static int __init ar79_cpu_intc_of_init(
+ }
+ IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc",
+               ar79_cpu_intc_of_init);
+-
+-void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3)
+-{
+-      irq_wb_chan[2] = irq_wb_chan2;
+-      irq_wb_chan[3] = irq_wb_chan3;
+-      mips_cpu_irq_init();
+-}
diff --git a/target/linux/ath79/patches-5.4/0011-MIPS-ath79-select-the-PINCTRL-subsystem.patch b/target/linux/ath79/patches-5.4/0011-MIPS-ath79-select-the-PINCTRL-subsystem.patch
new file mode 100644 (file)
index 0000000..4ac58d1
--- /dev/null
@@ -0,0 +1,24 @@
+From 0c8856211d26f84277f7fcb0b9595e5c646bc464 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 10:00:55 +0100
+Subject: [PATCH 11/33] MIPS: ath79: select the PINCTRL subsystem
+
+The pinmux on QCA SoCs is controlled by a single register. The
+"pinctrl-single" driver can be used but requires the target
+to select PINCTRL.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -295,6 +295,7 @@ config BCM63XX
+       select SYS_HAS_EARLY_PRINTK
+       select SWAP_IO_SPACE
+       select GPIOLIB
++      select PINCTRL
+       select HAVE_CLK
+       select MIPS_L1_CACHE_SHIFT_4
+       select CLKDEV_LOOKUP
diff --git a/target/linux/ath79/patches-5.4/0017-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch b/target/linux/ath79/patches-5.4/0017-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch
new file mode 100644 (file)
index 0000000..bf7eb69
--- /dev/null
@@ -0,0 +1,57 @@
+From 4a4f869ec58ed8910b9b2e68d0eee50957e9bb20 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 25 Jun 2018 15:52:10 +0200
+Subject: [PATCH 17/33] dt-bindings: PCI: qcom,ar7100: adds binding doc
+
+With the driver being converted from platform_data to pure OF, we need to
+also add some docs.
+
+Cc: Rob Herring <robh+dt@kernel.org>
+Cc: devicetree@vger.kernel.org
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ .../devicetree/bindings/pci/qcom,ar7100-pci.txt    | 38 ++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt
+@@ -0,0 +1,38 @@
++* Qualcomm Atheros AR7100 PCI express root complex
++
++Required properties:
++- compatible: should contain "qcom,ar7100-pci" to identify the core.
++- reg: Should contain the register ranges as listed in the reg-names property.
++- reg-names: Definition: Must include the following entries
++      - "cfg_base"    IO Memory
++- #address-cells: set to <3>
++- #size-cells: set to <2>
++- ranges: ranges for the PCI memory and I/O regions
++- interrupt-map-mask and interrupt-map: standard PCI
++      properties to define the mapping of the PCIe interface to interrupt
++      numbers.
++- #interrupt-cells: set to <1>
++- interrupt-controller: define to enable the builtin IRQ cascade.
++
++Optional properties:
++- interrupt-parent: phandle to the MIPS IRQ controller
++
++* Example for ar7100
++      pcie-controller@180c0000 {
++              compatible = "qca,ar7100-pci";
++              #address-cells = <3>;
++              #size-cells = <2>;
++              bus-range = <0x0 0x0>;
++              reg = <0x17010000 0x100>;
++              reg-names = "cfg_base";
++              ranges = <0x2000000 0 0x10000000 0x10000000 0 0x07000000
++                        0x1000000 0 0x00000000 0x00000000 0 0x00000001>;
++              interrupt-parent = <&cpuintc>;
++              interrupts = <2>;
++
++              interrupt-controller;
++              #interrupt-cells = <1>;
++
++              interrupt-map-mask = <0 0 0 1>;
++              interrupt-map = <0 0 0 0 &pcie0 0>;
++      };
diff --git a/target/linux/ath79/patches-5.4/0018-MIPS-pci-ar71xx-convert-to-OF.patch b/target/linux/ath79/patches-5.4/0018-MIPS-pci-ar71xx-convert-to-OF.patch
new file mode 100644 (file)
index 0000000..e600a4f
--- /dev/null
@@ -0,0 +1,202 @@
+From 1855ab6b1d27f5b38a648baf57ff6a534afec26d Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:07:23 +0200
+Subject: [PATCH 18/33] MIPS: pci-ar71xx: convert to OF
+
+With the ath79 target getting converted to pure OF, we can drop all the
+platform data code and add the missing OF bits to the driver. We also add
+a irq domain for the PCI/e controllers cascade, thus making it usable from
+dts files.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/pci/pci-ar71xx.c | 82 +++++++++++++++++++++++-----------------------
+ 1 file changed, 41 insertions(+), 41 deletions(-)
+
+--- a/arch/mips/pci/pci-ar71xx.c
++++ b/arch/mips/pci/pci-ar71xx.c
+@@ -15,8 +15,11 @@
+ #include <linux/pci.h>
+ #include <linux/pci_regs.h>
+ #include <linux/interrupt.h>
++#include <linux/irqchip/chained_irq.h>
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
+ #include <asm/mach-ath79/ar71xx_regs.h>
+ #include <asm/mach-ath79/ath79.h>
+@@ -46,12 +49,13 @@
+ #define AR71XX_PCI_IRQ_COUNT          5
+ struct ar71xx_pci_controller {
++      struct device_node *np;
+       void __iomem *cfg_base;
+       int irq;
+-      int irq_base;
+       struct pci_controller pci_ctrl;
+       struct resource io_res;
+       struct resource mem_res;
++      struct irq_domain *domain;
+ };
+ /* Byte lane enable bits */
+@@ -225,29 +229,30 @@ static struct pci_ops ar71xx_pci_ops = {
+ static void ar71xx_pci_irq_handler(struct irq_desc *desc)
+ {
+-      struct ar71xx_pci_controller *apc;
+       void __iomem *base = ath79_reset_base;
++      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc);
+       u32 pending;
+-      apc = irq_desc_get_handler_data(desc);
+-
++      chained_irq_enter(chip, desc);
+       pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) &
+                 __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+       if (pending & AR71XX_PCI_INT_DEV0)
+-              generic_handle_irq(apc->irq_base + 0);
++              generic_handle_irq(irq_linear_revmap(apc->domain, 1));
+       else if (pending & AR71XX_PCI_INT_DEV1)
+-              generic_handle_irq(apc->irq_base + 1);
++              generic_handle_irq(irq_linear_revmap(apc->domain, 2));
+       else if (pending & AR71XX_PCI_INT_DEV2)
+-              generic_handle_irq(apc->irq_base + 2);
++              generic_handle_irq(irq_linear_revmap(apc->domain, 3));
+       else if (pending & AR71XX_PCI_INT_CORE)
+-              generic_handle_irq(apc->irq_base + 4);
++              generic_handle_irq(irq_linear_revmap(apc->domain, 4));
+       else
+               spurious_interrupt();
++      chained_irq_exit(chip, desc);
+ }
+ static void ar71xx_pci_irq_unmask(struct irq_data *d)
+@@ -258,7 +263,7 @@ static void ar71xx_pci_irq_unmask(struct
+       u32 t;
+       apc = irq_data_get_irq_chip_data(d);
+-      irq = d->irq - apc->irq_base;
++      irq = irq_linear_revmap(apc->domain, d->irq);
+       t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+       __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+@@ -275,7 +280,7 @@ static void ar71xx_pci_irq_mask(struct i
+       u32 t;
+       apc = irq_data_get_irq_chip_data(d);
+-      irq = d->irq - apc->irq_base;
++      irq = irq_linear_revmap(apc->domain, d->irq);
+       t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+       __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+@@ -291,24 +296,31 @@ static struct irq_chip ar71xx_pci_irq_ch
+       .irq_mask_ack   = ar71xx_pci_irq_mask,
+ };
++static int ar71xx_pci_irq_map(struct irq_domain *d,
++                            unsigned int irq, irq_hw_number_t hw)
++{
++      struct ar71xx_pci_controller *apc = d->host_data;
++
++      irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq);
++      irq_set_chip_data(irq, apc);
++
++      return 0;
++}
++
++static const struct irq_domain_ops ar71xx_pci_domain_ops = {
++      .xlate = irq_domain_xlate_onecell,
++      .map = ar71xx_pci_irq_map,
++};
++
+ static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
+ {
+       void __iomem *base = ath79_reset_base;
+-      int i;
+       __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+       __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS);
+-      BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT);
+-
+-      apc->irq_base = ATH79_PCI_IRQ_BASE;
+-      for (i = apc->irq_base;
+-           i < apc->irq_base + AR71XX_PCI_IRQ_COUNT; i++) {
+-              irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip,
+-                                       handle_level_irq);
+-              irq_set_chip_data(i, apc);
+-      }
+-
++      apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT,
++                                          &ar71xx_pci_domain_ops, apc);
+       irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler,
+                                        apc);
+ }
+@@ -325,6 +337,11 @@ static void ar71xx_pci_reset(void)
+       mdelay(100);
+ }
++static const struct of_device_id ar71xx_pci_ids[] = {
++      { .compatible = "qca,ar7100-pci" },
++      {},
++};
++
+ static int ar71xx_pci_probe(struct platform_device *pdev)
+ {
+       struct ar71xx_pci_controller *apc;
+@@ -345,26 +362,6 @@ static int ar71xx_pci_probe(struct platf
+       if (apc->irq < 0)
+               return -EINVAL;
+-      res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base");
+-      if (!res)
+-              return -EINVAL;
+-
+-      apc->io_res.parent = res;
+-      apc->io_res.name = "PCI IO space";
+-      apc->io_res.start = res->start;
+-      apc->io_res.end = res->end;
+-      apc->io_res.flags = IORESOURCE_IO;
+-
+-      res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base");
+-      if (!res)
+-              return -EINVAL;
+-
+-      apc->mem_res.parent = res;
+-      apc->mem_res.name = "PCI memory space";
+-      apc->mem_res.start = res->start;
+-      apc->mem_res.end = res->end;
+-      apc->mem_res.flags = IORESOURCE_MEM;
+-
+       ar71xx_pci_reset();
+       /* setup COMMAND register */
+@@ -377,9 +374,11 @@ static int ar71xx_pci_probe(struct platf
+       ar71xx_pci_irq_init(apc);
++      apc->np = pdev->dev.of_node;
+       apc->pci_ctrl.pci_ops = &ar71xx_pci_ops;
+       apc->pci_ctrl.mem_resource = &apc->mem_res;
+       apc->pci_ctrl.io_resource = &apc->io_res;
++      pci_load_of_ranges(&apc->pci_ctrl, pdev->dev.of_node);
+       register_pci_controller(&apc->pci_ctrl);
+@@ -390,6 +389,7 @@ static struct platform_driver ar71xx_pci
+       .probe = ar71xx_pci_probe,
+       .driver = {
+               .name = "ar71xx-pci",
++              .of_match_table = of_match_ptr(ar71xx_pci_ids),
+       },
+ };
diff --git a/target/linux/ath79/patches-5.4/0019-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch b/target/linux/ath79/patches-5.4/0019-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch
new file mode 100644 (file)
index 0000000..a0af79c
--- /dev/null
@@ -0,0 +1,61 @@
+From ea27764bc3ef2a05decf3ae05edffc289cd0d93c Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 25 Jun 2018 15:52:02 +0200
+Subject: [PATCH 19/33] dt-bindings: PCI: qcom,ar7240: adds binding doc
+
+With the driver being converted from platform_data to pure OF, we need to
+also add some docs.
+
+Cc: Rob Herring <robh+dt@kernel.org>
+Cc: devicetree@vger.kernel.org
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ .../devicetree/bindings/pci/qcom,ar7240-pci.txt    | 42 ++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt
+@@ -0,0 +1,42 @@
++* Qualcomm Atheros AR724X PCI express root complex
++
++Required properties:
++- compatible: should contain "qcom,ar7240-pci" to identify the core.
++- reg: Should contain the register ranges as listed in the reg-names property.
++- reg-names: Definition: Must include the following entries
++      - "crp_base"    Configuration registers
++      - "ctrl_base"   Control registers
++      - "cfg_base"    IO Memory
++- #address-cells: set to <3>
++- #size-cells: set to <2>
++- ranges: ranges for the PCI memory and I/O regions
++- interrupt-map-mask and interrupt-map: standard PCI
++      properties to define the mapping of the PCIe interface to interrupt
++      numbers.
++- #interrupt-cells: set to <1>
++- interrupt-parent: phandle to the MIPS IRQ controller
++
++Optional properties:
++- interrupt-controller: define to enable the builtin IRQ cascade.
++
++* Example for qca9557
++      pcie-controller@180c0000 {
++              compatible = "qcom,ar7240-pci";
++              #address-cells = <3>;
++              #size-cells = <2>;
++              bus-range = <0x0 0x0>;
++              reg = <0x180c0000 0x1000>,
++                    <0x180f0000 0x100>,
++                    <0x14000000 0x1000>;
++              reg-names = "crp_base", "ctrl_base", "cfg_base";
++              ranges = <0x2000000 0 0x10000000 0x10000000 0 0x04000000
++                        0x1000000 0 0x00000000 0x00000000 0 0x00000001>;
++              interrupt-parent = <&intc2>;
++              interrupts = <1>;
++
++              interrupt-controller;
++              #interrupt-cells = <1>;
++
++              interrupt-map-mask = <0 0 0 1>;
++              interrupt-map = <0 0 0 0 &pcie0 0>;
++      };
diff --git a/target/linux/ath79/patches-5.4/0020-MIPS-pci-ar724x-convert-to-OF.patch b/target/linux/ath79/patches-5.4/0020-MIPS-pci-ar724x-convert-to-OF.patch
new file mode 100644 (file)
index 0000000..b8a877c
--- /dev/null
@@ -0,0 +1,205 @@
+From a522ee0199d5d3ea114ca2e211f6ac398d3e8e0b Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:07:37 +0200
+Subject: [PATCH 20/33] MIPS: pci-ar724x: convert to OF
+
+With the ath79 target getting converted to pure OF, we can drop all the
+platform data code and add the missing OF bits to the driver. We also add
+a irq domain for the PCI/e controllers cascade, thus making it usable from
+dts files.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/pci/pci-ar724x.c | 88 ++++++++++++++++++++++------------------------
+ 1 file changed, 42 insertions(+), 46 deletions(-)
+
+--- a/arch/mips/pci/pci-ar724x.c
++++ b/arch/mips/pci/pci-ar724x.c
+@@ -11,8 +11,11 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/platform_device.h>
++#include <linux/irqchip/chained_irq.h>
+ #include <asm/mach-ath79/ath79.h>
+ #include <asm/mach-ath79/ar71xx_regs.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
+ #define AR724X_PCI_REG_APP            0x00
+ #define AR724X_PCI_REG_RESET          0x18
+@@ -42,17 +45,20 @@ struct ar724x_pci_controller {
+       void __iomem *crp_base;
+       int irq;
+-      int irq_base;
+       bool link_up;
+       bool bar0_is_cached;
+       u32  bar0_value;
++      struct device_node *np;
+       struct pci_controller pci_controller;
++      struct irq_domain *domain;
+       struct resource io_res;
+       struct resource mem_res;
+ };
++static struct irq_chip ar724x_pci_irq_chip;
++
+ static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc)
+ {
+       u32 reset;
+@@ -228,35 +234,31 @@ static struct pci_ops ar724x_pci_ops = {
+ static void ar724x_pci_irq_handler(struct irq_desc *desc)
+ {
+-      struct ar724x_pci_controller *apc;
+-      void __iomem *base;
++      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct ar724x_pci_controller *apc = irq_desc_get_handler_data(desc);
+       u32 pending;
+-      apc = irq_desc_get_handler_data(desc);
+-      base = apc->ctrl_base;
+-
+-      pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
+-                __raw_readl(base + AR724X_PCI_REG_INT_MASK);
++      chained_irq_enter(chip, desc);
++      pending = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_STATUS) &
++                __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_MASK);
+       if (pending & AR724X_PCI_INT_DEV0)
+-              generic_handle_irq(apc->irq_base + 0);
+-
++              generic_handle_irq(irq_linear_revmap(apc->domain, 1));
+       else
+               spurious_interrupt();
++      chained_irq_exit(chip, desc);
+ }
+ static void ar724x_pci_irq_unmask(struct irq_data *d)
+ {
+       struct ar724x_pci_controller *apc;
+       void __iomem *base;
+-      int offset;
+       u32 t;
+       apc = irq_data_get_irq_chip_data(d);
+       base = apc->ctrl_base;
+-      offset = apc->irq_base - d->irq;
+-      switch (offset) {
++      switch (irq_linear_revmap(apc->domain, d->irq)) {
+       case 0:
+               t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+               __raw_writel(t | AR724X_PCI_INT_DEV0,
+@@ -270,14 +272,12 @@ static void ar724x_pci_irq_mask(struct i
+ {
+       struct ar724x_pci_controller *apc;
+       void __iomem *base;
+-      int offset;
+       u32 t;
+       apc = irq_data_get_irq_chip_data(d);
+       base = apc->ctrl_base;
+-      offset = apc->irq_base - d->irq;
+-      switch (offset) {
++      switch (irq_linear_revmap(apc->domain, d->irq)) {
+       case 0:
+               t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+               __raw_writel(t & ~AR724X_PCI_INT_DEV0,
+@@ -302,26 +302,34 @@ static struct irq_chip ar724x_pci_irq_ch
+       .irq_mask_ack   = ar724x_pci_irq_mask,
+ };
++static int ar724x_pci_irq_map(struct irq_domain *d,
++                            unsigned int irq, irq_hw_number_t hw)
++{
++      struct ar724x_pci_controller *apc = d->host_data;
++
++      irq_set_chip_and_handler(irq, &ar724x_pci_irq_chip, handle_level_irq);
++      irq_set_chip_data(irq, apc);
++
++      return 0;
++}
++
++static const struct irq_domain_ops ar724x_pci_domain_ops = {
++      .xlate = irq_domain_xlate_onecell,
++      .map = ar724x_pci_irq_map,
++};
++
+ static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
+                               int id)
+ {
+       void __iomem *base;
+-      int i;
+       base = apc->ctrl_base;
+       __raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
+       __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
+-      apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT);
+-
+-      for (i = apc->irq_base;
+-           i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) {
+-              irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
+-                                       handle_level_irq);
+-              irq_set_chip_data(i, apc);
+-      }
+-
++      apc->domain = irq_domain_add_linear(apc->np, 2,
++                                          &ar724x_pci_domain_ops, apc);
+       irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler,
+                                        apc);
+ }
+@@ -391,29 +399,11 @@ static int ar724x_pci_probe(struct platf
+       if (apc->irq < 0)
+               return -EINVAL;
+-      res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base");
+-      if (!res)
+-              return -EINVAL;
+-
+-      apc->io_res.parent = res;
+-      apc->io_res.name = "PCI IO space";
+-      apc->io_res.start = res->start;
+-      apc->io_res.end = res->end;
+-      apc->io_res.flags = IORESOURCE_IO;
+-
+-      res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base");
+-      if (!res)
+-              return -EINVAL;
+-
+-      apc->mem_res.parent = res;
+-      apc->mem_res.name = "PCI memory space";
+-      apc->mem_res.start = res->start;
+-      apc->mem_res.end = res->end;
+-      apc->mem_res.flags = IORESOURCE_MEM;
+-
++      apc->np = pdev->dev.of_node;
+       apc->pci_controller.pci_ops = &ar724x_pci_ops;
+       apc->pci_controller.io_resource = &apc->io_res;
+       apc->pci_controller.mem_resource = &apc->mem_res;
++      pci_load_of_ranges(&apc->pci_controller, pdev->dev.of_node);
+       /*
+        * Do the full PCIE Root Complex Initialization Sequence if the PCIe
+@@ -435,10 +425,16 @@ static int ar724x_pci_probe(struct platf
+       return 0;
+ }
++static const struct of_device_id ar724x_pci_ids[] = {
++      { .compatible = "qcom,ar7240-pci" },
++      {},
++};
++
+ static struct platform_driver ar724x_pci_driver = {
+       .probe = ar724x_pci_probe,
+       .driver = {
+               .name = "ar724x-pci",
++              .of_match_table = of_match_ptr(ar724x_pci_ids),
+       },
+ };
diff --git a/target/linux/ath79/patches-5.4/0032-MIPS-ath79-sanitize-symbols.patch b/target/linux/ath79/patches-5.4/0032-MIPS-ath79-sanitize-symbols.patch
new file mode 100644 (file)
index 0000000..382c5e6
--- /dev/null
@@ -0,0 +1,93 @@
+From 3fc8585cf76022dba7496627074d42af88c30718 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:16:55 +0200
+Subject: [PATCH 32/33] MIPS: ath79: sanitize symbols
+
+We no longer need to select which SoCs are supported as the whole arch
+code is always built. So lets drop all the SoC symbols
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/Kconfig       |  2 ++
+ arch/mips/ath79/Kconfig | 44 +++++---------------------------------------
+ arch/mips/pci/Makefile  |  2 +-
+ 3 files changed, 8 insertions(+), 40 deletions(-)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -216,6 +216,8 @@ config ATH79
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_MIPS16
+       select SYS_SUPPORTS_ZBOOT_UART_PROM
++      select HAVE_PCI
++      select USB_ARCH_HAS_EHCI
+       select USE_OF
+       select USB_EHCI_ROOT_HUB_TT if USB_EHCI_HCD_PLATFORM
+       help
+--- a/arch/mips/ath79/Kconfig
++++ b/arch/mips/ath79/Kconfig
+@@ -1,48 +1,14 @@
+ # SPDX-License-Identifier: GPL-2.0
+ if ATH79
+-config SOC_AR71XX
+-      select HAVE_PCI
+-      def_bool n
+-
+-config SOC_AR724X
+-      select HAVE_PCI
+-      select PCI_AR724X if PCI
+-      def_bool n
+-
+-config SOC_AR913X
+-      def_bool n
+-
+-config SOC_AR933X
+-      def_bool n
+-
+-config SOC_AR934X
+-      select HAVE_PCI
+-      select PCI_AR724X if PCI
+-      def_bool n
+-
+-config SOC_QCA955X
+-      select HAVE_PCI
+-      select PCI_AR724X if PCI
++config PCI_AR71XX
++      bool "PCI support for AR7100 type SoCs"
++      depends on PCI
+       def_bool n
+ config PCI_AR724X
+-      def_bool n
+-
+-config ATH79_DEV_GPIO_BUTTONS
+-      def_bool n
+-
+-config ATH79_DEV_LEDS_GPIO
+-      def_bool n
+-
+-config ATH79_DEV_SPI
+-      def_bool n
+-
+-config ATH79_DEV_USB
+-      def_bool n
+-
+-config ATH79_DEV_WMAC
+-      depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA955X)
++      bool "PCI support for AR724x type SoCs"
++      depends on PCI
+       def_bool n
+ endif
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -23,7 +23,7 @@ obj-$(CONFIG_BCM63XX)                += pci-bcm63xx.o
+                                       ops-bcm63xx.o
+ obj-$(CONFIG_MIPS_ALCHEMY)    += pci-alchemy.o
+ obj-$(CONFIG_PCI_AR2315)      += pci-ar2315.o
+-obj-$(CONFIG_SOC_AR71XX)      += pci-ar71xx.o
++obj-$(CONFIG_PCI_AR71XX)      += pci-ar71xx.o
+ obj-$(CONFIG_PCI_AR724X)      += pci-ar724x.o
+ obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
+ obj-$(CONFIG_PCI_XTALK_BRIDGE)        += pci-xtalk-bridge.o
diff --git a/target/linux/ath79/patches-5.4/0033-spi-ath79-drop-pdata-support.patch b/target/linux/ath79/patches-5.4/0033-spi-ath79-drop-pdata-support.patch
new file mode 100644 (file)
index 0000000..8fd99bd
--- /dev/null
@@ -0,0 +1,71 @@
+From c4e197bbcecc7233aa9e553e7047fa50e4e1fe77 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 25 Jun 2018 15:52:34 +0200
+Subject: [PATCH 33/33] spi: ath79: drop pdata support
+
+The target is being converted to pure OF. We can therefore drop all of the
+platform data code from the driver.
+
+Cc: linux-spi@vger.kernel.org
+Acked-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ include/linux/platform_data/spi-ath79.h | 16 -------------------
+ drivers/spi/spi-ath79.c                               |  8 --------
+ 2 files changed, 27 deletions(-)
+ delete mode 100644 arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
+
+--- a/include/linux/platform_data/spi-ath79.h
++++ /dev/null
+@@ -1,16 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-only */
+-/*
+- *  Platform data definition for Atheros AR71XX/AR724X/AR913X SPI controller
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- */
+-
+-#ifndef _ATH79_SPI_PLATFORM_H
+-#define _ATH79_SPI_PLATFORM_H
+-
+-struct ath79_spi_platform_data {
+-      unsigned        bus_num;
+-      unsigned        num_chipselect;
+-};
+-
+-#endif /* _ATH79_SPI_PLATFORM_H */
+--- a/drivers/spi/spi-ath79.c
++++ b/drivers/spi/spi-ath79.c
+@@ -19,7 +19,6 @@
+ #include <linux/bitops.h>
+ #include <linux/clk.h>
+ #include <linux/err.h>
+-#include <linux/platform_data/spi-ath79.h>
+ #define DRV_NAME      "ath79-spi"
+@@ -138,7 +137,6 @@ static int ath79_spi_probe(struct platfo
+ {
+       struct spi_master *master;
+       struct ath79_spi *sp;
+-      struct ath79_spi_platform_data *pdata;
+       unsigned long rate;
+       int ret;
+@@ -152,16 +150,10 @@ static int ath79_spi_probe(struct platfo
+       master->dev.of_node = pdev->dev.of_node;
+       platform_set_drvdata(pdev, sp);
+-      pdata = dev_get_platdata(&pdev->dev);
+-
+       master->use_gpio_descriptors = true;
+       master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
+       master->setup = spi_bitbang_setup;
+       master->cleanup = spi_bitbang_cleanup;
+-      if (pdata) {
+-              master->bus_num = pdata->bus_num;
+-              master->num_chipselect = pdata->num_chipselect;
+-      }
+       sp->bitbang.master = master;
+       sp->bitbang.chipselect = ath79_spi_chipselect;
diff --git a/target/linux/ath79/patches-5.4/0034-MIPS-ath79-ath9k-exports.patch b/target/linux/ath79/patches-5.4/0034-MIPS-ath79-ath9k-exports.patch
new file mode 100644 (file)
index 0000000..71acc22
--- /dev/null
@@ -0,0 +1,27 @@
+--- a/arch/mips/ath79/common.c
++++ b/arch/mips/ath79/common.c
+@@ -31,11 +31,13 @@ EXPORT_SYMBOL_GPL(ath79_ddr_freq);
+ enum ath79_soc_type ath79_soc;
+ unsigned int ath79_soc_rev;
++EXPORT_SYMBOL_GPL(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;
++EXPORT_SYMBOL_GPL(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/ath79.h
++++ b/arch/mips/include/asm/mach-ath79/ath79.h
+@@ -149,6 +149,7 @@ void ath79_ddr_wb_flush(unsigned int reg
+ void ath79_ddr_set_pci_windows(void);
+ extern void __iomem *ath79_pll_base;
++extern void __iomem *ath79_ddr_base;
+ extern void __iomem *ath79_reset_base;
+ static inline void ath79_pll_wr(unsigned reg, u32 val)
diff --git a/target/linux/ath79/patches-5.4/0036-GPIO-add-named-gpio-exports.patch b/target/linux/ath79/patches-5.4/0036-GPIO-add-named-gpio-exports.patch
new file mode 100644 (file)
index 0000000..c07d3d3
--- /dev/null
@@ -0,0 +1,165 @@
+From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 12 Aug 2014 20:49:27 +0200
+Subject: [PATCH 24/53] GPIO: add named gpio exports
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/gpio/gpiolib-of.c     |   68 +++++++++++++++++++++++++++++++++++++++++
+ drivers/gpio/gpiolib-sysfs.c  |   10 +++++-
+ include/asm-generic/gpio.h    |    6 ++++
+ include/linux/gpio/consumer.h |    8 +++++
+ 4 files changed, 91 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpiolib-of.c
++++ b/drivers/gpio/gpiolib-of.c
+@@ -19,6 +19,8 @@
+ #include <linux/pinctrl/pinctrl.h>
+ #include <linux/slab.h>
+ #include <linux/gpio/machine.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
+ #include "gpiolib.h"
+ #include "gpiolib-of.h"
+@@ -895,3 +897,68 @@ void of_gpiochip_remove(struct gpio_chip
+       gpiochip_remove_pin_ranges(chip);
+       of_node_put(chip->of_node);
+ }
++
++static struct of_device_id gpio_export_ids[] = {
++      { .compatible = "gpio-export" },
++      { /* sentinel */ }
++};
++
++static int of_gpio_export_probe(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node;
++      struct device_node *cnp;
++      u32 val;
++      int nb = 0;
++
++      for_each_child_of_node(np, cnp) {
++              const char *name = NULL;
++              int gpio;
++              bool dmc;
++              int max_gpio = 1;
++              int i;
++
++              of_property_read_string(cnp, "gpio-export,name", &name);
++
++              if (!name)
++                      max_gpio = of_gpio_count(cnp);
++
++              for (i = 0; i < max_gpio; i++) {
++                      unsigned flags = 0;
++                      enum of_gpio_flags of_flags;
++
++                      gpio = of_get_gpio_flags(cnp, i, &of_flags);
++                      if (!gpio_is_valid(gpio))
++                              return gpio;
++
++                      if (of_flags == OF_GPIO_ACTIVE_LOW)
++                              flags |= GPIOF_ACTIVE_LOW;
++
++                      if (!of_property_read_u32(cnp, "gpio-export,output", &val))
++                              flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
++                      else
++                              flags |= GPIOF_IN;
++
++                      if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
++                              continue;
++
++                      dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
++                      gpio_export_with_name(gpio, dmc, name);
++                      nb++;
++              }
++      }
++
++      dev_info(&pdev->dev, "%d gpio(s) exported\n", nb);
++
++      return 0;
++}
++
++static struct platform_driver gpio_export_driver = {
++      .driver         = {
++              .name           = "gpio-export",
++              .owner  = THIS_MODULE,
++              .of_match_table = of_match_ptr(gpio_export_ids),
++      },
++      .probe          = of_gpio_export_probe,
++};
++
++module_platform_driver(gpio_export_driver);
+--- a/drivers/gpio/gpiolib-sysfs.c
++++ b/drivers/gpio/gpiolib-sysfs.c
+@@ -563,7 +563,7 @@ static struct class gpio_class = {
+  *
+  * Returns zero on success, else an error.
+  */
+-int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name)
+ {
+       struct gpio_chip        *chip;
+       struct gpio_device      *gdev;
+@@ -625,6 +625,8 @@ int gpiod_export(struct gpio_desc *desc,
+       offset = gpio_chip_hwgpio(desc);
+       if (chip->names && chip->names[offset])
+               ioname = chip->names[offset];
++      if (name)
++              ioname = name;
+       dev = device_create_with_groups(&gpio_class, &gdev->dev,
+                                       MKDEV(0, 0), data, gpio_groups,
+@@ -646,6 +648,12 @@ err_unlock:
+       gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+       return status;
+ }
++EXPORT_SYMBOL_GPL(__gpiod_export);
++
++int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
++{
++      return __gpiod_export(desc, direction_may_change, NULL);
++}
+ EXPORT_SYMBOL_GPL(gpiod_export);
+ static int match_export(struct device *dev, const void *desc)
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g
+       return gpiod_export(gpio_to_desc(gpio), direction_may_change);
+ }
++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name)
++{
++      return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name);
++}
++
+ static inline int gpio_export_link(struct device *dev, const char *name,
+                                  unsigned gpio)
+ {
+--- a/include/linux/gpio/consumer.h
++++ b/include/linux/gpio/consumer.h
+@@ -661,6 +661,7 @@ static inline void devm_acpi_dev_remove_
+ #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
+ int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
+ int gpiod_export_link(struct device *dev, const char *name,
+                     struct gpio_desc *desc);
+@@ -668,6 +669,13 @@ void gpiod_unexport(struct gpio_desc *de
+ #else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
++static inline int _gpiod_export(struct gpio_desc *desc,
++                             bool direction_may_change,
++                             const char *name)
++{
++      return -ENOSYS;
++}
++
+ static inline int gpiod_export(struct gpio_desc *desc,
+                              bool direction_may_change)
+ {
diff --git a/target/linux/ath79/patches-5.4/0036-MIPS-ath79-remove-irq-code-from-pci.patch b/target/linux/ath79/patches-5.4/0036-MIPS-ath79-remove-irq-code-from-pci.patch
new file mode 100644 (file)
index 0000000..80fcd0a
--- /dev/null
@@ -0,0 +1,139 @@
+--- a/arch/mips/pci/pci-ar71xx.c
++++ b/arch/mips/pci/pci-ar71xx.c
+@@ -51,11 +51,9 @@
+ struct ar71xx_pci_controller {
+       struct device_node *np;
+       void __iomem *cfg_base;
+-      int irq;
+       struct pci_controller pci_ctrl;
+       struct resource io_res;
+       struct resource mem_res;
+-      struct irq_domain *domain;
+ };
+ /* Byte lane enable bits */
+@@ -227,104 +225,6 @@ static struct pci_ops ar71xx_pci_ops = {
+       .write  = ar71xx_pci_write_config,
+ };
+-static void ar71xx_pci_irq_handler(struct irq_desc *desc)
+-{
+-      void __iomem *base = ath79_reset_base;
+-      struct irq_chip *chip = irq_desc_get_chip(desc);
+-      struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc);
+-      u32 pending;
+-
+-      chained_irq_enter(chip, desc);
+-      pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) &
+-                __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-      if (pending & AR71XX_PCI_INT_DEV0)
+-              generic_handle_irq(irq_linear_revmap(apc->domain, 1));
+-
+-      else if (pending & AR71XX_PCI_INT_DEV1)
+-              generic_handle_irq(irq_linear_revmap(apc->domain, 2));
+-
+-      else if (pending & AR71XX_PCI_INT_DEV2)
+-              generic_handle_irq(irq_linear_revmap(apc->domain, 3));
+-
+-      else if (pending & AR71XX_PCI_INT_CORE)
+-              generic_handle_irq(irq_linear_revmap(apc->domain, 4));
+-
+-      else
+-              spurious_interrupt();
+-      chained_irq_exit(chip, desc);
+-}
+-
+-static void ar71xx_pci_irq_unmask(struct irq_data *d)
+-{
+-      struct ar71xx_pci_controller *apc;
+-      unsigned int irq;
+-      void __iomem *base = ath79_reset_base;
+-      u32 t;
+-
+-      apc = irq_data_get_irq_chip_data(d);
+-      irq = irq_linear_revmap(apc->domain, d->irq);
+-
+-      t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-      __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-      /* flush write */
+-      __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-}
+-
+-static void ar71xx_pci_irq_mask(struct irq_data *d)
+-{
+-      struct ar71xx_pci_controller *apc;
+-      unsigned int irq;
+-      void __iomem *base = ath79_reset_base;
+-      u32 t;
+-
+-      apc = irq_data_get_irq_chip_data(d);
+-      irq = irq_linear_revmap(apc->domain, d->irq);
+-
+-      t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-      __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-      /* flush write */
+-      __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-}
+-
+-static struct irq_chip ar71xx_pci_irq_chip = {
+-      .name           = "AR71XX PCI",
+-      .irq_mask       = ar71xx_pci_irq_mask,
+-      .irq_unmask     = ar71xx_pci_irq_unmask,
+-      .irq_mask_ack   = ar71xx_pci_irq_mask,
+-};
+-
+-static int ar71xx_pci_irq_map(struct irq_domain *d,
+-                            unsigned int irq, irq_hw_number_t hw)
+-{
+-      struct ar71xx_pci_controller *apc = d->host_data;
+-
+-      irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq);
+-      irq_set_chip_data(irq, apc);
+-
+-      return 0;
+-}
+-
+-static const struct irq_domain_ops ar71xx_pci_domain_ops = {
+-      .xlate = irq_domain_xlate_onecell,
+-      .map = ar71xx_pci_irq_map,
+-};
+-
+-static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
+-{
+-      void __iomem *base = ath79_reset_base;
+-
+-      __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-      __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS);
+-
+-      apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT,
+-                                          &ar71xx_pci_domain_ops, apc);
+-      irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler,
+-                                       apc);
+-}
+-
+ static void ar71xx_pci_reset(void)
+ {
+       ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
+@@ -358,10 +258,6 @@ static int ar71xx_pci_probe(struct platf
+       if (IS_ERR(apc->cfg_base))
+               return PTR_ERR(apc->cfg_base);
+-      apc->irq = platform_get_irq(pdev, 0);
+-      if (apc->irq < 0)
+-              return -EINVAL;
+-
+       ar71xx_pci_reset();
+       /* setup COMMAND register */
+@@ -372,8 +268,6 @@ static int ar71xx_pci_probe(struct platf
+       /* clear bus errors */
+       ar71xx_pci_check_error(apc, 1);
+-      ar71xx_pci_irq_init(apc);
+-
+       apc->np = pdev->dev.of_node;
+       apc->pci_ctrl.pci_ops = &ar71xx_pci_ops;
+       apc->pci_ctrl.mem_resource = &apc->mem_res;
diff --git a/target/linux/ath79/patches-5.4/0037-missing-registers.patch b/target/linux/ath79/patches-5.4/0037-missing-registers.patch
new file mode 100644 (file)
index 0000000..9067e4c
--- /dev/null
@@ -0,0 +1,21 @@
+commit f3ffac90bc7266b7d917616f3233f58e8c08a196
+Author: Christian Lamparter <chunkeey@gmail.com>
+Date:   Fri Aug 10 23:24:47 2018 +0200
+
+    ath79: gmac: add parsers for rxd(v)- and tx(d|en)-delay for AR9344
+
+    Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -1226,6 +1226,10 @@
+ #define AR934X_ETH_CFG_RDV_DELAY        BIT(16)
+ #define AR934X_ETH_CFG_RDV_DELAY_MASK   0x3
+ #define AR934X_ETH_CFG_RDV_DELAY_SHIFT  16
++#define AR934X_ETH_CFG_TXD_DELAY_MASK   0x3
++#define AR934X_ETH_CFG_TXD_DELAY_SHIFT  18
++#define AR934X_ETH_CFG_TXE_DELAY_MASK   0x3
++#define AR934X_ETH_CFG_TXE_DELAY_SHIFT  20
+ /*
+  * QCA953X GMAC Interface
diff --git a/target/linux/ath79/patches-5.4/0038-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch b/target/linux/ath79/patches-5.4/0038-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch
new file mode 100644 (file)
index 0000000..bc09062
--- /dev/null
@@ -0,0 +1,90 @@
+From 60efe35257b063ce584968f9f80b437030ce6ba6 Mon Sep 17 00:00:00 2001
+From: David Bauer <mail@david-bauer.net>
+Date: Mon, 18 Mar 2019 00:54:06 +0100
+Subject: [PATCH] MIPS: ath79: add missing QCA955x GMAC registers
+
+This adds missing GMAC register definitions for the Qualcomm Atheros
+QCA955X series MIPS SoCs.
+
+They originate from the platforms U-Boot code and the AVM FRITZ!WLAN
+Repeater 450E's GPL tarball.
+
+Signed-off-by: David Bauer <mail@david-bauer.net>
+---
+ .../mips/include/asm/mach-ath79/ar71xx_regs.h | 54 +++++++++++++++++++
+ 1 file changed, 54 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -1246,7 +1246,12 @@
+  */
+ #define QCA955X_GMAC_REG_ETH_CFG      0x00
++#define QCA955X_GMAC_REG_SGMII_RESET  0x14
+ #define QCA955X_GMAC_REG_SGMII_SERDES 0x18
++#define QCA955X_GMAC_REG_MR_AN_CONTROL        0x1c
++#define QCA955X_GMAC_REG_MR_AN_STATUS 0x20
++#define QCA955X_GMAC_REG_SGMII_CONFIG 0x34
++#define QCA955X_GMAC_REG_SGMII_DEBUG  0x58
+ #define QCA955X_ETH_CFG_RGMII_EN      BIT(0)
+ #define QCA955X_ETH_CFG_MII_GE0               BIT(1)
+@@ -1268,9 +1273,58 @@
+ #define QCA955X_ETH_CFG_TXE_DELAY_MASK        0x3
+ #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT       20
++#define QCA955X_SGMII_RESET_RX_CLK_N_RESET    0
++#define QCA955X_SGMII_RESET_RX_CLK_N          BIT(0)
++#define QCA955X_SGMII_RESET_TX_CLK_N          BIT(1)
++#define QCA955X_SGMII_RESET_RX_125M_N         BIT(2)
++#define QCA955X_SGMII_RESET_TX_125M_N         BIT(3)
++#define QCA955X_SGMII_RESET_HW_RX_125M_N      BIT(4)
++
+ #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS       BIT(15)
+ #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23
+ #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf
++
++#define QCA955X_MR_AN_CONTROL_SPEED_SEL1      BIT(6)
++#define QCA955X_MR_AN_CONTROL_DUPLEX_MODE     BIT(8)
++#define QCA955X_MR_AN_CONTROL_RESTART_AN      BIT(9)
++#define QCA955X_MR_AN_CONTROL_POWER_DOWN      BIT(11)
++#define QCA955X_MR_AN_CONTROL_AN_ENABLE               BIT(12)
++#define QCA955X_MR_AN_CONTROL_SPEED_SEL0      BIT(13)
++#define QCA955X_MR_AN_CONTROL_LOOPBACK                BIT(14)
++#define QCA955X_MR_AN_CONTROL_PHY_RESET               BIT(15)
++
++#define QCA955X_MR_AN_STATUS_EXT_CAP          BIT(0)
++#define QCA955X_MR_AN_STATUS_LINK_UP          BIT(2)
++#define QCA955X_MR_AN_STATUS_AN_ABILITY               BIT(3)
++#define QCA955X_MR_AN_STATUS_REMOTE_FAULT     BIT(4)
++#define QCA955X_MR_AN_STATUS_AN_COMPLETE      BIT(5)
++#define QCA955X_MR_AN_STATUS_NO_PREAMBLE      BIT(6)
++#define QCA955X_MR_AN_STATUS_BASE_PAGE                BIT(7)
++
++#define QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT          0
++#define QCA955X_SGMII_CONFIG_MODE_CTRL_MASK           0x7
++#define QCA955X_SGMII_CONFIG_ENABLE_SGMII_TX_PAUSE    BIT(3)
++#define QCA955X_SGMII_CONFIG_MR_REG4_CHANGED          BIT(4)
++#define QCA955X_SGMII_CONFIG_FORCE_SPEED              BIT(5)
++#define QCA955X_SGMII_CONFIG_SPEED_SHIFT              6
++#define QCA955X_SGMII_CONFIG_SPEED_MASK                       0xc0
++#define QCA955X_SGMII_CONFIG_REMOTE_PHY_LOOPBACK      BIT(8)
++#define QCA955X_SGMII_CONFIG_NEXT_PAGE_LOADED         BIT(9)
++#define QCA955X_SGMII_CONFIG_MDIO_ENABLE              BIT(10)
++#define QCA955X_SGMII_CONFIG_MDIO_PULSE                       BIT(11)
++#define QCA955X_SGMII_CONFIG_MDIO_COMPLETE            BIT(12)
++#define QCA955X_SGMII_CONFIG_PRBS_ENABLE              BIT(13)
++#define QCA955X_SGMII_CONFIG_BERT_ENABLE              BIT(14)
++
++#define QCA955X_SGMII_DEBUG_TX_STATE_MASK     0xff
++#define QCA955X_SGMII_DEBUG_TX_STATE_SHIFT    0
++#define QCA955X_SGMII_DEBUG_RX_STATE_MASK     0xff00
++#define QCA955X_SGMII_DEBUG_RX_STATE_SHIFT    8
++#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_MASK        0xff0000
++#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_SHIFT       16
++#define QCA955X_SGMII_DEBUG_ARB_STATE_MASK    0xf000000
++#define QCA955X_SGMII_DEBUG_ARB_STATE_SHIFT   24
++
+ /*
+  * QCA956X GMAC Interface
+  */
diff --git a/target/linux/ath79/patches-5.4/0039-MIPS-ath79-export-UART1-reference-clock.patch b/target/linux/ath79/patches-5.4/0039-MIPS-ath79-export-UART1-reference-clock.patch
new file mode 100644 (file)
index 0000000..edf888c
--- /dev/null
@@ -0,0 +1,52 @@
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -40,6 +40,7 @@ static const char * const clk_names[ATH7
+       [ATH79_CLK_AHB] = "ahb",
+       [ATH79_CLK_REF] = "ref",
+       [ATH79_CLK_MDIO] = "mdio",
++      [ATH79_CLK_UART1] = "uart1",
+ };
+ static const char * __init ath79_clk_name(int type)
+@@ -344,6 +345,9 @@ static void __init ar934x_clocks_init(vo
+       if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL)
+               ath79_set_clk(ATH79_CLK_MDIO, 100 * 1000 * 1000);
++      if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL)
++              ath79_set_clk(ATH79_CLK_UART1, 100 * 1000 * 1000);
++
+       iounmap(dpll_base);
+ }
+@@ -649,6 +653,9 @@ static void __init ath79_clocks_init_dt(
+       if (!clks[ATH79_CLK_MDIO])
+               clks[ATH79_CLK_MDIO] = clks[ATH79_CLK_REF];
++      if (!clks[ATH79_CLK_UART1])
++              clks[ATH79_CLK_UART1] = clks[ATH79_CLK_REF];
++
+       if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) {
+               pr_err("%pOF: could not register clk provider\n", np);
+               goto err_iounmap;
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -348,6 +348,7 @@
+ #define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL        BIT(24)
+ #define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL  BIT(6)
++#define AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL BIT(7)
+ #define QCA953X_PLL_CPU_CONFIG_REG            0x00
+ #define QCA953X_PLL_DDR_CONFIG_REG            0x04
+--- a/include/dt-bindings/clock/ath79-clk.h
++++ b/include/dt-bindings/clock/ath79-clk.h
+@@ -11,7 +11,8 @@
+ #define ATH79_CLK_AHB         2
+ #define ATH79_CLK_REF         3
+ #define ATH79_CLK_MDIO                4
++#define ATH79_CLK_UART1               5
+-#define ATH79_CLK_END         5
++#define ATH79_CLK_END         6
+ #endif /* __DT_BINDINGS_ATH79_CLK_H */
diff --git a/target/linux/ath79/patches-5.4/004-register_gpio_driver_earlier.patch b/target/linux/ath79/patches-5.4/004-register_gpio_driver_earlier.patch
new file mode 100644 (file)
index 0000000..fa4b05f
--- /dev/null
@@ -0,0 +1,18 @@
+HACK: register the GPIO driver earlier to ensure that gpio_request calls
+from mach files succeed.
+
+--- a/drivers/gpio/gpio-ath79.c
++++ b/drivers/gpio/gpio-ath79.c
+@@ -310,7 +310,11 @@ static struct platform_driver ath79_gpio
+       .probe = ath79_gpio_probe,
+ };
+-module_platform_driver(ath79_gpio_driver);
++static int __init ath79_gpio_init(void)
++{
++      return platform_driver_register(&ath79_gpio_driver);
++}
++postcore_initcall(ath79_gpio_init);
+ MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support");
+ MODULE_LICENSE("GPL v2");
diff --git a/target/linux/ath79/patches-5.4/0051-spi-add-driver-for-ar934x-spi-controller.patch b/target/linux/ath79/patches-5.4/0051-spi-add-driver-for-ar934x-spi-controller.patch
new file mode 100644 (file)
index 0000000..e314fa2
--- /dev/null
@@ -0,0 +1,283 @@
+From 7e161c423a232ef7ddf6c11b09ebe471dd5a23cf Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213@gmail.com>
+Date: Wed, 5 Feb 2020 18:25:37 +0800
+Subject: [PATCH v4 1/2] spi: add driver for ar934x spi controller
+
+This patch adds driver for SPI controller found in Qualcomm Atheros
+AR934x/QCA95xx SoCs.
+This controller is a superset of the already supported qca,ar7100-spi.
+Besides the bit-bang mode in spi-ath79.c, this new controller added
+a new "shift register" mode, allowing faster spi operations.
+
+Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
+---
+ drivers/spi/Kconfig      |   7 ++
+ drivers/spi/Makefile     |   1 +
+ drivers/spi/spi-ar934x.c | 235 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 243 insertions(+)
+ create mode 100644 drivers/spi/spi-ar934x.c
+
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -62,6 +62,13 @@ config SPI_ALTERA
+       help
+         This is the driver for the Altera SPI Controller.
++config SPI_AR934X
++      tristate "Qualcomm Atheros AR934X/QCA95XX SPI controller driver"
++      depends on ATH79 || COMPILE_TEST
++      help
++        This enables support for the SPI controller present on the
++        Qualcomm Atheros AR934X/QCA95XX SoCs.
++
+ config SPI_ATH79
+       tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
+       depends on ATH79 || COMPILE_TEST
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_LOOPBACK_TEST)              += spi-
+ # SPI master controller drivers (bus)
+ obj-$(CONFIG_SPI_ALTERA)              += spi-altera.o
++obj-$(CONFIG_SPI_AR934X)              += spi-ar934x.o
+ obj-$(CONFIG_SPI_ARMADA_3700)         += spi-armada-3700.o
+ obj-$(CONFIG_SPI_ATMEL)                       += spi-atmel.o
+ obj-$(CONFIG_SPI_ATMEL_QUADSPI)               += atmel-quadspi.o
+--- /dev/null
++++ b/drivers/spi/spi-ar934x.c
+@@ -0,0 +1,235 @@
++// SPDX-License-Identifier: GPL-2.0
++//
++// SPI controller driver for Qualcomm Atheros AR934x/QCA95xx SoCs
++//
++// Copyright (C) 2020 Chuanhong Guo <gch981213@gmail.com>
++//
++// Based on spi-mt7621.c:
++// Copyright (C) 2011 Sergiy <piratfm@gmail.com>
++// Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
++// Copyright (C) 2014-2015 Felix Fietkau <nbd@nbd.name>
++
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/spi/spi.h>
++
++#define DRIVER_NAME "spi-ar934x"
++
++#define AR934X_SPI_REG_FS             0x00
++#define AR934X_SPI_ENABLE             BIT(0)
++
++#define AR934X_SPI_REG_IOC            0x08
++#define AR934X_SPI_IOC_INITVAL                0x70000
++
++#define AR934X_SPI_REG_CTRL           0x04
++#define AR934X_SPI_CLK_MASK           GENMASK(5, 0)
++
++#define AR934X_SPI_DATAOUT            0x10
++
++#define AR934X_SPI_REG_SHIFT_CTRL     0x14
++#define AR934X_SPI_SHIFT_EN           BIT(31)
++#define AR934X_SPI_SHIFT_CS(n)                BIT(28 + (n))
++#define AR934X_SPI_SHIFT_TERM         26
++#define AR934X_SPI_SHIFT_VAL(cs, term, count)                 \
++      (AR934X_SPI_SHIFT_EN | AR934X_SPI_SHIFT_CS(cs) |        \
++      (term) << AR934X_SPI_SHIFT_TERM | (count))
++
++#define AR934X_SPI_DATAIN 0x18
++
++struct ar934x_spi {
++      struct spi_controller *ctlr;
++      void __iomem *base;
++      struct clk *clk;
++      unsigned int clk_freq;
++};
++
++static inline int ar934x_spi_clk_div(struct ar934x_spi *sp, unsigned int freq)
++{
++      int div = DIV_ROUND_UP(sp->clk_freq, freq * 2) - 1;
++
++      if (div < 0)
++              return 0;
++      else if (div > AR934X_SPI_CLK_MASK)
++              return -EINVAL;
++      else
++              return div;
++}
++
++static int ar934x_spi_setup(struct spi_device *spi)
++{
++      struct ar934x_spi *sp = spi_controller_get_devdata(spi->master);
++
++      if ((spi->max_speed_hz == 0) ||
++          (spi->max_speed_hz > (sp->clk_freq / 2))) {
++              spi->max_speed_hz = sp->clk_freq / 2;
++      } else if (spi->max_speed_hz < (sp->clk_freq / 128)) {
++              dev_err(&spi->dev, "spi clock is too low\n");
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int ar934x_spi_transfer_one_message(struct spi_controller *master,
++                                         struct spi_message *m)
++{
++      struct ar934x_spi *sp = spi_controller_get_devdata(master);
++      struct spi_transfer *t = NULL;
++      struct spi_device *spi = m->spi;
++      unsigned long trx_done, trx_cur;
++      int stat = 0;
++      u8 term = 0;
++      int div, i;
++      u32 reg;
++      const u8 *tx_buf;
++      u8 *buf;
++
++      m->actual_length = 0;
++      list_for_each_entry(t, &m->transfers, transfer_list) {
++              if (t->speed_hz)
++                      div = ar934x_spi_clk_div(sp, t->speed_hz);
++              else
++                      div = ar934x_spi_clk_div(sp, spi->max_speed_hz);
++              if (div < 0) {
++                      stat = -EIO;
++                      goto msg_done;
++              }
++
++              reg = ioread32(sp->base + AR934X_SPI_REG_CTRL);
++              reg &= ~AR934X_SPI_CLK_MASK;
++              reg |= div;
++              iowrite32(reg, sp->base + AR934X_SPI_REG_CTRL);
++              iowrite32(0, sp->base + AR934X_SPI_DATAOUT);
++
++              for (trx_done = 0; trx_done < t->len; trx_done += 4) {
++                      trx_cur = t->len - trx_done;
++                      if (trx_cur > 4)
++                              trx_cur = 4;
++                      else if (list_is_last(&t->transfer_list, &m->transfers))
++                              term = 1;
++
++                      if (t->tx_buf) {
++                              tx_buf = t->tx_buf + trx_done;
++                              reg = tx_buf[0];
++                              for (i = 1; i < trx_cur; i++)
++                                      reg = reg << 8 | tx_buf[i];
++                              iowrite32(reg, sp->base + AR934X_SPI_DATAOUT);
++                      }
++
++                      reg = AR934X_SPI_SHIFT_VAL(spi->chip_select, term,
++                                                 trx_cur * 8);
++                      iowrite32(reg, sp->base + AR934X_SPI_REG_SHIFT_CTRL);
++                      stat = readl_poll_timeout(
++                              sp->base + AR934X_SPI_REG_SHIFT_CTRL, reg,
++                              !(reg & AR934X_SPI_SHIFT_EN), 0, 5);
++                      if (stat < 0)
++                              goto msg_done;
++
++                      if (t->rx_buf) {
++                              reg = ioread32(sp->base + AR934X_SPI_DATAIN);
++                              buf = t->rx_buf + trx_done;
++                              for (i = 0; i < trx_cur; i++) {
++                                      buf[trx_cur - i - 1] = reg & 0xff;
++                                      reg >>= 8;
++                              }
++                      }
++              }
++              m->actual_length += t->len;
++      }
++
++msg_done:
++      m->status = stat;
++      spi_finalize_current_message(master);
++
++      return 0;
++}
++
++static const struct of_device_id ar934x_spi_match[] = {
++      { .compatible = "qca,ar934x-spi" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, ar934x_spi_match);
++
++static int ar934x_spi_probe(struct platform_device *pdev)
++{
++      struct spi_controller *ctlr;
++      struct ar934x_spi *sp;
++      void __iomem *base;
++      struct clk *clk;
++      int ret;
++
++      base = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(base))
++              return PTR_ERR(base);
++
++      clk = devm_clk_get(&pdev->dev, NULL);
++      if (IS_ERR(clk)) {
++              dev_err(&pdev->dev, "failed to get clock\n");
++              return PTR_ERR(clk);
++      }
++
++      ret = clk_prepare_enable(clk);
++      if (ret)
++              return ret;
++
++      ctlr = spi_alloc_master(&pdev->dev, sizeof(*sp));
++      if (!ctlr) {
++              dev_info(&pdev->dev, "failed to allocate spi controller\n");
++              return -ENOMEM;
++      }
++
++      /* disable flash mapping and expose spi controller registers */
++      iowrite32(AR934X_SPI_ENABLE, base + AR934X_SPI_REG_FS);
++      /* restore pins to default state: CSn=1 DO=CLK=0 */
++      iowrite32(AR934X_SPI_IOC_INITVAL, base + AR934X_SPI_REG_IOC);
++
++      ctlr->mode_bits = SPI_LSB_FIRST;
++      ctlr->setup = ar934x_spi_setup;
++      ctlr->transfer_one_message = ar934x_spi_transfer_one_message;
++      ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
++      ctlr->dev.of_node = pdev->dev.of_node;
++      ctlr->num_chipselect = 3;
++
++      dev_set_drvdata(&pdev->dev, ctlr);
++
++      sp = spi_controller_get_devdata(ctlr);
++      sp->base = base;
++      sp->clk = clk;
++      sp->clk_freq = clk_get_rate(clk);
++      sp->ctlr = ctlr;
++
++      return devm_spi_register_controller(&pdev->dev, ctlr);
++}
++
++static int ar934x_spi_remove(struct platform_device *pdev)
++{
++      struct spi_controller *ctlr;
++      struct ar934x_spi *sp;
++
++      ctlr = dev_get_drvdata(&pdev->dev);
++      sp = spi_controller_get_devdata(ctlr);
++
++      clk_disable_unprepare(sp->clk);
++
++      return 0;
++}
++
++static struct platform_driver ar934x_spi_driver = {
++      .driver = {
++              .name = DRIVER_NAME,
++              .of_match_table = ar934x_spi_match,
++      },
++      .probe = ar934x_spi_probe,
++      .remove = ar934x_spi_remove,
++};
++
++module_platform_driver(ar934x_spi_driver);
++
++MODULE_DESCRIPTION("SPI controller driver for Qualcomm Atheros AR934x/QCA95xx");
++MODULE_AUTHOR("Chuanhong Guo <gch981213@gmail.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/target/linux/ath79/patches-5.4/0060-serial-ar933x_uart-set-UART_CS_-RX-TX-_READY_ORIDE.patch b/target/linux/ath79/patches-5.4/0060-serial-ar933x_uart-set-UART_CS_-RX-TX-_READY_ORIDE.patch
new file mode 100644 (file)
index 0000000..485aadc
--- /dev/null
@@ -0,0 +1,64 @@
+From patchwork Fri Feb  7 09:53:35 2020
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
+X-Patchwork-Id: 1190470
+Date: Fri, 7 Feb 2020 11:53:35 +0200
+From: Daniel Golle <daniel@makrotopia.org>
+To: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
+        Jiri Slaby <jslaby@suse.com>,
+        Chuanhong Guo <gch981213@gmail.com>,
+        Eitan Cohen <eitan@neot-semadar.com>,
+        Ori Gofen <origofen@gmail.com>
+Subject: [PATCH] serial: ar933x_uart: set UART_CS_{RX,TX}_READY_ORIDE
+Message-ID: <20200207095335.GA179836@makrotopia.org>
+MIME-Version: 1.0
+Content-Disposition: inline
+Sender: linux-kernel-owner@vger.kernel.org
+Precedence: bulk
+List-ID: <linux-kernel.vger.kernel.org>
+X-Mailing-List: linux-kernel@vger.kernel.org
+
+On AR934x this UART is usually not initialized by the bootloader
+as it is only used as a secondary serial port while the primary
+UART is a newly introduced NS16550-compatible.
+In order to make use of the ar933x-uart on AR934x without RTS/CTS
+hardware flow control, one needs to set the
+UART_CS_{RX,TX}_READY_ORIDE bits as other than on AR933x where this
+UART is used as primary/console, the bootloader on AR934x typically
+doesn't set those bits.
+Setting them explicitely on AR933x should not do any harm, so just
+set them unconditionally.
+
+Tested-by: Chuanhong Guo <gch981213@gmail.com>
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+ drivers/tty/serial/ar933x_uart.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/tty/serial/ar933x_uart.c
++++ b/drivers/tty/serial/ar933x_uart.c
+@@ -286,6 +286,10 @@ static void ar933x_uart_set_termios(stru
+       ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+                           AR933X_UART_CS_HOST_INT_EN);
++      /* enable RX and TX ready overide */
++      ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
++              AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
++
+       /* reenable the UART */
+       ar933x_uart_rmw(up, AR933X_UART_CS_REG,
+                       AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
+@@ -418,6 +422,10 @@ static int ar933x_uart_startup(struct ua
+       ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+                           AR933X_UART_CS_HOST_INT_EN);
++      /* enable RX and TX ready overide */
++      ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
++              AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
++
+       /* Enable RX interrupts */
+       up->ier = AR933X_UART_INT_RX_VALID;
+       ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
diff --git a/target/linux/ath79/patches-5.4/404-mtd-cybertan-trx-parser.patch b/target/linux/ath79/patches-5.4/404-mtd-cybertan-trx-parser.patch
new file mode 100644 (file)
index 0000000..c26ef60
--- /dev/null
@@ -0,0 +1,24 @@
+--- a/drivers/mtd/parsers/Makefile
++++ b/drivers/mtd/parsers/Makefile
+@@ -1,3 +1,4 @@
++obj-$(CONFIG_MTD_PARSER_CYBERTAN)     += parser_cybertan.o
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_MTD_AR7_PARTS)           += ar7part.o
+ obj-$(CONFIG_MTD_BCM47XX_PARTS)               += bcm47xxpart.o
+--- a/drivers/mtd/parsers/Kconfig
++++ b/drivers/mtd/parsers/Kconfig
+@@ -94,6 +94,14 @@ config MTD_AFS_PARTS
+         for your particular device. It won't happen automatically. The
+         'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
++config MTD_PARSER_CYBERTAN
++      tristate "Parser for Cybertan format partitions"
++      depends on MTD && (ATH79 || COMPILE_TEST)
++      help
++        Cybertan has a proprietory header than encompasses a Broadcom trx
++        header. This driver will parse the header and take care of the
++        special offsets that result in the extra headers.
++
+ config MTD_PARSER_TRX
+       tristate "Parser for TRX format partitions"
+       depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST)
diff --git a/target/linux/ath79/patches-5.4/405-mtd-tp-link-partition-parser.patch b/target/linux/ath79/patches-5.4/405-mtd-tp-link-partition-parser.patch
new file mode 100644 (file)
index 0000000..7ea07f3
--- /dev/null
@@ -0,0 +1,25 @@
+--- a/drivers/mtd/Kconfig
++++ b/drivers/mtd/Kconfig
+@@ -62,6 +62,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
+@@ -8,6 +8,7 @@ obj-$(CONFIG_MTD)              += mtd.o
+ mtd-y                         := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o
+ obj-y                         += parsers/
++obj-$(CONFIG_MTD_TPLINK_PARTS)        += tplinkpart.o
+ # 'Users' - code which presents functionality to userspace.
+ obj-$(CONFIG_MTD_BLKDEVS)     += mtd_blkdevs.o
diff --git a/target/linux/ath79/patches-5.4/408-mtd-redboot_partition_scan.patch b/target/linux/ath79/patches-5.4/408-mtd-redboot_partition_scan.patch
new file mode 100644 (file)
index 0000000..8f3ee32
--- /dev/null
@@ -0,0 +1,44 @@
+--- a/drivers/mtd/parsers/redboot.c
++++ b/drivers/mtd/parsers/redboot.c
+@@ -85,12 +85,18 @@ static int parse_redboot_partitions(stru
+       parse_redboot_of(master);
++      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;
+@@ -103,10 +109,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);
+@@ -179,6 +181,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/ath79/patches-5.4/425-at803x-allow-sgmii-aneg-override.patch b/target/linux/ath79/patches-5.4/425-at803x-allow-sgmii-aneg-override.patch
new file mode 100644 (file)
index 0000000..396b1ee
--- /dev/null
@@ -0,0 +1,16 @@
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -383,6 +383,13 @@ static int at803x_aneg_done(struct phy_d
+       if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
+               phydev_warn(phydev, "803x_aneg_done: SGMII link is not ok\n");
+               aneg_done = 0;
++#ifdef CONFIG_OF_MDIO
++              if (phydev->mdio.dev.of_node &&
++                              of_property_read_bool(phydev->mdio.dev.of_node,
++                              "at803x-override-sgmii-link-check")) {
++                      aneg_done = 1;
++              }
++#endif
+       }
+       /* switch back to copper page */
+       phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
diff --git a/target/linux/ath79/patches-5.4/430-drivers-link-spi-before-mtd.patch b/target/linux/ath79/patches-5.4/430-drivers-link-spi-before-mtd.patch
new file mode 100644 (file)
index 0000000..4c6558d
--- /dev/null
@@ -0,0 +1,12 @@
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -80,8 +80,8 @@ obj-y                                += 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-$(CONFIG_SLIMBUS)         += slimbus/
diff --git a/target/linux/ath79/patches-5.4/440-mtd-ar934x-nand-driver.patch b/target/linux/ath79/patches-5.4/440-mtd-ar934x-nand-driver.patch
new file mode 100644 (file)
index 0000000..8cb47ff
--- /dev/null
@@ -0,0 +1,25 @@
+--- a/drivers/mtd/nand/raw/Kconfig
++++ b/drivers/mtd/nand/raw/Kconfig
+@@ -544,4 +544,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
+         load time (assuming you build diskonchip as a module) with the module
+         parameter "inftl_bbt_write=1".
++config MTD_NAND_AR934X
++      tristate "Support for NAND controller on Qualcomm Atheros AR934x/QCA955x SoCs"
++      depends on ATH79 || COMPILE_TEST
++      depends on HAS_IOMEM
++      help
++        Enables support for NAND controller on Qualcomm Atheros SoCs.
++        This controller is found on AR934x and QCA955x SoCs.
++
+ endif # MTD_RAW_NAND
+--- a/drivers/mtd/nand/raw/Makefile
++++ b/drivers/mtd/nand/raw/Makefile
+@@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_MXIC)          += mxic_nan
+ obj-$(CONFIG_MTD_NAND_TEGRA)          += tegra_nand.o
+ obj-$(CONFIG_MTD_NAND_STM32_FMC2)     += stm32_fmc2_nand.o
+ obj-$(CONFIG_MTD_NAND_MESON)          += meson_nand.o
++obj-$(CONFIG_MTD_NAND_AR934X)         += ar934x_nand.o
+ nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
+ nand-objs += nand_onfi.o
diff --git a/target/linux/ath79/patches-5.4/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch b/target/linux/ath79/patches-5.4/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch
new file mode 100644 (file)
index 0000000..924faec
--- /dev/null
@@ -0,0 +1,98 @@
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ath79/mangle-port.h
+@@ -0,0 +1,37 @@
++/*
++ *  Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
++ *
++ *  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_AR71XX
++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/pci/pci-ar71xx.c
++++ b/arch/mips/pci/pci-ar71xx.c
+@@ -68,6 +68,45 @@ static const u32 ar71xx_pci_read_mask[8]
+       0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0
+ };
++static unsigned long (*__ath79_pci_swizzle_b)(unsigned long port);
++static unsigned long (*__ath79_pci_swizzle_w)(unsigned long port);
++
++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);
++
+ static inline u32 ar71xx_pci_get_ble(int where, int size, int local)
+ {
+       u32 t;
+@@ -276,6 +315,9 @@ static int ar71xx_pci_probe(struct platf
+       register_pci_controller(&apc->pci_ctrl);
++      __ath79_pci_swizzle_b = ar71xx_pci_swizzle_b;
++      __ath79_pci_swizzle_w = ar71xx_pci_swizzle_w;
++
+       return 0;
+ }
diff --git a/target/linux/ath79/patches-5.4/900-mdio_bitbang_ignore_ta_value.patch b/target/linux/ath79/patches-5.4/900-mdio_bitbang_ignore_ta_value.patch
new file mode 100644 (file)
index 0000000..148d843
--- /dev/null
@@ -0,0 +1,32 @@
+--- a/drivers/net/phy/mdio-bitbang.c
++++ b/drivers/net/phy/mdio-bitbang.c
+@@ -152,7 +152,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);
+@@ -162,19 +162,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/ath79/patches-5.4/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch b/target/linux/ath79/patches-5.4/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch
new file mode 100644 (file)
index 0000000..8c71e5b
--- /dev/null
@@ -0,0 +1,61 @@
+From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+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 <jogo@openwrt.org>
+---
+ 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
+@@ -14,6 +14,7 @@
+  * Vitaly Bordug <vbordug@ru.mvista.com>
+  */
++#include <linux/irqflags.h>
+ #include <linux/module.h>
+ #include <linux/mdio-bitbang.h>
+ #include <linux/types.h>
+@@ -153,7 +154,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);
+@@ -166,13 +169,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);
+@@ -187,6 +194,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/ath79/patches-5.4/910-unaligned_access_hacks.patch b/target/linux/ath79/patches-5.4/910-unaligned_access_hacks.patch
new file mode 100644 (file)
index 0000000..950430a
--- /dev/null
@@ -0,0 +1,869 @@
+--- 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 <asm-generic/checksum.h>
+ #endif /* CONFIG_GENERIC_CSUM */
+--- a/include/uapi/linux/ip.h
++++ b/include/uapi/linux/ip.h
+@@ -103,7 +103,7 @@ struct iphdr {
+       __be32  saddr;
+       __be32  daddr;
+       /*The options start here. */
+-};
++} __attribute__((packed, aligned(2)));
+ struct ip_auth_hdr {
+--- a/include/uapi/linux/ipv6.h
++++ b/include/uapi/linux/ipv6.h
+@@ -131,7 +131,7 @@ struct ipv6hdr {
+       struct  in6_addr        saddr;
+       struct  in6_addr        daddr;
+-};
++} __attribute__((packed, aligned(2)));
+ /* index values for the variables in ipv6_devconf */
+--- a/include/uapi/linux/tcp.h
++++ b/include/uapi/linux/tcp.h
+@@ -55,7 +55,7 @@ struct tcphdr {
+       __be16  window;
+       __sum16 check;
+       __be16  urg_ptr;
+-};
++} __attribute__((packed, aligned(2)));
+ /*
+  *    The union cast uses a gcc extension to avoid aliasing problems
+@@ -65,7 +65,7 @@ struct tcphdr {
+ union tcp_word_hdr { 
+       struct tcphdr hdr;
+       __be32            words[5];
+-}; 
++} __attribute__((packed, aligned(2)));
+ #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) 
+--- a/include/uapi/linux/udp.h
++++ b/include/uapi/linux/udp.h
+@@ -25,7 +25,7 @@ struct udphdr {
+       __be16  dest;
+       __be16  len;
+       __sum16 check;
+-};
++} __attribute__((packed, aligned(2)));
+ /* UDP socket options */
+ #define UDP_CORK      1       /* Never send partially complete segments */
+--- a/net/netfilter/nf_conntrack_core.c
++++ b/net/netfilter/nf_conntrack_core.c
+@@ -271,8 +271,8 @@ nf_ct_get_tuple(const struct sk_buff *sk
+       switch (l3num) {
+       case NFPROTO_IPV4:
+-              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);
+               break;
+       case NFPROTO_IPV6:
+               memcpy(tuple->src.u3.ip6, ap, sizeof(tuple->src.u3.ip6));
+--- a/include/uapi/linux/icmp.h
++++ b/include/uapi/linux/icmp.h
+@@ -82,7 +82,7 @@ struct icmphdr {
+       } frag;
+       __u8    reserved[4];
+   } un;
+-};
++} __attribute__((packed, aligned(2)));
+ /*
+--- a/include/uapi/linux/in6.h
++++ b/include/uapi/linux/in6.h
+@@ -43,7 +43,7 @@ struct in6_addr {
+ #define s6_addr16             in6_u.u6_addr16
+ #define s6_addr32             in6_u.u6_addr32
+ #endif
+-};
++} __attribute__((packed, aligned(2)));
+ #endif /* __UAPI_DEF_IN6_ADDR */
+ #if __UAPI_DEF_SOCKADDR_IN6
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -35,6 +35,7 @@
+ #include <linux/ipsec.h>
+ #include <linux/times.h>
+ #include <linux/slab.h>
++#include <asm/unaligned.h>
+ #include <linux/uaccess.h>
+ #include <linux/ipv6.h>
+ #include <linux/icmpv6.h>
+@@ -849,10 +850,10 @@ static void tcp_v6_send_response(const s
+       topt = (__be32 *)(t1 + 1);
+       if (tsecr) {
+-              *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+-                              (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+-              *topt++ = htonl(tsval);
+-              *topt++ = htonl(tsecr);
++              put_unaligned_be32((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
++                              (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP, topt++);
++              put_unaligned_be32(tsval, topt++);
++              put_unaligned_be32(tsecr, topt++);
+       }
+ #ifdef CONFIG_TCP_MD5SIG
+--- a/include/linux/ipv6.h
++++ b/include/linux/ipv6.h
+@@ -6,6 +6,7 @@
+ #define ipv6_optlen(p)  (((p)->hdrlen+1) << 3)
+ #define ipv6_authlen(p) (((p)->hdrlen+2) << 2)
++
+ /*
+  * This structure contains configuration options per IPv6 link.
+  */
+--- a/net/ipv6/datagram.c
++++ b/net/ipv6/datagram.c
+@@ -476,7 +476,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;
+               }
+@@ -830,12 +830,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/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -752,7 +752,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, idev, IPSTATS_MIB_INHDRERRORS);
+               icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
+--- a/include/linux/types.h
++++ b/include/linux/types.h
+@@ -225,5 +225,11 @@ struct callback_head {
+ typedef void (*rcu_callback_t)(struct rcu_head *head);
+ typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func);
++struct net_hdr_word {
++       u32 words[1];
++} __attribute__((packed, aligned(2)));
++
++#define net_hdr_word(_p) (((struct net_hdr_word *) (_p))->words[0])
++
+ #endif /*  __ASSEMBLY__ */
+ #endif /* _LINUX_TYPES_H */
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -1441,8 +1441,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;
+       list_for_each_entry(p, head, list) {
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -457,48 +457,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)) {
+@@ -506,16 +511,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;
+@@ -528,13 +534,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/include/uapi/linux/igmp.h
++++ b/include/uapi/linux/igmp.h
+@@ -33,7 +33,7 @@ struct igmphdr {
+       __u8 code;              /* For newer IGMP */
+       __sum16 csum;
+       __be32 group;
+-};
++} __attribute__((packed, aligned(2)));
+ /* V3 group record types [grec_type] */
+ #define IGMPV3_MODE_IS_INCLUDE                1
+@@ -49,7 +49,7 @@ struct igmpv3_grec {
+       __be16  grec_nsrcs;
+       __be32  grec_mca;
+       __be32  grec_src[0];
+-};
++} __attribute__((packed, aligned(2)));
+ struct igmpv3_report {
+       __u8 type;
+@@ -58,7 +58,7 @@ struct igmpv3_report {
+       __be16 resv2;
+       __be16 ngrec;
+       struct igmpv3_grec grec[0];
+-};
++} __attribute__((packed, aligned(2)));
+ struct igmpv3_query {
+       __u8 type;
+@@ -79,7 +79,7 @@ struct igmpv3_query {
+       __u8 qqic;
+       __be16 nsrcs;
+       __be32 srcs[0];
+-};
++} __attribute__((packed, aligned(2)));
+ #define IGMP_HOST_MEMBERSHIP_QUERY    0x11    /* From RFC1112 */
+ #define IGMP_HOST_MEMBERSHIP_REPORT   0x12    /* Ditto */
+--- a/net/core/flow_dissector.c
++++ b/net/core/flow_dissector.c
+@@ -196,7 +196,7 @@ __be32 __skb_flow_get_ports(const struct
+               ports = __skb_header_pointer(skb, thoff + poff,
+                                            sizeof(_ports), data, hlen, &_ports);
+               if (ports)
+-                      return *ports;
++                      return (__be32)net_hdr_word(ports);
+       }
+       return 0;
+--- a/include/uapi/linux/icmpv6.h
++++ b/include/uapi/linux/icmpv6.h
+@@ -77,7 +77,7 @@ struct icmp6hdr {
+ #define icmp6_addrconf_other  icmp6_dataun.u_nd_ra.other
+ #define icmp6_rt_lifetime     icmp6_dataun.u_nd_ra.rt_lifetime
+ #define icmp6_router_pref     icmp6_dataun.u_nd_ra.router_pref
+-};
++} __attribute__((packed, aligned(2)));
+ #define ICMPV6_ROUTER_PREF_LOW                0x3
+--- a/include/net/ndisc.h
++++ b/include/net/ndisc.h
+@@ -92,7 +92,7 @@ struct ra_msg {
+         struct icmp6hdr               icmph;
+       __be32                  reachable_time;
+       __be32                  retrans_timer;
+-};
++} __attribute__((packed, aligned(2)));
+ struct rd_msg {
+       struct icmp6hdr icmph;
+@@ -371,10 +371,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
+@@ -155,7 +155,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;
+                       }
+@@ -206,8 +206,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
+@@ -240,7 +240,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *
+                       continue;
+               iph2 = (struct ipv6hdr *)(p->data + off);
+-              first_word = *(__be32 *)iph ^ *(__be32 *)iph2;
++              first_word = net_hdr_word(iph) ^ net_hdr_word(iph2);
+               /* All fields must match except length and Traffic Class.
+                * XXX skbs on the gro_list have all been parsed and pulled
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -47,7 +47,7 @@ struct prefix_info {
+       __be32                  reserved2;
+       struct in6_addr         prefix;
+-};
++} __attribute__((packed, aligned(2)));
+ #include <linux/ipv6.h>
+ #include <linux/netdevice.h>
+--- a/include/net/inet_ecn.h
++++ b/include/net/inet_ecn.h
+@@ -125,9 +125,9 @@ static inline int IP6_ECN_set_ce(struct
+       if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
+               return 0;
+-      from = *(__be32 *)iph;
++      from = net_hdr_word(iph);
+       to = from | htonl(INET_ECN_CE << 20);
+-      *(__be32 *)iph = to;
++      net_hdr_word(iph) = to;
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from),
+                                    (__force __wsum)to);
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -146,7 +146,7 @@ struct frag_hdr {
+       __u8    reserved;
+       __be16  frag_off;
+       __be32  identification;
+-};
++} __attribute__((packed, aligned(2)));
+ #define       IP6_MF          0x0001
+ #define       IP6_OFFSET      0xFFF8
+@@ -557,8 +557,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,
+@@ -617,6 +617,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;
+@@ -625,7 +627,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;
+@@ -741,13 +745,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));
+       }
+@@ -934,17 +938,18 @@ static inline int ip6_multipath_hash_pol
+ static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass,
+                               __be32 flowlabel)
+ {
+-      *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel;
++      net_hdr_word((__be32 *)hdr) =
++              htonl(0x60000000 | (tclass << 20)) | flowlabel;
+ }
+ static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr)
+ {
+-      return *(__be32 *)hdr & IPV6_FLOWINFO_MASK;
++      return net_hdr_word((__be32 *)hdr) & IPV6_FLOWINFO_MASK;
+ }
+ static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
+ {
+-      return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
++      return net_hdr_word((__be32 *)hdr) & IPV6_FLOWLABEL_MASK;
+ }
+ static inline u8 ip6_tclass(__be32 flowinfo)
+--- a/include/net/secure_seq.h
++++ b/include/net/secure_seq.h
+@@ -3,6 +3,7 @@
+ #define _NET_SECURE_SEQ
+ #include <linux/types.h>
++#include <linux/in6.h>
+ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+--- a/include/uapi/linux/in.h
++++ b/include/uapi/linux/in.h
+@@ -84,7 +84,7 @@ enum {
+ /* Internet address. */
+ struct in_addr {
+       __be32  s_addr;
+-};
++} __attribute__((packed, aligned(2)));
+ #endif
+ #define IP_TOS                1
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -140,7 +140,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]);
+ }
+ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags, bool with_fib6_nh)
+--- a/net/netfilter/nf_conntrack_proto_tcp.c
++++ b/net/netfilter/nf_conntrack_proto_tcp.c
+@@ -415,7 +415,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
+@@ -162,8 +162,8 @@ int xfrm_parse_spi(struct sk_buff *skb,
+       if (!pskb_may_pull(skb, hlen))
+               return -EINVAL;
+-      *spi = *(__be32 *)(skb_transport_header(skb) + offset);
+-      *seq = *(__be32 *)(skb_transport_header(skb) + offset_seq);
++      *spi = net_hdr_word(skb_transport_header(skb) + offset);
++      *seq = net_hdr_word(skb_transport_header(skb) + offset_seq);
+       return 0;
+ }
+ EXPORT_SYMBOL(xfrm_parse_spi);
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -3953,14 +3953,16 @@ static bool tcp_parse_aligned_timestamp(
+ {
+       const __be32 *ptr = (const __be32 *)(th + 1);
+-      if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+-                        | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
++      if (net_hdr_word(ptr) ==
++          htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
++                (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
+               tp->rx_opt.saw_tstamp = 1;
+               ++ptr;
+-              tp->rx_opt.rcv_tsval = ntohl(*ptr);
++              tp->rx_opt.rcv_tsval = get_unaligned_be32(ptr);
+               ++ptr;
+-              if (*ptr)
+-                      tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
++              if (net_hdr_word(ptr))
++                      tp->rx_opt.rcv_tsecr = get_unaligned_be32(ptr) -
++                                             tp->tsoffset;
+               else
+                       tp->rx_opt.rcv_tsecr = 0;
+               return true;
+--- a/include/uapi/linux/if_pppox.h
++++ b/include/uapi/linux/if_pppox.h
+@@ -51,6 +51,7 @@ struct pppoe_addr {
+  */
+ struct pptp_addr {
+       __u16           call_id;
++      __u16           pad;
+       struct in_addr  sin_addr;
+ };
+--- a/net/ipv6/netfilter/nf_log_ipv6.c
++++ b/net/ipv6/netfilter/nf_log_ipv6.c
+@@ -63,9 +63,9 @@ static void dump_ipv6_packet(struct net
+       /* 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
+@@ -274,8 +274,10 @@ static inline bool neigh_key_eq128(const
+       const u32 *n32 = (const u32 *)n->primary_key;
+       const u32 *p32 = pkey;
+-      return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) |
+-              (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0;
++      return ((n32[0] ^ net_hdr_word(&p32[0])) |
++              (n32[1] ^ net_hdr_word(&p32[1])) |
++              (n32[2] ^ net_hdr_word(&p32[2])) |
++              (n32[3] ^ net_hdr_word(&p32[3]))) == 0;
+ }
+ static inline struct neighbour *___neigh_lookup_noref(
+--- a/include/uapi/linux/netfilter_arp/arp_tables.h
++++ b/include/uapi/linux/netfilter_arp/arp_tables.h
+@@ -70,7 +70,7 @@ struct arpt_arp {
+       __u8 flags;
+       /* Inverse flags */
+       __u16 invflags;
+-};
++} __attribute__((aligned(4)));
+ /* Values for "flag" field in struct arpt_ip (general arp structure).
+  * No flags defined yet.
+--- a/net/core/utils.c
++++ b/net/core/utils.c
+@@ -443,8 +443,14 @@ void inet_proto_csum_replace16(__sum16 *
+                              bool pseudohdr)
+ {
+       __be32 diff[] = {
+-              ~from[0], ~from[1], ~from[2], ~from[3],
+-              to[0], to[1], to[2], to[3],
++              ~net_hdr_word(&from[0]),
++              ~net_hdr_word(&from[1]),
++              ~net_hdr_word(&from[2]),
++              ~net_hdr_word(&from[3]),
++              net_hdr_word(&to[0]),
++              net_hdr_word(&to[1]),
++              net_hdr_word(&to[2]),
++              net_hdr_word(&to[3]),
+       };
+       if (skb->ip_summed != CHECKSUM_PARTIAL) {
+               *sum = csum_fold(csum_partial(diff, sizeof(diff),
+--- a/include/linux/etherdevice.h
++++ b/include/linux/etherdevice.h
+@@ -496,7 +496,7 @@ static inline bool is_etherdev_addr(cons
+  * @b: Pointer to Ethernet header
+  *
+  * Compare two Ethernet headers, returns 0 if equal.
+- * This assumes that the network header (i.e., IP header) is 4-byte
++ * This assumes that the network header (i.e., IP header) is 2-byte
+  * aligned OR the platform can handle unaligned access.  This is the
+  * case for all packets coming into netif_receive_skb or similar
+  * entry points.
+@@ -519,11 +519,12 @@ static inline unsigned long compare_ethe
+       fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6);
+       return fold;
+ #else
+-      u32 *a32 = (u32 *)((u8 *)a + 2);
+-      u32 *b32 = (u32 *)((u8 *)b + 2);
++      const u16 *a16 = a;
++      const u16 *b16 = b;
+-      return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) |
+-             (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]);
++      return (a16[0] ^ b16[0]) | (a16[1] ^ b16[1]) | (a16[2] ^ b16[2]) |
++             (a16[3] ^ b16[3]) | (a16[4] ^ b16[4]) | (a16[5] ^ b16[5]) |
++             (a16[6] ^ b16[6]);
+ #endif
+ }
+--- a/net/ipv4/tcp_offload.c
++++ b/net/ipv4/tcp_offload.c
+@@ -223,7 +223,7 @@ struct sk_buff *tcp_gro_receive(struct l
+               th2 = tcp_hdr(p);
+-              if (*(u32 *)&th->source ^ *(u32 *)&th2->source) {
++              if (net_hdr_word(&th->source) ^ net_hdr_word(&th2->source)) {
+                       NAPI_GRO_CB(p)->same_flow = 0;
+                       continue;
+               }
+@@ -241,8 +241,8 @@ found:
+                 ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH));
+       flush |= (__force int)(th->ack_seq ^ th2->ack_seq);
+       for (i = sizeof(*th); i < thlen; i += 4)
+-              flush |= *(u32 *)((u8 *)th + i) ^
+-                       *(u32 *)((u8 *)th2 + i);
++              flush |= net_hdr_word((u8 *)th + i) ^
++                       net_hdr_word((u8 *)th2 + i);
+       /* When we receive our second frame we can made a decision on if we
+        * continue this flow as an atomic flow with a fixed ID or if we use
+--- a/net/ipv6/netfilter/ip6table_mangle.c
++++ b/net/ipv6/netfilter/ip6table_mangle.c
+@@ -47,7 +47,7 @@ ip6t_mangle_out(struct sk_buff *skb, con
+       hop_limit = ipv6_hdr(skb)->hop_limit;
+       /* flowlabel and prio (includes version, which shouldn't change either */
+-      flowlabel = *((u_int32_t *)ipv6_hdr(skb));
++      flowlabel = net_hdr_word(ipv6_hdr(skb));
+       ret = ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle);
+@@ -56,7 +56,7 @@ ip6t_mangle_out(struct sk_buff *skb, con
+            !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) ||
+            skb->mark != mark ||
+            ipv6_hdr(skb)->hop_limit != hop_limit ||
+-           flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) {
++           flowlabel != net_hdr_word(ipv6_hdr(skb)))) {
+               err = ip6_route_me_harder(state->net, skb);
+               if (err < 0)
+                       ret = NF_DROP_ERR(err);
index 9b845abbff77de3538adc71af04055c855ed7030..42243cfc481ab57f0b159535c8a3618c861070f9 100644 (file)
@@ -1,9 +1,12 @@
 CONFIG_LEDS_RESET=y
 CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+CONFIG_NET_DEVLINK=y
 CONFIG_NET_DSA=y
 CONFIG_NET_DSA_MV88E6060=y
+# CONFIG_NET_DSA_TAG_QCA is not set
 CONFIG_NET_DSA_TAG_TRAILER=y
 CONFIG_NET_SWITCHDEV=y
+CONFIG_PHYLINK=y
 CONFIG_PHY_AR7100_USB=y
 CONFIG_PHY_AR7200_USB=y
 CONFIG_REGULATOR=y