From 8292537e905b8f0042aaf03fe76be03681f77d13 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Mon, 16 Jan 2023 18:25:40 +0100 Subject: [PATCH 01/21] dosfstools: refresh patches Signed-off-by: David Bauer --- .../dosfstools/patches/source-date-epoch.patch | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/tools/dosfstools/patches/source-date-epoch.patch b/tools/dosfstools/patches/source-date-epoch.patch index fb46753f247..c758caa4c1d 100644 --- a/tools/dosfstools/patches/source-date-epoch.patch +++ b/tools/dosfstools/patches/source-date-epoch.patch @@ -19,8 +19,6 @@ Signed-off-by: Bjørn Forsman src/mkfs.fat.c | 19 ++++++++++++++++--- 3 files changed, 53 insertions(+), 7 deletions(-) -diff --git a/src/boot.c b/src/boot.c -index 4de450d..8f78e1c 100644 --- a/src/boot.c +++ b/src/boot.c @@ -33,6 +33,8 @@ @@ -32,7 +30,7 @@ index 4de450d..8f78e1c 100644 #include "common.h" #include "fsck.fat.h" -@@ -672,6 +674,7 @@ void write_volume_label(DOS_FS * fs, char *label) +@@ -672,6 +674,7 @@ void write_volume_label(DOS_FS * fs, cha { time_t now; struct tm *mtime; @@ -40,7 +38,7 @@ index 4de450d..8f78e1c 100644 off_t offset; int created; DIR_ENT de; -@@ -687,8 +690,24 @@ void write_volume_label(DOS_FS * fs, char *label) +@@ -687,8 +690,24 @@ void write_volume_label(DOS_FS * fs, cha if (de.name[0] == 0xe5) de.name[0] = 0x05; @@ -67,8 +65,6 @@ index 4de450d..8f78e1c 100644 if (mtime && mtime->tm_year >= 80 && mtime->tm_year <= 207) { de.time = htole16((unsigned short)((mtime->tm_sec >> 1) + (mtime->tm_min << 5) + -diff --git a/src/common.c b/src/common.c -index 6a2e396..4f1afcb 100644 --- a/src/common.c +++ b/src/common.c @@ -30,6 +30,7 @@ @@ -83,10 +79,9 @@ index 6a2e396..4f1afcb 100644 uint32_t generate_volume_id(void) { struct timeval now; -- -- if (gettimeofday(&now, NULL) != 0 || now.tv_sec == (time_t)-1 || now.tv_sec < 0) { + char *source_date_epoch = NULL; -+ + +- if (gettimeofday(&now, NULL) != 0 || now.tv_sec == (time_t)-1 || now.tv_sec < 0) { + source_date_epoch = getenv("SOURCE_DATE_EPOCH"); + if (source_date_epoch) { + char *tmp = NULL; @@ -103,8 +98,6 @@ index 6a2e396..4f1afcb 100644 srand(getpid()); /* rand() returns int from [0,RAND_MAX], therefore only 31 bits */ return (((uint32_t)(rand() & 0xFFFF)) << 16) | ((uint32_t)(rand() & 0xFFFF)); -diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c -index 37fc8ff..1948635 100644 --- a/src/mkfs.fat.c +++ b/src/mkfs.fat.c @@ -1074,7 +1074,7 @@ static void setup_tables(void) @@ -154,4 +147,4 @@ index 37fc8ff..1948635 100644 + volume_id = generate_volume_id(); check_atari(); - \ No newline at end of file + From 9300a20dcce2217b121bd2020cc1a4ea41fa4475 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Mon, 16 Jan 2023 01:30:29 +0100 Subject: [PATCH 02/21] dosfstools: switch to AC_CHECK_LIB This fixes spurious build-errors on OpenWrt, where the AM_ICONV macro is undefined while invoking autoconfig. Later in the build, the ICONV LDOPTIONS are set to @LIBICONV@, failing the build. Signed-off-by: David Bauer --- ...poch.patch => 100-source-date-epoch.patch} | 0 .../101-config-switch-to-AC_CHECK_LIB.patch | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+) rename tools/dosfstools/patches/{source-date-epoch.patch => 100-source-date-epoch.patch} (100%) create mode 100644 tools/dosfstools/patches/101-config-switch-to-AC_CHECK_LIB.patch diff --git a/tools/dosfstools/patches/source-date-epoch.patch b/tools/dosfstools/patches/100-source-date-epoch.patch similarity index 100% rename from tools/dosfstools/patches/source-date-epoch.patch rename to tools/dosfstools/patches/100-source-date-epoch.patch diff --git a/tools/dosfstools/patches/101-config-switch-to-AC_CHECK_LIB.patch b/tools/dosfstools/patches/101-config-switch-to-AC_CHECK_LIB.patch new file mode 100644 index 00000000000..ba2d00bf84b --- /dev/null +++ b/tools/dosfstools/patches/101-config-switch-to-AC_CHECK_LIB.patch @@ -0,0 +1,28 @@ +From e7671c2a3be03d790cbc225cd3e784b5434fb5da Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 16 Jan 2023 01:29:22 +0100 +Subject: [PATCH] config: switch to AC_CHECK_LIB + +This fixes spurious build-errors on OpenWrt, where the AM_ICONV macro +is undefined while invoking autoconfig. Later in the build, the ICONV +LDOPTIONS are set to @LIBICONV@, failing the build. + +Signed-off-by: David Bauer +--- + configure.ac | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/configure.ac ++++ b/configure.ac +@@ -70,10 +70,7 @@ AC_CHECK_DECLS([getmntent], [], [], [[#i + AC_CHECK_DECLS([getmntinfo], [], [], [[#include ]]) + + # optional iconv support +-AC_ARG_WITH([iconv], AS_HELP_STRING([--without-iconv], [build without iconv support])) +-if test "x$with_iconv" != "xno"; then +- AM_ICONV +-fi ++AC_CHECK_LIB(iconv, iconv_open) + + # xxd (distributed with vim) is used in the testsuite + AC_CHECK_PROG([XXD_FOUND], [xxd], [yes]) From 1cefb14230db9b7e87015e7950ee931b3f21e1aa Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Sat, 14 Jan 2023 00:20:32 +0100 Subject: [PATCH 03/21] archs38: switch to 5.15 by default It appears that only a few users are using the archs38 SoC. The most active user of the target has already approved the testing kernel and so it is very unlikely bugs will be reported in the near future. Therefore, the target should be directly bumped to 5.15. Signed-off-by: Nick Hainke --- target/linux/archs38/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/archs38/Makefile b/target/linux/archs38/Makefile index fb00884a9af..42b4edad8a9 100644 --- a/target/linux/archs38/Makefile +++ b/target/linux/archs38/Makefile @@ -11,8 +11,7 @@ BOARDNAME:=Synopsys DesignWare ARC HS38 FEATURES:=source-only SUBTARGETS:=generic -KERNEL_PATCHVER:=5.10 -KERNEL_TESTING_PATCHVER:=5.15 +KERNEL_PATCHVER:=5.15 DEVICE_TYPE:=basic From 83c0942ff7cb1a1aae2e5da6424c803644e3fa38 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 16 Jan 2023 19:40:24 +0000 Subject: [PATCH 04/21] kernel: fix kernel panic in mtk_ppe The patch that adds support for hw flow-offloading counters on newer MediaTek SoCs tries to prints acct->packets and acct->bytes in debugfs, without checking that acct isn't null. This causes a kernel panic when trying to read /sys/kernel/debug/ppe0/entries on older MediaTek SoCs. Fix this by adding a check for acct. Fixes: openwrt#11756 Fixes: 9721a42a27 ("kernel: support hw flow-offloading counters on newer MediaTek SoCs") Reported-by: Stijn Tintel Signed-off-by: Daniel Golle --- ...1-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch b/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch index aea6a605a90..c76a00eabd8 100644 --- a/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch +++ b/target/linux/generic/pending-5.15/731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch @@ -357,7 +357,7 @@ v2: fix wrong variable name in return value check spotted by Denis Kirjanov h_source, h_dest, ntohs(l2->etype), - l2->vlan1, l2->vlan2, entry->ib1, ib2); + l2->vlan1, l2->vlan2, entry->ib1, ib2, -+ acct->packets, acct->bytes); ++ acct ? acct->packets : 0, acct ? acct->bytes : 0); } return 0; From 86a2dae29a7391f83a0b8d2f85828f72c834b17e Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 16 Jan 2023 21:00:41 +0000 Subject: [PATCH 05/21] mediatek: mt7622: fix sysupgrade on MMC on BPi-R64 A previous attempt to simplify things went wrong and now sysupgrade is broken on this device. Fix that. Fixes: d640cbac0e ("mediatek: mt7622: don't rely on existing image for sysupgrade") Signed-off-by: Daniel Golle --- target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh index e62eba7ef17..d3d503dd1ef 100755 --- a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh @@ -8,6 +8,7 @@ platform_do_upgrade() { bananapi,bpi-r64) local rootdev="$(cmdline_get_var root)" rootdev="${rootdev##*/}" + rootdev="${rootdev%p[0-9]*}" case "$rootdev" in mmc*) CI_ROOTDEV="$rootdev" From ab3c9ccb615032d18b2395ca2d68523fc1565dc3 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 16 Jan 2023 21:02:00 +0000 Subject: [PATCH 06/21] mediatek: filogic: fix sysupgrade on MMC on the BPi-R3 A previous attempt to simplify things went wrong and now sysupgrade is broken on this device. Fix that. Fixes: de94587e70 ("mediatek: filogic: don't rely on image preset in flash or sysupgrade") Signed-off-by: Daniel Golle --- .../filogic/base-files/lib/upgrade/platform.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index c2808bc7368..93b202218a8 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -43,17 +43,20 @@ platform_do_upgrade() { case "$board" in bananapi,bpi-r3) - case "$(cmdline_get_var root)" in - /dev/mmc*) + local rootdev="$(cmdline_get_var root)" + rootdev="${rootdev##*/}" + rootdev="${rootdev%p[0-9]*}" + case "$rootdev" in + mmc*) CI_ROOTDEV="$rootdev" CI_KERNPART="production" emmc_do_upgrade "$1" ;; - /dev/mtdblock*) + mtdblock*) PART_NAME="fit" default_do_upgrade "$1" ;; - /dev/ubiblock*) + ubiblock*) CI_KERNPART="fit" nand_do_upgrade "$1" ;; From f0a98bf048bdab981a1c34ba25d3c91989a57c22 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 16 Jan 2023 22:03:31 +0000 Subject: [PATCH 07/21] procd: update to git HEAD 04d7570 jail: fs: don't overwrite existing mount target 6b9629b jail: don't assume positive return value of creat 190f13a init: attempt to mount efivarfs Signed-off-by: Daniel Golle --- package/system/procd/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile index 2eebe50a4fa..56aa9e0b358 100644 --- a/package/system/procd/Makefile +++ b/package/system/procd/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=procd -PKG_RELEASE:=$(AUTORELEASE) +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/procd.git -PKG_MIRROR_HASH:=d60b4aa9d47d75e906dfd812528a1bc28e91f5af72a9d9275056b71b19d99f04 -PKG_SOURCE_DATE:=2022-11-10 -PKG_SOURCE_VERSION:=039b88f75367203e540009cc97603b1bce3fafa6 +PKG_MIRROR_HASH:=75a92c01ef85f41dc7e0b77ac35f464fbe45942af02ca6847516c4ebf574c4a4 +PKG_SOURCE_DATE:=2023-01-16 +PKG_SOURCE_VERSION:=190f13a75e67e0bdb662188da79b8be31e0aae01 CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 From 568d17989f22cf7179d789da2543feee79ad0647 Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Wed, 21 Aug 2019 08:29:33 +0200 Subject: [PATCH 08/21] kernel: add Intel/Lantiq VRX518 EP driver This driver was picked from the Intel UGW 8.5.2. Signed-off-by: Martin Schiller [updated for kernel 5.10] Signed-off-by: Jan Hoffmann [update to 8.5.2] Signed-off-by: Andre Heider [fix masking interrupts and add locking] Signed-off-by: Jan Hoffmann Signed-off-by: Andre Heider --- package/kernel/lantiq/vrx518_ep/Makefile | 57 + .../lantiq/vrx518_ep/patches/100-compat.patch | 73 + .../patches/200-fix-irq-masking.patch | 49 + package/kernel/lantiq/vrx518_ep/src/Kconfig | 9 + package/kernel/lantiq/vrx518_ep/src/Makefile | 33 + package/kernel/lantiq/vrx518_ep/src/aca.c | 1209 +++++++++++++++++ package/kernel/lantiq/vrx518_ep/src/aca.h | 481 +++++++ package/kernel/lantiq/vrx518_ep/src/ep.c | 770 +++++++++++ package/kernel/lantiq/vrx518_ep/src/ep.h | 127 ++ .../lantiq/vrx518_ep/src/include/net/dc_ep.h | 349 +++++ package/kernel/lantiq/vrx518_ep/src/misc.c | 325 +++++ package/kernel/lantiq/vrx518_ep/src/misc.h | 51 + package/kernel/lantiq/vrx518_ep/src/regs.h | 138 ++ .../kernel/lantiq/vrx518_ep/src/test/Makefile | 2 + .../lantiq/vrx518_ep/src/test/ep_test.c | 924 +++++++++++++ .../lantiq/vrx518_ep/src/test/ep_test.h | 273 ++++ 16 files changed, 4870 insertions(+) create mode 100644 package/kernel/lantiq/vrx518_ep/Makefile create mode 100644 package/kernel/lantiq/vrx518_ep/patches/100-compat.patch create mode 100644 package/kernel/lantiq/vrx518_ep/patches/200-fix-irq-masking.patch create mode 100644 package/kernel/lantiq/vrx518_ep/src/Kconfig create mode 100644 package/kernel/lantiq/vrx518_ep/src/Makefile create mode 100644 package/kernel/lantiq/vrx518_ep/src/aca.c create mode 100644 package/kernel/lantiq/vrx518_ep/src/aca.h create mode 100644 package/kernel/lantiq/vrx518_ep/src/ep.c create mode 100644 package/kernel/lantiq/vrx518_ep/src/ep.h create mode 100644 package/kernel/lantiq/vrx518_ep/src/include/net/dc_ep.h create mode 100644 package/kernel/lantiq/vrx518_ep/src/misc.c create mode 100644 package/kernel/lantiq/vrx518_ep/src/misc.h create mode 100644 package/kernel/lantiq/vrx518_ep/src/regs.h create mode 100644 package/kernel/lantiq/vrx518_ep/src/test/Makefile create mode 100644 package/kernel/lantiq/vrx518_ep/src/test/ep_test.c create mode 100644 package/kernel/lantiq/vrx518_ep/src/test/ep_test.h diff --git a/package/kernel/lantiq/vrx518_ep/Makefile b/package/kernel/lantiq/vrx518_ep/Makefile new file mode 100644 index 00000000000..1ed59d302ef --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/Makefile @@ -0,0 +1,57 @@ +# +# Copyright (C) 2019 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=vrx518_ep +PKG_VERSION:=2.1.0 +PKG_RELEASE:=$(AUTORELEASE) +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +# TODO this driver depends on the vrx518 aca firmware, add this dependency if +# that ever gets a compatible license +define KernelPackage/vrx518_ep + SECTION:=sys + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=VRX518 EP Support + DEPENDS:=@TARGET_ipq40xx + AUTOLOAD:=$(call AutoLoad,26,vrx518) + FILES:=$(PKG_BUILD_DIR)/vrx518.ko +endef + +define KernelPackage/vrx518_ep/description + VRX518 endpoint driver +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/net/ + $(CP) $(PKG_BUILD_DIR)/include/net/dc_ep.h $(1)/usr/include/net/ +endef + +EXTRA_KCONFIG:= \ + CONFIG_VRX518=m +# CONFIG_TEST=m +# CONFIG_VRX518_PCIE_SWITCH_BONDING=y + +EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ + -I$(PKG_BUILD_DIR)/include + +define Build/Compile + $(KERNEL_MAKE) \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + $(EXTRA_KCONFIG) \ + modules +endef + +$(eval $(call KernelPackage,vrx518_ep)) diff --git a/package/kernel/lantiq/vrx518_ep/patches/100-compat.patch b/package/kernel/lantiq/vrx518_ep/patches/100-compat.patch new file mode 100644 index 00000000000..f5b917e7078 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/patches/100-compat.patch @@ -0,0 +1,73 @@ +--- a/ep.c ++++ b/ep.c +@@ -373,23 +373,23 @@ int dc_ep_dev_info_req(int dev_idx, enum + + switch (module) { + case DC_EP_INT_PPE: +- dev->irq = priv->irq_base; ++ dev->irq = pci_irq_vector(priv->pdev, 0); + if (priv->msi_mode == DC_EP_8_MSI_MODE) { +- dev->aca_tx_irq = priv->irq_base + 7; +- dev->aca_rx_irq = priv->irq_base + 6; ++ dev->aca_tx_irq = pci_irq_vector(priv->pdev, 7); ++ dev->aca_rx_irq = pci_irq_vector(priv->pdev, 6); + } else if (priv->msi_mode == DC_EP_4_MSI_MODE) { +- dev->aca_tx_irq = priv->irq_base + 2; +- dev->aca_rx_irq = priv->irq_base + 3; ++ dev->aca_tx_irq = pci_irq_vector(priv->pdev, 2); ++ dev->aca_rx_irq = pci_irq_vector(priv->pdev, 3); + } else { + dev_err(dev->dev, "%s ACA should never occur\n", + __func__); + } + break; + case DC_EP_INT_MEI: +- dev->irq = priv->irq_base + 1; ++ dev->irq = pci_irq_vector(priv->pdev, 1); + break; + default: +- dev->irq = priv->irq_base; ++ dev->irq = pci_irq_vector(priv->pdev, 0); + break; + } + +@@ -466,8 +466,8 @@ static int dc_ep_msi_enable(struct pci_d + return -EIO; + } + +- err = pci_enable_msi_exact(pdev, nvec); +- if (err) { ++ err = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_MSI | PCI_IRQ_LEGACY); ++ if (err < 0) { + dev_err(&pdev->dev, + "%s: Failed to enable MSI interrupts error code: %d\n", + __func__, err); +@@ -654,7 +654,7 @@ static int dc_ep_probe(struct pci_dev *p + goto err_iomap; + + spin_lock(&dc_ep_lock); +- priv->irq_base = pdev->irq; ++ priv->irq_base = pci_irq_vector(pdev, 0); + spin_unlock(&dc_ep_lock); + + #ifndef CONFIG_OF +@@ -715,7 +715,7 @@ static void dc_ep_remove(struct pci_dev + dc_ep_icu_disable(priv); + pci_iounmap(pdev, priv->mem); + pci_release_region(pdev, DC_EP_BAR_NUM); +- pci_disable_msi(pdev); ++ pci_free_irq_vectors(pdev); + wmb(); + pci_clear_master(pdev); + pci_disable_device(pdev); +--- a/aca.c ++++ b/aca.c +@@ -756,7 +756,7 @@ static void aca_hif_param_init_done(stru + addr = fw_param->init_addr; + dev_dbg(priv->dev, "init_addr: %x\n", addr); + memcpy_toio(priv->mem + addr, hif_params, sizeof(*hif_params)); +- kzfree(hif_params); ++ kfree(hif_params); + dev_dbg(priv->dev, "%s\n", __func__); + } + diff --git a/package/kernel/lantiq/vrx518_ep/patches/200-fix-irq-masking.patch b/package/kernel/lantiq/vrx518_ep/patches/200-fix-irq-masking.patch new file mode 100644 index 00000000000..b833c72bec3 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/patches/200-fix-irq-masking.patch @@ -0,0 +1,49 @@ +Fix double negation of bitmask in dc_ep_icu_disable andwr32_mask. +Also add locking to ensure the masking is applied atomically. + +--- a/misc.c ++++ b/misc.c +@@ -68,12 +68,22 @@ void dc_ep_icu_disable(struct dc_ep_priv + + void dc_ep_icu_dis_intr(struct dc_ep_priv *priv, u32 bits) + { +- wr32_mask(~bits, 0, ICU_IMER); ++ struct dc_aca *aca = to_aca(priv); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&aca->icu_lock, flags); ++ wr32_mask(bits, 0, ICU_IMER); ++ spin_unlock_irqrestore(&aca->icu_lock, flags); + } + + void dc_ep_icu_en_intr(struct dc_ep_priv *priv, u32 bits) + { ++ struct dc_aca *aca = to_aca(priv); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&aca->icu_lock, flags); + wr32_mask(0, bits, ICU_IMER); ++ spin_unlock_irqrestore(&aca->icu_lock, flags); + } + + void dc_ep_assert_device(struct dc_ep_priv *priv, u32 bits) +--- a/aca.c ++++ b/aca.c +@@ -1158,6 +1158,7 @@ void dc_aca_info_init(struct dc_ep_priv + struct dc_aca *aca = to_aca(priv); + + aca->initialized = false; ++ spin_lock_init(&aca->icu_lock); + spin_lock_init(&aca->clk_lock); + spin_lock_init(&aca->rcu_lock); + mutex_init(&aca->pin_lock); +--- a/aca.h ++++ b/aca.h +@@ -470,6 +470,7 @@ struct aca_hif_params { + + struct dc_aca { + bool initialized; ++ spinlock_t icu_lock; + spinlock_t clk_lock; + spinlock_t rcu_lock; + struct mutex pin_lock; diff --git a/package/kernel/lantiq/vrx518_ep/src/Kconfig b/package/kernel/lantiq/vrx518_ep/src/Kconfig new file mode 100644 index 00000000000..296bc4c7aae --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/Kconfig @@ -0,0 +1,9 @@ +config TEST + tristate "Intel(R) VRX518 SmartPHY DSL Test Driver" + depends on VRX518 + ---help--- + This driver supports Intel(R) VRX518 DSL interrupt and ACA test. + + To compile this driver as a module, choose M here. The module + will be called vrx518. MSI interrupt support is required for + this driver to work correctly. diff --git a/package/kernel/lantiq/vrx518_ep/src/Makefile b/package/kernel/lantiq/vrx518_ep/src/Makefile new file mode 100644 index 00000000000..b79e74b3170 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/Makefile @@ -0,0 +1,33 @@ +################################################################################ +# +# Intel SmartPHY DSL PCIe EP/ACA Linux driver +# Copyright(c) 2016 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +# +# The full GNU General Public License is included in this distribution in +# the file called "COPYING". +# +################################################################################ + +# +# Makefile for the Intel(R) SmartPHY PCIe/ACA driver +# + +obj-$(CONFIG_VRX518) += vrx518.o + +vrx518-objs := ep.o aca.o misc.o + +obj-$(CONFIG_TEST) += test/ + diff --git a/package/kernel/lantiq/vrx518_ep/src/aca.c b/package/kernel/lantiq/vrx518_ep/src/aca.c new file mode 100644 index 00000000000..3fcf454884a --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/aca.c @@ -0,0 +1,1209 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ +#define DEBUG +#include +#include +#include +#include + +#include + +#include "regs.h" +#include "ep.h" +#include "misc.h" +#include "aca.h" + +#define ACA_FW_FILE "aca_fw.bin" + +#define set_mask_bit(val, set, mask, bits) \ + (val = (((val) & (~((mask) << (bits)))) \ + | (((set) & (mask)) << (bits)))) + +static char soc_str[128]; + +static const char *const aca_img_type_str[ACA_IMG_MAX] = { + "vrx518", + "vrx618", + "falcon-mx", + "pmua", +}; + +static void soc_type_to_str(u32 soc) +{ + memset(soc_str, 0, sizeof(soc_str)); + + if ((soc & ACA_SOC_XRX300)) + strcat(soc_str, "xrx300 "); + + if ((soc & ACA_SOC_XRX500)) + strcat(soc_str, "xrx500 "); + + if ((soc & ACA_SOC_PUMA)) + strcat(soc_str, "puma "); + + if ((soc & ACA_SOC_3RD_PARTY)) + strcat(soc_str, "third party SoC "); +} + +static const char *fw_id_to_str(u32 fw_id) +{ + switch (fw_id) { + case ACA_FW_TXIN: + return "txin"; + + case ACA_FW_TXOUT: + return "txout"; + + case ACA_FW_RXIN: + return "rxin"; + + case ACA_FW_RXOUT: + return "rxout"; + + case ACA_FW_GNRC: + return "Genrisc"; + + default: + return "unknow"; + } +} + +static const char * const sec_id_str[] = { + "Unknown", "HIF", "GenRisc", "MAC_HT", "TXIN", "TXIN_PDRING", "TXOUT", + "TXOUT_PDRING", "RXIN", "RXIN_PDRING", "RXOUT", "RXOUT_PDRING", "DMA", + "FW_INIT", +}; +static const char *sec_id_to_str(u32 sec_id) +{ + switch (sec_id) { + case ACA_SEC_HIF: + case ACA_SEC_GNR: + case ACA_SEC_MAC_HT: + case ACA_SEC_MEM_TXIN: + case ACA_SEC_MEM_TXIN_PDRING: + case ACA_SEC_MEM_TXOUT: + case ACA_SEC_MEM_TXOUT_PDRING: + case ACA_SEC_MEM_RXIN: + case ACA_SEC_MEM_RXIN_PDRING: + case ACA_SEC_MEM_RXOUT: + case ACA_SEC_MEM_RXOUT_PDRING: + case ACA_SEC_DMA: + case ACA_SEC_FW_INIT: + return sec_id_str[sec_id]; + case ACA_SEC_FW: + return "ACA FW"; + + default: + return "unknown"; + } +} + +static inline struct aca_fw_info *to_fw_info(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info; +} + +static inline struct aca_fw_dl_addr *to_fw_addr(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info.fw_dl; +} + +static inline struct aca_mem_layout *to_mem_layout(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info.mem_layout; +} + +static inline struct aca_pdmem_layout *to_pdmem_layout(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info.pdmem_layout; +} + +static inline struct aca_fw_param *to_aca_fw_param(struct dc_ep_priv *priv) +{ + return &priv->aca.fw_info.fw_param; +} + +static inline struct aca_hif_params *to_hif_params(struct dc_ep_priv *priv) +{ + return priv->aca.hif_params; +} + +static const struct firmware *aca_fetch_fw_file(struct dc_ep_priv *priv, + char *dir, const char *file) +{ + int ret; + char filename[100] = {0}; + const struct firmware *fw; + + if (file == NULL) + return ERR_PTR(-ENOENT); + + if (dir == NULL) + dir = "."; + + snprintf(filename, sizeof(filename), "%s/%s", dir, file); + ret = request_firmware(&fw, filename, priv->dev); + if (ret) + return ERR_PTR(ret); + + return fw; +} + +void dc_aca_free_fw_file(struct dc_ep_priv *priv) +{ + struct aca_fw_info *fw_info = to_fw_info(priv); + + if (fw_info->fw && !IS_ERR(fw_info->fw)) + release_firmware(fw_info->fw); + + fw_info->fw = NULL; + fw_info->fw_data = NULL; + fw_info->fw_len = 0; +} + +static void aca_dma_parse(struct dc_ep_priv *priv, const char *data, int chn) +{ + int i; + u32 cid, dbase; + struct aca_fw_dma *fw_dma; + struct aca_fw_info *fw_info = to_fw_info(priv); + + fw_info->chan_num = chn; + + for (i = 0; i < fw_info->chan_num; i++) { + fw_dma = (struct aca_fw_dma *)(data + i * sizeof(*fw_dma)); + cid = be32_to_cpu(fw_dma->cid); + dbase = be32_to_cpu(fw_dma->base); + fw_info->adma_desc_base[cid] = dbase; + dev_dbg(priv->dev, "dma channel %d desc base 0x%08x\n", + cid, dbase); + } +} + +static void aca_sram_desc_parse(struct dc_ep_priv *priv, const char *data, + u32 sid) +{ + u32 dbase, dnum; + struct aca_sram_desc *desc_base; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_pdmem_layout *pdmem = to_pdmem_layout(priv); + + desc_base = (struct aca_sram_desc *)data; + dbase = be32_to_cpu(desc_base->dbase); + dnum = be32_to_cpu(desc_base->dnum); + + dev_dbg(priv->dev, "Sec %s desc base 0x%08x, des_num: %d\n", + sec_id_to_str(sid), dbase, dnum); + + switch (sid) { + case ACA_SEC_MEM_TXIN: + mem_layout->txin_host_desc_base = dbase; + mem_layout->txin_host_dnum = dnum; + break; + + case ACA_SEC_MEM_TXOUT: + mem_layout->txout_host_desc_base = dbase; + mem_layout->txout_host_dnum = dnum; + break; + + case ACA_SEC_MEM_RXIN: + mem_layout->rxin_host_desc_base = dbase; + mem_layout->rxin_host_dnum = dnum; + break; + + case ACA_SEC_MEM_RXOUT: + mem_layout->rxout_host_desc_base = dbase; + mem_layout->rxout_host_dnum = dnum; + break; + case ACA_SEC_MEM_TXIN_PDRING: + pdmem->txin_pd_desc_base = dbase; + pdmem->txin_pd_dnum = dnum; + break; + case ACA_SEC_MEM_TXOUT_PDRING: + pdmem->txout_pd_desc_base = dbase; + pdmem->txout_pd_dnum = dnum; + break; + case ACA_SEC_MEM_RXIN_PDRING: + pdmem->rxin_pd_desc_base = dbase; + pdmem->rxin_pd_dnum = dnum; + break; + case ACA_SEC_MEM_RXOUT_PDRING: + pdmem->rxin_pd_desc_base = dbase; + pdmem->rxin_pd_dnum = dnum; + break; + default: + dev_err(priv->dev, "Unknow aca sram section %d\n", sid); + break; + } +} + +static void aca_init_parse(struct dc_ep_priv *priv, const char *data, + u32 sid) +{ + struct aca_fw_param *fw_param = to_aca_fw_param(priv); + struct aca_fw_param *param; + u32 hdr_sz, hdr_addr; + + param = (struct aca_fw_param *)data; + hdr_sz = be32_to_cpu(param->st_sz); + hdr_addr = be32_to_cpu(param->init_addr); + + fw_param->init_addr = hdr_addr; + fw_param->st_sz = hdr_sz; + dev_dbg(priv->dev, "init st size: %d, addr: 0x%x\n", + hdr_sz, hdr_addr); +} + +static void aca_fw_parse(struct dc_ep_priv *priv, const char *data, + const char *fw_base, int fw_num) +{ + int i; + size_t size; + u32 id, offset, addr; + struct aca_int_hdr *hdr; + struct aca_fw_dl_addr *fw_dl = to_fw_addr(priv); + + fw_dl->fw_num = fw_num; + + for (i = 0; i < fw_dl->fw_num; i++) { + hdr = (struct aca_int_hdr *)(data + i * sizeof(*hdr)); + id = be32_to_cpu(hdr->id); + offset = be32_to_cpu(hdr->offset); + size = be32_to_cpu(hdr->size); + addr = be32_to_cpu(hdr->load_addr); + + fw_dl->fw_addr[i].fw_id = id; + fw_dl->fw_addr[i].fw_load_addr = addr; + fw_dl->fw_addr[i].fw_size = size; + fw_dl->fw_addr[i].fw_base = fw_base + offset; + dev_dbg(priv->dev, + "aca %s fw offset 0x%x size %zd loc 0x%x fw base %p\n", + fw_id_to_str(id), offset, size, addr, fw_base + offset); + } +} + +/* -------------------------------------------------------- + | Fixed header (20Bytes) | + --------------------------------------------------------- + | Variable header | + | ie / payload | + |-------------------------------------------------------| + | Actual ACA FW | + --------------------------------------------------------- +*/ +static int aca_section_parse(struct dc_ep_priv *priv, const char *fw_data) +{ + int ret = 0; + u32 fixed_hlen; + u32 var_hlen; + u32 ie_id; + size_t ie_len, ie_hlen, ie_dlen; + u32 fw_hlen; + struct aca_fw_f_hdr *fw_f_hdr; + struct aca_fw_ie *ie_hdr; + struct aca_int_hdr *aca_hdr; + const char *data = fw_data; + const char *aca_fw_data; + struct device *dev = priv->dev; + + fw_f_hdr = (struct aca_fw_f_hdr *)data; + + fw_hlen = be32_to_cpu(fw_f_hdr->hdr_size); + fixed_hlen = sizeof(*fw_f_hdr); + var_hlen = fw_hlen - fixed_hlen; + ie_hlen = sizeof(*ie_hdr); + + /* Record actual ACA fw data pointer */ + aca_fw_data = data + fw_hlen; + + /* Point to variable header and parse them */ + data += fixed_hlen; + + while (var_hlen > ie_hlen) { + /* Variable header information element */ + ie_hdr = (struct aca_fw_ie *)data; + ie_id = be32_to_cpu(ie_hdr->id); + ie_len = be32_to_cpu(ie_hdr->len); + dev_dbg(dev, "Section %s ie_len %zd\n", sec_id_to_str(ie_id), + ie_len); + + /* Variable header data conents */ + data += ie_hlen; + var_hlen -= ie_hlen; + + switch (ie_id) { + case ACA_SEC_HIF: + case ACA_SEC_GNR: + case ACA_SEC_MAC_HT: + ie_dlen = ie_len * sizeof(struct aca_fw_reg); + data += ie_dlen; + var_hlen -= ie_dlen; + + break; + + case ACA_SEC_MEM_TXIN: + case ACA_SEC_MEM_TXOUT: + case ACA_SEC_MEM_RXIN: + case ACA_SEC_MEM_RXOUT: + case ACA_SEC_MEM_TXIN_PDRING: + case ACA_SEC_MEM_TXOUT_PDRING: + case ACA_SEC_MEM_RXIN_PDRING: + case ACA_SEC_MEM_RXOUT_PDRING: + aca_sram_desc_parse(priv, data, ie_id); + ie_dlen = ie_len * sizeof(struct aca_sram_desc); + data += ie_dlen; + var_hlen -= ie_dlen; + break; + + case ACA_SEC_DMA: + if (ie_len > ACA_DMA_CHAN_MAX) { + dev_err(dev, "invalid dma channel %d\n", + ie_len); + ret = -EINVAL; + goto done; + } + aca_dma_parse(priv, data, ie_len); + ie_dlen = ie_len * sizeof(struct aca_fw_dma); + data += ie_dlen; + var_hlen -= ie_dlen; + break; + + case ACA_SEC_FW_INIT: + aca_init_parse(priv, data, ie_id); + ie_dlen = ie_len * sizeof(struct aca_fw_param); + data += ie_dlen; + var_hlen -= ie_dlen; + break; + + case ACA_SEC_FW: + if (ie_len > ACA_FW_MAX) { + dev_err(dev, "Too many aca fws %d\n", ie_len); + ret = -EINVAL; + goto done; + } + aca_fw_parse(priv, data, aca_fw_data, ie_len); + ie_dlen = ie_len * sizeof(*aca_hdr); + data += ie_dlen; + var_hlen -= ie_dlen; + break; + + default: + dev_warn(dev, "Unknown Sec id: %u\n", ie_id); + break; + } + } +done: + return ret; +} + +static int aca_fetch_fw_api(struct dc_ep_priv *priv, const char *name) +{ + int ret; + size_t hdr_len; + const u8 *fw_data; + size_t fw_len; + char dir[8] = {0}; + union fw_ver ver; + union img_soc_type type; + struct device *dev = priv->dev; + struct aca_fw_f_hdr *fw_f_hdr; + struct aca_fw_info *fw_info = to_fw_info(priv); + + sprintf(dir, "%04x", priv->pdev->device); + fw_info->fw = aca_fetch_fw_file(priv, dir, name); + if (IS_ERR(fw_info->fw)) { + dev_err(dev, "Could not fetch firmware file '%s': %ld\n", + name, PTR_ERR(fw_info->fw)); + return PTR_ERR(fw_info->fw); + } + + fw_data = fw_info->fw->data; + fw_len = fw_info->fw->size; + + /* Parse the fixed header part */ + fw_f_hdr = (struct aca_fw_f_hdr *)fw_data; + ver.all = be32_to_cpu(fw_f_hdr->ver); + + dev_info(dev, "ACA fw build %d branch %d major 0x%2x minor 0x%04x\n", + ver.field.build, ver.field.branch, + ver.field.major, ver.field.minor); + + type.all = be32_to_cpu(fw_f_hdr->type); + + if (type.field.img_type > (ACA_IMG_MAX - 1) + || ((type.field.soc_type & ACA_SOC_MASK) == 0)) { + dev_err(dev, "Invalid aca fw img %d soc %d\n", + type.field.img_type, type.field.soc_type); + ret = -EINVAL; + goto err; + } + + soc_type_to_str(type.field.soc_type); + + dev_info(priv->dev, "ACA fw for %s supported SoC type %s\n", + aca_img_type_str[type.field.img_type], soc_str); + + hdr_len = be32_to_cpu(fw_f_hdr->hdr_size); + /* Sanity Check */ + if (fw_len < hdr_len) { + dev_err(dev, "Invalid aca fw hdr len %zd fw len %zd\n", + hdr_len, fw_len); + ret = -EINVAL; + goto err; + } + dev_dbg(dev, "Header size 0x%08x fw size 0x%08x\n", + hdr_len, be32_to_cpu(fw_f_hdr->fw_size)); + dev_dbg(dev, "section number %d\n", + be32_to_cpu(fw_f_hdr->num_section)); + + aca_section_parse(priv, fw_data); + return 0; +err: + dc_aca_free_fw_file(priv); + return ret; +} + +static int aca_fetch_fw(struct dc_ep_priv *priv) +{ + return aca_fetch_fw_api(priv, ACA_FW_FILE); +} + +static int aca_fw_download(struct dc_ep_priv *priv) +{ + int i, j; + u32 val; + size_t size; + u32 id, load_addr; + const char *fw_base; + struct aca_fw_dl_addr *fw_dl = to_fw_addr(priv); + + for (i = 0; i < fw_dl->fw_num; i++) { + id = fw_dl->fw_addr[i].fw_id; + load_addr = fw_dl->fw_addr[i].fw_load_addr; + size = fw_dl->fw_addr[i].fw_size; + fw_base = fw_dl->fw_addr[i].fw_base; + + if (size % 4) { + dev_err(priv->dev, + "aca %s fw size is not a multiple of 4\n", + fw_id_to_str(id)); + return -EINVAL; + } + + for (j = 0; j < size; j += 4) { + val = *((u32 *)(fw_base + j)); + wr32(cpu_to_be32(val), load_addr + j); + } + /* Write flush */ + rd32(load_addr); + #ifdef DEBUG + { + u32 src, dst; + + for (j = 0; j < size; j += 4) { + dst = rd32(load_addr + j); + src = *((u32 *)(fw_base + j)); + if (dst != cpu_to_be32(src)) { + dev_info(priv->dev, + "dst 0x%08x != src 0x%08x\n", dst, src); + return -EIO; + } + } + } + #endif /* DEBUG */ + } + return 0; +} + +static void aca_dma_ctrl_init(struct dc_ep_priv *priv) +{ + u32 val; + struct dc_aca *aca = to_aca(priv); + + /* Global software reset CDMA */ + wr32_mask(0, BIT(CTRL_RST), ADMA_CTRL); + while ((rd32(ADMA_CTRL) & BIT(CTRL_RST))) + ; + + val = rd32(ADMA_ID); + /* Record max dma channels for later usage */ + aca->adma_chans = MS(val, ADMA_ID_CHNR); + val = rd32(ADMA_CTRL); + /* + * Enable Packet Arbitration + * Enable Meta data copy + * Enable Dedicated Descriptor port + */ + val |= BIT(CTRL_PKTARB) | BIT(CTRL_MDC) | BIT(CTRL_DSRAM); + set_mask_bit(val, 1, 1, CTRL_ENBE); /* Enable byte enable */ + set_mask_bit(val, 1, 1, CTRL_DCNF); /* 2DW descriptor format */ + set_mask_bit(val, 1, 1, CTRL_DDBR); /* Descriptor read back */ + set_mask_bit(val, 1, 1, CTRL_DRB); /* Dynamic burst read */ + wr32(val, ADMA_CTRL); + + /* Polling cnt cfg */ + wr32(ADMA_CPOLL_EN | SM(ADMA_DEFAULT_POLL, ADMA_CPOLL_CNT), + ADMA_CPOLL); +} + +static void aca_dma_port_init(struct dc_ep_priv *priv) +{ + u32 val; + + /* Only one port /port 0 */ + wr32(0, ADMA_PS); + val = rd32(ADMA_PCTRL); + set_mask_bit(val, 1, 1, PCTRL_RXBL16); + set_mask_bit(val, 1, 1, PCTRL_TXBL16); + set_mask_bit(val, 0, 3, PCTRL_RXBL); + set_mask_bit(val, 0, 3, PCTRL_TXBL); + + set_mask_bit(val, 0, 3, PCTRL_TXENDI); + set_mask_bit(val, 0, 3, PCTRL_RXENDI); + wr32(val, ADMA_PCTRL); +} + +static void aca_dma_ch_init(struct dc_ep_priv *priv, u32 cid, + u32 dbase, u32 dlen) +{ + /* Select channel */ + wr32(cid, ADMA_CS); + + /* Reset Channel */ + wr32_mask(0, BIT(CCTRL_RST), ADMA_CCTRL); + while ((rd32(ADMA_CCTRL) & BIT(CCTRL_RST))) + ; + + /* Set descriptor list base and length */ + wr32(dbase, ADMA_CDBA); + wr32(dlen, ADMA_CDLEN); + + /*Clear Intr */ + wr32(ADMA_CI_ALL, ADMA_CIS); + /* Enable Intr */ + wr32(ADMA_CI_ALL, ADMA_CIE); + + /* Enable Channel */ + wr32_mask(0, BIT(CCTRL_ONOFF), ADMA_CCTRL); + mb(); +} + +static void aca_dma_ch_off(struct dc_ep_priv *priv) +{ + int i; + struct dc_aca *aca = to_aca(priv); + + /* Shared between OS and ACA FW. Stop ACA first */ + for (i = 0; i < aca->adma_chans; i++) { + wr32(i, ADMA_CS); + wr32_mask(BIT(CCTRL_ONOFF), 0, ADMA_CCTRL); + while (rd32(ADMA_CCTRL) & BIT(CCTRL_ONOFF)) + ; + } + dev_dbg(priv->dev, "aca dma channel done\n"); +} + +static void aca_xbar_ia_reject_set(struct dc_ep_priv *priv, int ia_id) +{ + u32 val; + int timeout = 1000; + struct device *dev = priv->dev; + + /* Set reject bit */ + wr32(XBAR_CTRL_REJECT, ACA_AGENT_CTRL(ia_id)); + + /* Poll burst, readex, resp_waiting, req_active */ + val = XBAR_STAT_REQ_ACTIVE | XBAR_STAT_RESP_WAITING + | XBAR_STAT_BURST | XBAR_STAT_READEX; + while (--timeout && !!(rd32(ACA_AGENT_STATUS(ia_id)) & val)) + udelay(1); + + if (timeout <= 0) { + dev_dbg(dev, + "ACA XBAR IA: %d reset timeout, pending on 0x%x\n", + ia_id, rd32(ACA_AGENT_STATUS(ia_id))); + return; + } +} + +static void aca_xbar_ia_reject_clr(struct dc_ep_priv *priv, int ia_id) +{ + u32 val; + + /* Check reject bit */ + val = rd32(ACA_AGENT_CTRL(ia_id)); + if ((val & XBAR_CTRL_REJECT) == 0) + return; + + /* Clear reject bit */ + val &= ~XBAR_CTRL_REJECT; + wr32(val, ACA_AGENT_CTRL(ia_id)); + rd32(ACA_AGENT_CTRL(ia_id)); +} + +static void aca_xbar_ia_reset(struct dc_ep_priv *priv, int ia_id) +{ + /* ACA IA reset */ + wr32(XBAR_CTRL_CORE_RESET, ACA_AGENT_CTRL(ia_id)); + + /* Read till status become 1 */ + while ((rd32(ACA_AGENT_STATUS(ia_id)) & XBAR_STAT_CORE_RESET) == 0) + ; + + /* Clear the IA Reset signal */ + wr32(0, ACA_AGENT_CTRL(ia_id)); + + /* Read till status become 0 */ + while ((rd32(ACA_AGENT_STATUS(ia_id)) & XBAR_STAT_CORE_RESET) == 1) + ; + + dev_dbg(priv->dev, "ACA XBAR IA(%d) reset done\n", ia_id); +} + +void dc_aca_shutdown(struct dc_ep_priv *priv) +{ + struct dc_aca *aca = to_aca(priv); + + if (aca->initialized) { + aca_xbar_ia_reset(priv, ACA_ACC_IA04); + aca_xbar_ia_reset(priv, ACA_M_IA06); + } +} + +static void aca_dma_init(struct dc_ep_priv *priv) +{ + int i; + struct aca_fw_info *fw_info = to_fw_info(priv); + + aca_dma_ctrl_init(priv); + aca_dma_port_init(priv); + + for (i = 0; i < fw_info->chan_num; i++) { + aca_dma_ch_init(priv, i, + fw_info->adma_desc_base[i] | priv->phymem, + DESC_NUM_PER_CH); + } + + dev_dbg(priv->dev, "aca dma init done\n"); +} + +static void aca_basic_init(struct dc_ep_priv *priv) +{ + u32 addr, mask; + + /* Low 32 is RX, High 32 is TX */ + wr32(0x1, UMT_ORDER_CFG); + /* TXIN/TXOUT/RXIN/RXOUT All Controlled by Genrisc */ + wr32(0xF, HOST_TYPE); + /* Enable Host Gate CLK */ + wr32(0x4000, HT_GCLK_ENABLE); + /* Host Page/MASK */ + mask = ~priv->memsize + 1; + addr = mask | ((priv->phymem & mask) >> 16); + wr32(addr, AHB_ARB_HP_REG); + wr32(addr, OCP_ARB_ACC_PAGE_REG); + /* Stop all functions first */ + wr32(0, GNRC_EN_TASK_BITMAP); + + /* Enable XBAR */ + aca_xbar_ia_reject_clr(priv, ACA_ACC_IA04); + aca_xbar_ia_reject_clr(priv, ACA_M_IA06); + + dev_dbg(priv->dev, "aca basic config done\n"); +} + +static int aca_hif_param_init(struct dc_ep_priv *priv) +{ + struct dc_aca *aca = to_aca(priv); + + aca->hif_params = kzalloc(sizeof(struct aca_hif_params), GFP_KERNEL); + if (!aca->hif_params) + return -ENOMEM; + aca->hif_params->task_mask = 0x0000000F; + dev_dbg(priv->dev, "%s\n", __func__); + return 0; +} + +static void aca_hif_param_init_done(struct dc_ep_priv *priv) +{ + u32 addr; + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_fw_param *fw_param = to_aca_fw_param(priv); + + /* wr32(ACA_HIF_PARAM_ADDR, ACA_HIF_LOC_POS);*/ + /* addr = rd32(ACA_HIF_LOC_POS);*/ + + addr = fw_param->init_addr; + dev_dbg(priv->dev, "init_addr: %x\n", addr); + memcpy_toio(priv->mem + addr, hif_params, sizeof(*hif_params)); + kzfree(hif_params); + dev_dbg(priv->dev, "%s\n", __func__); +} + +static bool aca_hif_param_init_check(struct dc_ep_priv *priv) +{ + u32 addr; + int timeout = ACA_LOOP_CNT; + u32 offset = offsetof(struct aca_hif_params, magic); + struct aca_fw_param *fw_param = to_aca_fw_param(priv); + + /* addr = rd32(ACA_HIF_LOC_POS);*/ + addr = fw_param->init_addr; + while (--timeout && (rd32(addr + offset) != ACA_MAGIC)) + udelay(1); + + if (timeout <= 0) { + dev_err(priv->dev, "aca hif params init failed\n"); + return false; + } + + return true; +} + +static void aca_txin_init(struct dc_ep_priv *priv, + struct aca_cfg_param *aca_txin) +{ + u32 val = 0; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_hif_param *txin_param = &hif_params->txin; + + if (aca_txin->byteswap) + val = BYTE_SWAP_EN; + + val |= (aca_txin->hd_size_in_dw - 1) + | SM((aca_txin->pd_size_in_dw - 1), PD_DESC_IN_DW); + wr32(val, TXIN_CONV_CFG); + + /* SoC cumulative counter address */ + wr32(aca_txin->soc_cmlt_cnt_addr, GNRC_TXIN_CMLT_CNT_ADDR); + + + /* SoC descriptors */ + txin_param->soc_desc_base = aca_txin->soc_desc_base; + txin_param->soc_desc_num = aca_txin->soc_desc_num; + + /* Ping/pong buffer */ + txin_param->pp_buf_base = priv->phymem + + mem_layout->txin_host_desc_base; + + txin_param->pp_buf_num = mem_layout->txin_host_dnum; + + /* PD ring */ + txin_param->pd_desc_base = priv->phymem + + aca_txin->pd_desc_base; + txin_param->pd_desc_num = aca_txin->pd_desc_num; + + dev_dbg(priv->dev, "aca txin init done\n"); +} + +static void aca_txout_init(struct dc_ep_priv *priv, + struct aca_cfg_param *aca_txout) +{ + u32 val = 0; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_hif_param *txout_param = &hif_params->txout; + + if (aca_txout->byteswap) + val = BYTE_SWAP_EN; + + val |= (aca_txout->hd_size_in_dw - 1) + | SM((aca_txout->pd_size_in_dw - 1), PD_DESC_IN_DW); + wr32(val, TXOUT_CONV_CFG); + + /* SoC Ring size */ + val = aca_txout->soc_desc_num; + wr32(val, TXOUT_RING_CFG); + + /* SoC cumulative counter address */ + wr32(aca_txout->soc_cmlt_cnt_addr, GNRC_TXOUT_CMLT_CNT_ADDR); + /* SoC descriptors */ + txout_param->soc_desc_base = aca_txout->soc_desc_base; + txout_param->soc_desc_num = aca_txout->soc_desc_num; + + /* Ping/pong buffer */ + txout_param->pp_buf_base = priv->phymem + +mem_layout->txout_host_desc_base; + + txout_param->pp_buf_num = mem_layout->txout_host_dnum; + + /* PD ring */ + txout_param->pd_desc_base = priv->phymem + + aca_txout->pd_desc_base; + txout_param->pd_desc_num = aca_txout->pd_desc_num; + + txout_param->pd_desc_threshold = aca_txout->pp_buf_desc_num; + + dev_dbg(priv->dev, "aca txout init done\n"); +} + +static void aca_rxin_init(struct dc_ep_priv *priv, + struct aca_cfg_param *aca_rxin) +{ + u32 val = 0; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_hif_param *rxin_param = &hif_params->rxin; + + if (aca_rxin->byteswap) + val = BYTE_SWAP_EN; + + val |= (aca_rxin->hd_size_in_dw - 1) + | SM((aca_rxin->pd_size_in_dw - 1), PD_DESC_IN_DW); + wr32(val, RXIN_CONV_CFG); + + /* SoC cumulative counter address */ + wr32(aca_rxin->soc_cmlt_cnt_addr, GNRC_RXIN_CMLT_CNT_ADDR); + + /* RXIN may not be used */ + if (!(aca_rxin->soc_desc_base)) + goto __RXIN_DONE; + /* SoC descriptors */ + rxin_param->soc_desc_base = aca_rxin->soc_desc_base; + rxin_param->soc_desc_num = aca_rxin->soc_desc_num; + + /* Ping/pong buffer */ + rxin_param->pp_buf_base = (u32)priv->phymem + + mem_layout->rxin_host_desc_base; + + rxin_param->pp_buf_num = mem_layout->rxin_host_dnum; + + /* PD ring */ + rxin_param->pd_desc_base = (u32)priv->phymem + + aca_rxin->pd_desc_base; + rxin_param->pd_desc_num = aca_rxin->pd_desc_num; + + rxin_param->pd_desc_threshold = aca_rxin->pp_buf_desc_num; + +__RXIN_DONE: + dev_dbg(priv->dev, "aca rxin init done\n"); +} + +static void aca_rxout_init(struct dc_ep_priv *priv, + struct aca_cfg_param *aca_rxout) +{ + u32 val = 0; + struct aca_mem_layout *mem_layout = to_mem_layout(priv); + struct aca_hif_params *hif_params = to_hif_params(priv); + struct aca_hif_param *rxout_param = &hif_params->rxout; + + if (aca_rxout->byteswap) + val = BYTE_SWAP_EN; + + val |= (aca_rxout->hd_size_in_dw - 1) + | SM((aca_rxout->pd_size_in_dw - 1), PD_DESC_IN_DW); + wr32(val, RXOUT_CONV_CFG); + + /* SoC Ring size */ + val = aca_rxout->soc_desc_num; + wr32(val, RXOUT_RING_CFG); + + /* SoC cumulative counter address */ + wr32(aca_rxout->soc_cmlt_cnt_addr, GNRC_RXOUT_CMLT_CNT_ADDR); + /* SoC descriptors */ + rxout_param->soc_desc_base = aca_rxout->soc_desc_base; + rxout_param->soc_desc_num = aca_rxout->soc_desc_num; + + /* Ping/pong buffer */ + rxout_param->pp_buf_base = (u32)priv->phymem + + mem_layout->rxout_host_desc_base; + + rxout_param->pp_buf_num = mem_layout->rxout_host_dnum; + + /* PD ring */ + rxout_param->pd_desc_base = (u32)priv->phymem + + aca_rxout->pd_desc_base; + rxout_param->pd_desc_num = aca_rxout->pd_desc_num; + + rxout_param->pd_desc_threshold = aca_rxout->pp_buf_desc_num; + dev_dbg(priv->dev, "aca rxout init done\n"); +} + +static void aca_mdm_init(struct dc_ep_priv *priv, struct aca_modem_param *mdm) +{ + struct aca_proj_param *param; + + if (!mdm) + return; + + param = &mdm->mdm_txout; + wr32(param->stat | priv->phymem, GNRC_TXOUT_TGT_STAT); + wr32(param->pd | priv->phymem, GNRC_TXOUT_TGT_PD_OFF); + wr32(param->acc_cnt | priv->phymem, GNRC_TXOUT_TGT_ACCM_CNT); + + param = &mdm->mdm_rxin; + wr32(param->stat | priv->phymem, GNRC_RXIN_TGT_STAT); + wr32(param->pd | priv->phymem, GNRC_RXIN_TGT_PD_OFF); + wr32(param->acc_cnt | priv->phymem, GNRC_RXIN_TGT_ACCM_CNT); + + param = &mdm->mdm_rxout; + wr32(param->stat | priv->phymem, GNRC_RXOUT_TGT_STAT); + wr32(param->pd | priv->phymem, GNRC_RXOUT_TGT_PD_OFF); + wr32(param->acc_cnt | priv->phymem, GNRC_RXOUT_TGT_ACCM_CNT); + dev_dbg(priv->dev, "aca mdm init done\n"); +} + +static void dc_aca_clk_on(struct dc_ep_priv *priv) +{ + dc_ep_clk_on(priv, PMU_ADMA); +} + +static void dc_aca_clk_off(struct dc_ep_priv *priv) +{ + dc_ep_clk_off(priv, PMU_ADMA); +} + +static void dc_aca_reset(struct dc_ep_priv *priv) +{ + dc_ep_reset_device(priv, RST_ACA_DMA | RST_ACA_HOSTIF); +} + +static void aca_mem_clear(struct dc_ep_priv *priv) +{ + struct aca_fw_dl_addr *fw_dl = to_fw_addr(priv); + + memset_io(priv->mem + fw_dl->fw_addr[0].fw_load_addr, + 0, ACA_ACC_FW_SIZE); + memset_io(priv->mem + ACA_SRAM_BASE, 0, ACA_SRAM_SIZE); +} + +int dc_aca_start(struct dc_ep_priv *priv, u32 func, int start) +{ + if (!func) + return -EINVAL; + + wr32_mask(0, func, GNRC_EN_TASK_BITMAP); + + /* Only do if requested by caller */ + if (start) { + wr32(0x1, GNRC_START_OP); /* Any write will trigger */ + rd32(GNRC_START_OP); + if (!aca_hif_param_init_check(priv)) + return -EIO; + } + return 0; +} + +static void aca_sw_reset(struct dc_ep_priv *priv) +{ + u32 val = SW_RST_GENRISC | SW_RST_HOSTIF_REG | SW_RST_RXIN + | SW_RST_RXOUT | SW_RST_TXIN | SW_RST_TXOUT; + + wr32(val, HT_SW_RST_ASSRT); + udelay(1); + wr32(val, HT_SW_RST_RELEASE); + wmb(); +} + +int dc_aca_stop(struct dc_ep_priv *priv, u32 *func, int reset) +{ + u32 val = *func; + u32 reg; + + if (!val) + return 0; + + *func = 0; + + /* Only do it if reset is required. Otherwise, pending is fine */ + if (reset) { + if (val & ACA_TXIN_EN) { + reg = rd32(TXIN_COUNTERS); + if (MS(reg, ACA_PENDING_JOB) + || (MS(reg, ACA_AVAIL_BUF) != ACA_PP_BUFS)) { + *func = ACA_TXIN_EN; + return -EBUSY; + } + } + + if (val & ACA_TXOUT_EN) { + reg = rd32(TXOUT_COUNTERS); + if (MS(reg, ACA_PENDING_JOB) + || (MS(reg, ACA_AVAIL_BUF) != ACA_PP_BUFS)) { + *func = ACA_TXOUT_EN; + return -EBUSY; + } + } + + + if (val & ACA_RXIN_EN) { + reg = rd32(RXIN_COUNTERS); + if (MS(reg, ACA_PENDING_JOB) + || (MS(reg, ACA_AVAIL_BUF) != ACA_PP_BUFS)) { + *func = ACA_RXIN_EN; + return -EBUSY; + } + } + + if (val & ACA_RXOUT_EN) { + reg = rd32(RXOUT_COUNTERS); + if (MS(reg, ACA_PENDING_JOB) + || (MS(reg, ACA_AVAIL_BUF) != ACA_PP_BUFS)) { + *func = ACA_RXOUT_EN; + return -EBUSY; + } + } + } + + wr32_mask(val, 0, GNRC_EN_TASK_BITMAP); + + if (reset) { + aca_dma_ch_off(priv); + aca_xbar_ia_reject_set(priv, ACA_ACC_IA04); + aca_xbar_ia_reject_set(priv, ACA_M_IA06); + aca_sw_reset(priv); + } + return 0; +} + +#ifdef CONFIG_SOC_TYPE_XWAY +static void aca_grx330_init(struct dc_ep_priv *priv) +{ + wr32(0x0044001E, TXIN_CFG1); + wr32(0x0040041F, TXIN_CFG2); + wr32(0x007FE020, TXIN_CFG3); + + wr32(0x0044001F, TXOUT_CFG1); + wr32(0x0040041F, TXOUT_CFG2); + wr32(0x007BE020, TXOUT_CFG3); + + wr32(0x0044001F, RXOUT_CFG1); + wr32(0x0040041F, RXOUT_CFG2); + wr32(0x007BE020, RXOUT_CFG3); + + wr32(0x0044001E, RXIN_CFG1); + wr32(0x0040041F, RXIN_CFG2); + wr32(0x007FE020, RXIN_CFG3); + + wr32(0x1, TXIN_DST_OWWBIT_CFG4); + wr32(0x1, TXOUT_DST_OWWBIT_CFG4); + wr32(0x1, RXOUT_SRC_OWNBIT_CFG3); + wr32(0x1, RXIN_SRC_OWNBIT_CFG3); + + wr32(0x0, GNRC_TXIN_BUF_PREFILL); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x4); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x8); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0xc); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x10); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x14); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x18); + wr32(0x0, GNRC_TXIN_BUF_PREFILL + 0x1c); +} +#endif + +int dc_aca_init(struct dc_ep_priv *priv, struct aca_param *param, + struct aca_modem_param *mdm) +{ + int ret; + struct dc_aca *aca = to_aca(priv); + + dc_aca_clk_on(priv); + dc_aca_reset(priv); + + ret = aca_fetch_fw(priv); + if (ret) { + dev_err(priv->dev, + "could not fetch firmware files %d\n", ret); + dc_aca_clk_off(priv); + return ret; + } + + aca_mem_clear(priv); + aca_dma_init(priv); + aca_basic_init(priv); + aca_fw_download(priv); + aca_hif_param_init(priv); + aca_txin_init(priv, ¶m->aca_txin); + aca_txout_init(priv, ¶m->aca_txout); + aca_rxout_init(priv, ¶m->aca_rxout); + aca_rxin_init(priv, ¶m->aca_rxin); + aca_hif_param_init_done(priv); + aca_mdm_init(priv, mdm); +#ifdef CONFIG_SOC_TYPE_XWAY + aca_grx330_init(priv); +#endif + aca->initialized = true; + dev_info(priv->dev, "aca init done\n"); + return 0; +} + +static int aca_max_gpio(struct dc_ep_priv *priv) +{ + return fls(rd32(PADC_AVAIL)); +} + +void dc_aca_info_init(struct dc_ep_priv *priv) +{ + struct dc_aca *aca = to_aca(priv); + + aca->initialized = false; + spin_lock_init(&aca->clk_lock); + spin_lock_init(&aca->rcu_lock); + mutex_init(&aca->pin_lock); + aca->max_gpio = aca_max_gpio(priv); +} + +#define ACA_ENDIAN_ADDR(addr, endian) \ +{ \ + if (endian == ACA_BIG_ENDIAN) \ + return addr##_BE; \ + else \ + return addr; \ +} + +u32 aca_umt_msg_addr(struct dc_ep_priv *priv, u32 endian, u32 type) +{ + switch (type) { + case ACA_TXIN: + ACA_ENDIAN_ADDR(TXIN_HD_ACCUM_ADD, endian); + case ACA_RXIN: + ACA_ENDIAN_ADDR(RXIN_HD_ACCUM_ADD, endian); + case ACA_TXOUT: + ACA_ENDIAN_ADDR(TXOUT_HD_ACCUM_SUB, endian); + case ACA_RXOUT: + ACA_ENDIAN_ADDR(RXOUT_HD_ACCUM_SUB, endian); + default: + ACA_ENDIAN_ADDR(RXIN_HD_ACCUM_ADD, endian); + }; +} + +void dc_aca_event_addr_get(struct dc_ep_priv *priv, + struct aca_event_reg_addr *regs) +{ + regs->txin_acc_sub = TXIN_ACA_ACCUM_SUB; + regs->txout_acc_add = TXOUT_ACA_ACCUM_ADD; + regs->rxin_acc_sub = RXIN_ACA_ACCUM_SUB; + regs->rxout_acc_add = RXOUT_ACA_ACCUM_ADD; +} + +void dc_aca_txin_sub_ack(struct dc_ep_priv *priv, u32 val) +{ + wr32(val, TXIN_ACA_ACCUM_SUB); +} + +u32 dc_aca_txin_hd_cnt(struct dc_ep_priv *priv) +{ + return rd32(TXIN_ACA_HD_ACC_CNT); +} + diff --git a/package/kernel/lantiq/vrx518_ep/src/aca.h b/package/kernel/lantiq/vrx518_ep/src/aca.h new file mode 100644 index 00000000000..10f2ecb4c16 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/aca.h @@ -0,0 +1,481 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef ACA_H +#define ACA_H + +#define HOST_IF_BASE 0x50000 +#define ACA_CORE_BASE 0x50800 +#define GENRISC_IRAM_BASE 0x58000 +#define GENRISC_SPRAM_BASE 0x5C000 +#define GENRISC_BASE 0x5D000 +#define MAC_HT_EXT_BASE 0x5D400 +#define ACA_SRAM_BASE 0x100000 +#define ACA_SRAM_SIZE 0x2000 /* Project specific */ +#define ACA_HOSTIF_ADDR_SHIFT 2 + +#define ACA_HOSTIF_ADDR(addr) ((addr) >> ACA_HOSTIF_ADDR_SHIFT) + +#define ACA_HIF_LOC_POS 0x100060 +#define ACA_HIF_PARAM_ADDR 0x100064 +#define ACA_ACC_FW_SIZE 0x400 +#define ACA_LOOP_CNT 1000 + +/* TODO: change name after karthik explained */ +#define TXIN_DST_OWNBIT 0xC4 +#define TXOUT_DST_OWNBIT 0x1C4 +#define RXOUT_SRC_OWNBIT 0x3C4 +#define RXIN_DST_OWNBIT 0x2C4 + +/* Genrisc Internal Host Descriptor(Ping/Pong) decided by ACA fw header */ +/* ACA Core */ +#define ACA_CORE_REG(X) (ACA_CORE_BASE + (X)) +#define TXIN_CFG1 ACA_CORE_REG(0x0) +#define TXIN_CFG2 ACA_CORE_REG(0x4) +#define TXIN_CFG3 ACA_CORE_REG(0x8) +#define TXIN_DST_OWWBIT_CFG4 ACA_CORE_REG(TXIN_DST_OWNBIT) + +#define TXOUT_CFG1 ACA_CORE_REG(0x100) +#define TXOUT_CFG2 ACA_CORE_REG(0x104) +#define TXOUT_CFG3 ACA_CORE_REG(0x108) +#define TXOUT_DST_OWWBIT_CFG4 ACA_CORE_REG(TXOUT_DST_OWNBIT) + +#define RXOUT_CFG1 ACA_CORE_REG(0x300) +#define RXOUT_CFG2 ACA_CORE_REG(0x304) +#define RXOUT_CFG3 ACA_CORE_REG(0x308) +#define RXOUT_SRC_OWNBIT_CFG3 ACA_CORE_REG(RXOUT_SRC_OWNBIT) + +#define RXIN_CFG1 ACA_CORE_REG(0x200) +#define RXIN_CFG2 ACA_CORE_REG(0x204) +#define RXIN_CFG3 ACA_CORE_REG(0x208) +#define RXIN_SRC_OWNBIT_CFG3 ACA_CORE_REG(RXIN_DST_OWNBIT) + +/* Genrisc */ +#define GNRC_REG(X) (GENRISC_BASE + (X)) +#define GNRC_STOP_OP GNRC_REG(0x60) +#define GNRC_CONTINUE_OP GNRC_REG(0x64) +#define GNRC_START_OP GNRC_REG(0x90) + +/* HOST Interface Register */ +#define HOST_IF_REG(X) (HOST_IF_BASE + (X)) +#define HD_DESC_IN_DW 0x7u +#define HD_DESC_IN_DW_S 0 +#define PD_DESC_IN_DW 0x70u +#define PD_DESC_IN_DW_S 4 +#define BYTE_SWAP_EN BIT(28) + +#define TXIN_CONV_CFG HOST_IF_REG(0x14) +#define TXOUT_CONV_CFG HOST_IF_REG(0x18) +#define RXIN_CONV_CFG HOST_IF_REG(0x1C) +#define RXOUT_CONV_CFG HOST_IF_REG(0x20) + +#define TXIN_COUNTERS HOST_IF_REG(0x44) +#define TXOUT_COUNTERS HOST_IF_REG(0x48) +#define RXIN_COUNTERS HOST_IF_REG(0x4c) +#define RXOUT_COUNTERS HOST_IF_REG(0x50) + +#define TXOUT_RING_CFG HOST_IF_REG(0x98) +#define RXOUT_RING_CFG HOST_IF_REG(0x9C) + +#define ACA_PENDING_JOB 0x00000300 +#define ACA_PENDING_JOB_S 8 +#define ACA_AVAIL_BUF 0x00030000 +#define ACA_AVAIL_BUF_S 16 +#define ACA_PP_BUFS 2 + +#define HOST_TYPE HOST_IF_REG(0xA0) +#define TXOUT_COUNTERS_UPDATE HOST_IF_REG(0xAC) +#define RXOUT_COUNTERS_UPDATE HOST_IF_REG(0xB4) +#define RXIN_HD_ACCUM_ADD HOST_IF_REG(0xC8) /* UMT Message trigger */ +#define TXIN_HD_ACCUM_ADD HOST_IF_REG(0xCC) /* UMT Message trigger */ +#define RXOUT_HD_ACCUM_ADD HOST_IF_REG(0xD0) +#define TXOUT_HD_ACCUM_ADD HOST_IF_REG(0xD4) +#define RXOUT_ACA_ACCUM_ADD HOST_IF_REG(0xE0) /* PPE FW tigger */ +#define TXOUT_ACA_ACCUM_ADD HOST_IF_REG(0xE4) /* PPE FW tigger */ +#define RXOUT_HD_ACCUM_SUB HOST_IF_REG(0xF8) +#define TXOUT_HD_ACCUM_SUB HOST_IF_REG(0xFC) +#define RXIN_ACA_ACCUM_SUB HOST_IF_REG(0x100) +#define TXIN_ACA_ACCUM_SUB HOST_IF_REG(0x104) +#define TXIN_ACA_HD_ACC_CNT HOST_IF_REG(0x11C) +#define UMT_ORDER_CFG HOST_IF_REG(0x234) +#define RXIN_HD_ACCUM_ADD_BE HOST_IF_REG(0x250) +#define TXIN_HD_ACCUM_ADD_BE HOST_IF_REG(0x254) +#define RXOUT_HD_ACCUM_SUB_BE HOST_IF_REG(0x268) +#define TXOUT_HD_ACCUM_SUB_BE HOST_IF_REG(0x26c) + +/* MAC_HT_EXTENSION Register */ +#define MAC_HT_EXT_REG(X) (MAC_HT_EXT_BASE + (X)) + +#define HT_GCLK_ENABLE MAC_HT_EXT_REG(0) +#define HT_SW_RST_RELEASE MAC_HT_EXT_REG(0x4) +#define HT_SW_RST_ASSRT MAC_HT_EXT_REG(0x1C) +#define SW_RST_GENRISC BIT(14) +#define SW_RST_RXOUT BIT(26) +#define SW_RST_RXIN BIT(27) +#define SW_RST_TXOUT BIT(28) +#define SW_RST_TXIN BIT(29) +#define SW_RST_HOSTIF_REG BIT(30) +#define OCP_ARB_ACC_PAGE_REG MAC_HT_EXT_REG(0x1C4) +#define AHB_ARB_HP_REG MAC_HT_EXT_REG(0x1C8) + +/* Genrisc FW Configuration */ +#define GNRC_SPRAM_REG(X) (GENRISC_SPRAM_BASE + (X)) + +/* TX IN */ +#define GNRC_TXIN_TGT_STAT GNRC_SPRAM_REG(0x04) +#define GNRC_TXIN_TGT_PD_OFF GNRC_SPRAM_REG(0x08) +#define GNRC_TXIN_TGT_ACCM_CNT GNRC_SPRAM_REG(0x0C) + +/* TX OUT */ +#define GNRC_TXOUT_TGT_STAT GNRC_SPRAM_REG(0x10) +#define GNRC_TXOUT_TGT_PD_OFF GNRC_SPRAM_REG(0x14) +#define GNRC_TXOUT_TGT_ACCM_CNT GNRC_SPRAM_REG(0x18) + +/* RX IN */ +#define GNRC_RXIN_TGT_STAT GNRC_SPRAM_REG(0x1C) +#define GNRC_RXIN_TGT_PD_OFF GNRC_SPRAM_REG(0x20) +#define GNRC_RXIN_TGT_ACCM_CNT GNRC_SPRAM_REG(0x24) + +/* RX OUT XXX not consistent */ +#define GNRC_RXOUT_TGT_STAT GNRC_SPRAM_REG(0x28) +#define GNRC_RXOUT_TGT_PD_OFF GNRC_SPRAM_REG(0x2C) +#define GNRC_RXOUT_TGT_ACCM_CNT GNRC_SPRAM_REG(0x30) + +/* 4 Ring 8 UMT case SoC cumulative counter address configuration */ +#define GNRC_TXIN_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x34) +#define GNRC_TXOUT_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x38) +#define GNRC_RXOUT_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x3C) +#define GNRC_RXIN_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x40) + + +#define GNRC_SOURCE_TXIN_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x54) +#define GNRC_SOURCE_TXOUT_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x58) +#define GNRC_SOURCE_RXOUT_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x5c) +#define GNRC_SOURCE_RXIN_CMLT_CNT_ADDR GNRC_SPRAM_REG(0x60) + +/* Txin index prefill */ +#define GNRC_TXIN_BUF_PREFILL GNRC_SPRAM_REG(0x44) +/* Task enable bitmap */ +#define GNRC_EN_TASK_BITMAP GNRC_SPRAM_REG(0x64) + +#define ACA_SRAM_REG(X) (ACA_SRAM_BASE + (X)) +#define ACA_TXOUT_PING_BUFFER_START ACA_SRAM_REG(0x1528) + + +/* XBAR SSX0 */ +#define ACA_SSX0_BASE 0x180000 +#define ACA_SSX0_IA_BASE(id) (ACA_SSX0_BASE + (((id) - 1) << 10)) +#define ACA_AGENT_CTRL(id) (ACA_SSX0_IA_BASE(id) + 0x20) +#define ACA_AGENT_STATUS(id) (ACA_SSX0_IA_BASE(id) + 0x28) + +#define XBAR_CTRL_CORE_RESET BIT(0) +#define XBAR_CTRL_REJECT BIT(4) + +#define XBAR_STAT_CORE_RESET BIT(0) +#define XBAR_STAT_REQ_ACTIVE BIT(4) +#define XBAR_STAT_RESP_WAITING BIT(5) +#define XBAR_STAT_BURST BIT(6) +#define XBAR_STAT_READEX BIT(7) + +enum { + ACA_ACC_IA04 = 4, + ACA_M_IA06 = 6, +}; + +/* Should be passed from ACA FW header */ +#define DESC_NUM_PER_CH 1 + +/* ACA DMA REG */ +#define ACA_DMA_BASE 0x60000 + +#define ACA_DMA_REG(X) (ACA_DMA_BASE + (X)) +#define ADMA_CLC ACA_DMA_REG(0x0) +#define ADMA_ID ACA_DMA_REG(0x8) +#define ADMA_CTRL ACA_DMA_REG(0x10) +#define ADMA_CPOLL ACA_DMA_REG(0x14) + +#define ADMA_ID_REV 0x1Fu +#define ADMA_ID_REV_S 0 +#define ADMA_ID_ID 0xFF00u +#define ADMA_ID_ID_S 8 +#define ADMA_ID_PRTNR 0xF0000u +#define ADMA_ID_PRTNR_S 16 +#define ADMA_ID_CHNR 0x7F00000u +#define ADMA_ID_CHNR_S 20 + +#define ADMA_CPOLL_EN BIT(31) + +#define ADMA_CPOLL_CNT 0xFFF0u +#define ADMA_CPOLL_CNT_S 4 +#define ADMA_DEFAULT_POLL 24 +#define ADMA_CS ACA_DMA_REG(0x18) +#define ADMA_CCTRL ACA_DMA_REG(0x1C) +#define ADMA_CDBA ACA_DMA_REG(0x20) +#define ADMA_CDLEN ACA_DMA_REG(0x24) +#define ADMA_CIS ACA_DMA_REG(0x28) +#define ADMA_CIE ACA_DMA_REG(0x2C) + +#define ADMA_CI_EOP BIT(1) +#define ADMA_CI_DUR BIT(2) +#define ADMA_CI_DESCPT BIT(3) +#define ADMA_CI_CHOFF BIT(4) +#define ADMA_CI_RDERR BIT(5) +#define ADMA_CI_ALL (ADMA_CI_EOP | ADMA_CI_DUR | ADMA_CI_DESCPT\ + | ADMA_CI_CHOFF | ADMA_CI_RDERR) + +#define ADMA_CDPTNRD ACA_DMA_REG(0x34) +#define ADMA_PS ACA_DMA_REG(0x40) +#define ADMA_PCTRL ACA_DMA_REG(0x44) + +/* DMA CCTRL BIT */ +#define CCTRL_RST 1 /* Channel Reset */ +#define CCTRL_ONOFF 0 /* Channel On/Off */ + +/* DMA CTRL BIT */ +#define CTRL_PKTARB 31 /* Packet Arbitration */ +#define CTRL_MDC 15 /* Meta data copy */ +#define CTRL_DDBR 14 /* Dynamic Burst */ +#define CTRL_DCNF 13 /* Descriptor Length CFG*/ +#define CTRL_ENBE 9 /* Byte Enable */ +#define CTRL_DRB 8 /* Descriptor read back */ +#define CTRL_DSRAM 1 /* Dedicated Descriptor Access port Enable */ +#define CTRL_RST 0 /* Global Reset */ + +/* DMA PORT BIT */ +#define PCTRL_FLUSH 16 +#define PCTRL_TXENDI 10 /* TX DIR Endianess */ +#define PCTRL_RXENDI 8 /* RX DIR Endianess */ +#define PCTRL_TXBL 4 /* TX burst 2/4/8 */ +#define PCTRL_RXBL 2 /* RX burst 2/4/8 */ +#define PCTRL_TXBL16 1 /* TX burst of 16 */ +#define PCTRL_RXBL16 0 /* RX burst of 16 */ + +/*DMA ID BIT */ +#define ID_CHNR 20 /* Channel Number */ + +/*DMA POLLING BIT */ +#define POLL_EN 31 /* Polling Enable */ +#define POLL_CNT 4 /* Polling Counter */ + +#define ACA_DMA_CHAN_MAX 12 + +enum aca_sec_id { + ACA_SEC_HIF = 0x1, + ACA_SEC_GNR = 0x2, + ACA_SEC_MAC_HT = 0x3, + ACA_SEC_MEM_TXIN = 0x4, + ACA_SEC_MEM_TXIN_PDRING = 0x5, + ACA_SEC_MEM_TXOUT = 0x6, + ACA_SEC_MEM_TXOUT_PDRING = 0x7, + ACA_SEC_MEM_RXOUT = 0x8, + ACA_SEC_MEM_RXOUT_PDRING = 0x9, + ACA_SEC_MEM_RXIN = 0xa, + ACA_SEC_MEM_RXIN_PDRING = 0xb, + ACA_SEC_DMA = 0xc, + ACA_SEC_FW_INIT = 0xd, + ACA_SEC_FW = 0x88, +}; + +enum aca_fw_id { + ACA_FW_TXIN = 1, + ACA_FW_TXOUT = 2, + ACA_FW_RXIN = 3, + ACA_FW_RXOUT = 4, + ACA_FW_GNRC = 5, + ACA_FW_MAX = 5, +}; + +enum aca_img_type { + ACA_VRX518_IMG, + ACA_VRX618_IMG, + ACA_FALCON_IMG, + ACA_PUMA_IMG, + ACA_IMG_MAX, +}; + +enum aca_soc_type { + ACA_SOC_XRX300 = 1, + ACA_SOC_XRX500 = 2, + ACA_SOC_PUMA = 4, + ACA_SOC_3RD_PARTY = 8, +}; + +#define ACA_SOC_MASK 0xf + +/* Common information element, len has different variants */ +struct aca_fw_ie { + __be32 id; + __be32 len; +} __packed; + +struct aca_fw_reg { + __be32 offset; + __be32 value; +} __packed; + +struct aca_sram_desc { + __be32 dnum; + __be32 dbase; +} __packed; + +struct aca_fw_dma { + __be32 cid; + __be32 base; +} __packed; + +/* ACA internal header part */ +struct aca_int_hdr { + __be32 id; + __be32 offset; + __be32 size; + __be32 load_addr; +} __packed; + +struct aca_fw_param { + __be32 st_sz; + __be32 init_addr; +} __packed; + +struct aca_mem_layout { + u32 txin_host_desc_base; + u32 txin_host_dnum; + u32 txout_host_desc_base; + u32 txout_host_dnum; + u32 rxin_host_desc_base; + u32 rxin_host_dnum; + u32 rxout_host_desc_base; + u32 rxout_host_dnum; +}; + +struct aca_pdmem_layout { + u32 txin_pd_desc_base; + u32 txin_pd_dnum; + u32 txout_pd_desc_base; + u32 txout_pd_dnum; + u32 rxin_pd_desc_base; + u32 rxin_pd_dnum; + u32 rxout_pd_desc_base; + u32 rxout_pd_dnum; +}; + +struct aca_fw_addr_tuple { + u32 fw_id; + u32 fw_load_addr; + size_t fw_size; + const char *fw_base; +}; + +struct aca_fw_dl_addr { + u32 fw_num; + struct aca_fw_addr_tuple fw_addr[ACA_FW_MAX]; +}; + +struct aca_fw_info { + const struct firmware *fw; + const void *fw_data; + size_t fw_len; + struct aca_mem_layout mem_layout; + struct aca_pdmem_layout pdmem_layout; + struct aca_fw_param fw_param; + struct aca_fw_dl_addr fw_dl; + u32 chan_num; + u32 adma_desc_base[ACA_DMA_CHAN_MAX]; +}; + +union fw_ver { +#ifdef CONFIG_CPU_BIG_ENDIAN + struct { + u32 build:4; + u32 branch:4; + u32 major:8; + u32 minor:16; + } __packed field; +#else + struct { + u32 minor:16; + u32 major:8; + u32 branch:4; + u32 build:4; + } __packed field; +#endif /* CONFIG_CPU_BIG_ENDIAN */ + u32 all; +} __packed; + +union img_soc_type { +#ifdef CONFIG_CPU_BIG_ENDIAN + struct { + u32 img_type:16; + u32 soc_type:16; + } __packed field; +#else + struct { + u32 soc_type:16; + u32 img_type:16; + } __packed field; +#endif /* CONFIG_CPU_BIG_ENDIAN */ + u32 all; +} __packed; + +/* Fixed header part */ +struct aca_fw_f_hdr { + __be32 ver; + __be32 type; + __be32 hdr_size; + __be32 fw_size; + __be32 num_section; +} __packed; + +struct aca_hif_param { + u32 soc_desc_base; + u32 soc_desc_num; + u32 pp_buf_base; + u32 pp_buf_num; + u32 pd_desc_base; + u32 pd_desc_num; + u32 pd_desc_threshold; +} __packed; + +struct aca_hif_params { + u32 task_mask; + struct aca_hif_param txin; + struct aca_hif_param txout; + struct aca_hif_param rxin; + struct aca_hif_param rxout; + u32 dbg_base; + u32 dbg_size; + u32 magic; +} __packed; + +#define ACA_MAGIC 0x25062016 + +struct dc_aca { + bool initialized; + spinlock_t clk_lock; + spinlock_t rcu_lock; + struct mutex pin_lock; + struct aca_fw_info fw_info; + struct aca_hif_params *hif_params; + u32 max_gpio; + u32 adma_chans; +}; +#endif /* ACA_H */ diff --git a/package/kernel/lantiq/vrx518_ep/src/ep.c b/package/kernel/lantiq/vrx518_ep/src/ep.c new file mode 100644 index 00000000000..40fc9d36299 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/ep.c @@ -0,0 +1,770 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ep.h" +#include "aca.h" +#include "misc.h" + +#define DC_EP_DBG + +#define MAJ 2 +#define MIN 1 +#define BUILD 0 +#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ + __stringify(BUILD) "-k" + +static bool pcie_switch_exist; +module_param(pcie_switch_exist, bool, 0644); +MODULE_PARM_DESC(pcie_switch_exist, "pcie switch existed or not"); + +static const char dc_ep_driver_name[] = "vrx518"; +static const char dc_ep_driver_version[] = DRV_VERSION; +static const char dc_ep_driver_string[] = + "Intel(R) SmartPHY DSL(VRX518) PCIe EP/ACA Driver"; +static const char dc_ep_copyright[] = + "Copyright (c) 2016 Intel Corporation."; + +static struct dc_ep_info g_dc_ep_info; +static DEFINE_SPINLOCK(dc_ep_lock); + +static inline void reset_assert_device(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_ep_assert_device(dev->priv, bits); +} + +static inline void reset_deassert_device(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_ep_deassert_device(dev->priv, bits); +} + +static inline void icu_disable_intr(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_ep_icu_dis_intr(dev->priv, bits); +} + +static inline void icu_enable_intr(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_ep_icu_en_intr(dev->priv, bits); +} + +static inline int reset_device(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_reset_device(dev->priv, bits); +} + +static inline int clk_on(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_clk_on(dev->priv, bits); +} + +static inline int clk_off(struct dc_ep_dev *dev, u32 bits) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_clk_off(dev->priv, bits); +} + +static inline int clk_set(struct dc_ep_dev *dev, u32 sysclk, u32 ppeclk) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_clk_set(dev->priv, sysclk, ppeclk); +} + +static inline int clk_get(struct dc_ep_dev *dev, u32 *sysclk, u32 *ppeclk) +{ + if (WARN_ON(!dev || !sysclk || !ppeclk)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_clk_get(dev->priv, sysclk, ppeclk); +} + +static inline int gpio_dir(struct dc_ep_dev *dev, u32 gpio, int dir) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_dir(dev->priv, gpio, dir); +} + +static inline int gpio_set(struct dc_ep_dev *dev, u32 gpio, int val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_set(dev->priv, gpio, val); +} + +static inline int gpio_get(struct dc_ep_dev *dev, u32 gpio, int *val) +{ + if (WARN_ON(!dev || !val)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_get(dev->priv, gpio, val); +} + +static inline int pinmux_set(struct dc_ep_dev *dev, u32 gpio, int func) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_pinmux_set(dev->priv, gpio, func); +} + +static inline int pinmux_get(struct dc_ep_dev *dev, u32 gpio, int *func) +{ + if (WARN_ON(!dev || !func)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_pinmux_get(dev->priv, gpio, func); +} + +static inline int gpio_pupd_set(struct dc_ep_dev *dev, u32 gpio, u32 val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_pupd_set(dev->priv, gpio, val); +} + +static inline int gpio_od_set(struct dc_ep_dev *dev, u32 gpio, int val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_od_set(dev->priv, gpio, val); +} + +static inline int gpio_src_set(struct dc_ep_dev *dev, u32 gpio, int val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_src_set(dev->priv, gpio, val); +} + +static inline int gpio_dcc_set(struct dc_ep_dev *dev, u32 gpio, u32 val) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_ep_gpio_dcc_set(dev->priv, gpio, val); +} + +static inline int aca_start(struct dc_ep_dev *dev, u32 func, int start) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_aca_start(dev->priv, func, start); +} + +static inline int aca_stop(struct dc_ep_dev *dev, u32 *func, int reset) +{ + if (WARN_ON(!dev || !func)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_aca_stop(dev->priv, func, reset); +} + +static inline int aca_init(struct dc_ep_dev *dev, struct aca_param *aca, + struct aca_modem_param *mdm) +{ + if (WARN_ON(!dev || !aca)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_aca_init(dev->priv, aca, mdm); +} + +static inline void aca_event_addr_get(struct dc_ep_dev *dev, + struct aca_event_reg_addr *regs) +{ + if (WARN_ON(!dev || !regs)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_aca_event_addr_get(dev->priv, regs); +} + +static inline u32 umt_msg_addr(struct dc_ep_dev *dev, u32 endian, u32 type) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return aca_umt_msg_addr(dev->priv, endian, type); +} + +static inline void aca_txin_sub_ack(struct dc_ep_dev *dev, u32 val) +{ + if (WARN_ON(!dev)) + return; + if (WARN_ON(!dev->priv)) + return; + + dc_aca_txin_sub_ack(dev->priv, val); +} + +static inline u32 aca_txin_hd_cnt(struct dc_ep_dev *dev) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (WARN_ON(!dev->priv)) + return -EINVAL; + + return dc_aca_txin_hd_cnt(dev->priv); +} + +static const struct aca_hw_ops dc_ep_hw_ops = { + .reset_assert = reset_assert_device, + .reset_deassert = reset_deassert_device, + .reset_device = reset_device, + .icu_en = icu_enable_intr, + .icu_mask = icu_disable_intr, + .clk_on = clk_on, + .clk_off = clk_off, + .clk_set = clk_set, + .clk_get = clk_get, + .gpio_dir = gpio_dir, + .gpio_set = gpio_set, + .gpio_get = gpio_get, + .pinmux_set = pinmux_set, + .pinmux_get = pinmux_get, + .gpio_pupd_set = gpio_pupd_set, + .gpio_od_set = gpio_od_set, + .gpio_src_set = gpio_src_set, + .gpio_dcc_set = gpio_dcc_set, + .aca_start = aca_start, + .aca_stop = aca_stop, + .aca_init = aca_init, + .aca_event_addr_get = aca_event_addr_get, + .umt_msg_addr = umt_msg_addr, + .aca_txin_ack_sub = aca_txin_sub_ack, + .aca_txin_hd_cnt = aca_txin_hd_cnt, +}; + +int dc_ep_dev_num_get(int *dev_num) +{ + if ((g_dc_ep_info.dev_num <= 0) + || (g_dc_ep_info.dev_num > DC_EP_MAX_NUM)) + return -EIO; + + *dev_num = g_dc_ep_info.dev_num; + return 0; +} +EXPORT_SYMBOL_GPL(dc_ep_dev_num_get); + +int dc_ep_dev_info_req(int dev_idx, enum dc_ep_int module, + struct dc_ep_dev *dev) +{ + int i; + struct dc_ep_priv *priv; + + if ((dev_idx < 0) || (dev_idx >= DC_EP_MAX_NUM)) { + dev_err(dev->dev, "%s invalid device index %d\n", + __func__, dev_idx); + return -EIO; + } + + priv = &g_dc_ep_info.pcie_ep[dev_idx]; + if (atomic_read(&priv->refcnt) >= DC_EP_MAX_REFCNT) { + dev_err(dev->dev, + "%s mismatch request/release module usage\n", __func__); + return -EIO; + } + + switch (module) { + case DC_EP_INT_PPE: + dev->irq = priv->irq_base; + if (priv->msi_mode == DC_EP_8_MSI_MODE) { + dev->aca_tx_irq = priv->irq_base + 7; + dev->aca_rx_irq = priv->irq_base + 6; + } else if (priv->msi_mode == DC_EP_4_MSI_MODE) { + dev->aca_tx_irq = priv->irq_base + 2; + dev->aca_rx_irq = priv->irq_base + 3; + } else { + dev_err(dev->dev, "%s ACA should never occur\n", + __func__); + } + break; + case DC_EP_INT_MEI: + dev->irq = priv->irq_base + 1; + break; + default: + dev->irq = priv->irq_base; + break; + } + + dev->dev = priv->dev; + dev->membase = priv->mem; + dev->phy_membase = priv->phymem; + dev->peer_num = priv->peer_num; + for (i = 0; i < dev->peer_num; i++) { + dev->peer_membase[i] = priv->peer_mem[i]; + dev->peer_phy_membase[i] = priv->peer_phymem[i]; + } + dev->switch_attached = priv->switch_attached; + dev->priv = priv; + dev->hw_ops = &dc_ep_hw_ops; + atomic_inc(&priv->refcnt); + return 0; +} +EXPORT_SYMBOL_GPL(dc_ep_dev_info_req); + +int dc_ep_dev_info_release(int dev_idx) +{ + struct dc_ep_priv *priv; + + if ((dev_idx < 0) || (dev_idx >= DC_EP_MAX_NUM)) { + pr_err("%s invalid device index %d\n", + __func__, dev_idx); + return -EIO; + } + + priv = &g_dc_ep_info.pcie_ep[dev_idx]; + if (atomic_read(&priv->refcnt) <= 0) { + pr_err("%s mismatch request/release module usage\n", + __func__); + return -EIO; + } + + atomic_dec(&priv->refcnt); + return 0; +} +EXPORT_SYMBOL_GPL(dc_ep_dev_info_release); + +static int pci_msi_vec_set(struct pci_dev *dev, int nvec) +{ + int pos; + u16 msgctl; + + if (!is_power_of_2(nvec)) + return -EINVAL; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!pos) + return -EINVAL; + + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); + msgctl &= ~PCI_MSI_FLAGS_QSIZE; + msgctl |= ((ffs(nvec) - 1) << 4); + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl); + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); + return 0; +} + +static int dc_ep_msi_enable(struct pci_dev *pdev, int nvec) +{ + int err; + struct dc_ep_priv *priv = pci_get_drvdata(pdev); + + /* NB, ICU initailize first */ + dc_ep_icu_init(priv); + + err = pci_msi_vec_set(pdev, nvec); + if (err) { + dev_err(&pdev->dev, "%s: Failed to set maximum MSI vector\n", + __func__); + return -EIO; + } + + err = pci_enable_msi_exact(pdev, nvec); + if (err) { + dev_err(&pdev->dev, + "%s: Failed to enable MSI interrupts error code: %d\n", + __func__, err); + return -EIO; + } + return 0; +} + +static void dc_ep_info_xchange(struct pci_dev *pdev, int card_num) +{ + /* More cards supported, exchange address information + * For example, suppose three cards dected. + * 0, <1, 2> + * 1, <0, 2> + * 2, <0, 1> + * For four cards detected + * 0, <1, 2, 3> + * 1, <0, 2, 3> + * 2, <0, 1, 3> + * 3, <0, 1, 2> + * and etc + */ + int i, j, k; + int peer_num; +#ifdef DC_EP_DBG + struct dc_ep_priv *priv; +#endif /* DC_EP_DBG */ + spin_lock(&dc_ep_lock); + if (card_num > 1) { + peer_num = card_num - 1; + for (i = 0; i < card_num; i++) { + struct dc_ep_priv *ep = &g_dc_ep_info.pcie_ep[i]; + j = 0; + k = 0; + ep->peer_num = peer_num; + do { + struct dc_ep_priv *partner; + + if (j == i) { + j++; + continue; + } + partner = &g_dc_ep_info.pcie_ep[j]; + ep->peer_mem[k] = partner->mem; + ep->peer_phymem[k] = partner->phymem; + ep->peer_memsize[k] = partner->memsize; + k++; + j++; + } while ((k < peer_num) && (j < card_num)); + } + } + spin_unlock(&dc_ep_lock); + +#ifdef DC_EP_DBG + dev_dbg(&pdev->dev, "Total cards found %d\n", card_num); + /* Dump detailed debug information */ + for (i = 0; i < card_num; i++) { + priv = &g_dc_ep_info.pcie_ep[i]; + dev_dbg(&pdev->dev, "card %d attached\n", priv->ep_idx); + dev_dbg(&pdev->dev, "irq base %d irq numbers %d\n", + priv->irq_base, priv->irq_num); + dev_dbg(&pdev->dev, + "its own phymem 0x%08x mem 0x%p size 0x%08x\n", + priv->phymem, priv->mem, priv->memsize); + if (card_num > 1) { + for (j = 0; j < priv->peer_num; j++) + dev_dbg(&pdev->dev, + "its peer phymem 0x%08x mem 0x%p size 0x%08x\n", + priv->peer_phymem[j], + priv->peer_mem[j], priv->peer_memsize[j]); + } + } +#endif /* DC_EP_DBG */ +} + +static int pci_msi_vec_num(struct pci_dev *dev) +{ + int ret; + u16 msgctl; + + if (!dev->msi_cap) + return -EINVAL; + + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl); + ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); + + return ret; +} + +static int dc_ep_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int ret; + int nvec; + bool switch_exist; + int current_ep; + unsigned long phymem; + void __iomem *mem; + size_t memsize; + int msi_mode; + static int cards_found; +#ifndef CONFIG_OF + struct pcie_ep_adapter *adapter; +#endif + struct dc_ep_priv *priv; + + ret = pci_enable_device(pdev); + if (ret) { + dev_err(&pdev->dev, "can't enable PCI device %d\n", ret); + goto err_pci; + } + + /* Physical address */ + ret = pci_request_region(pdev, DC_EP_BAR_NUM, dc_ep_driver_name); + if (ret) { + dev_err(&pdev->dev, "PCI MMIO reservation error: %d\n", ret); + goto err_device; + } + + /* Target structures have a limit of 32 bit DMA pointers. + * DMA pointers can be wider than 32 bits by default on some systems. + */ + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "32-bit DMA not available: %d\n", ret); + goto err_region; + } + + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "cannot enable 32-bit consistent DMA\n"); + goto err_region; + } + + /* Set bus master bit in PCI_COMMAND to enable DMA */ + pci_set_master(pdev); + /* NB, some delay may need due to BME reset */ + udelay(1); + + /* Arrange for access to Target SoC registers. */ + mem = pci_iomap(pdev, DC_EP_BAR_NUM, 0); + if (!mem) { + dev_err(&pdev->dev, "PCI iomap error\n"); + ret = -EIO; + goto err_master; + } + phymem = pci_resource_start(pdev, DC_EP_BAR_NUM); + memsize = pci_resource_len(pdev, DC_EP_BAR_NUM); + + nvec = pci_msi_vec_num(pdev); + /* Overwrite maximum vector number according to + * the specific requirement + */ + if ((DC_PCIE_SWITCH_ATTACH > 0) || pcie_switch_exist) + switch_exist = true; + else + switch_exist = false; + /* Always use 4 vector mode */ + nvec = DC_EP_DEFAULT_MSI_VECTOR; + msi_mode = DC_EP_4_MSI_MODE; + + current_ep = cards_found++; + priv = &g_dc_ep_info.pcie_ep[current_ep]; + memset(priv, 0, sizeof(*priv)); + pci_set_drvdata(pdev, priv); + + /* Collect basic info for further operations */ + spin_lock(&dc_ep_lock); + g_dc_ep_info.dev_num = cards_found; + atomic_set(&priv->refcnt, 0); + priv->pdev = pdev; + priv->device_id = pdev->device; + priv->dev = &pdev->dev; + priv->ep_idx = current_ep; + priv->mem = mem; + priv->phymem = phymem; + priv->memsize = memsize; + priv->irq_num = nvec; + priv->switch_attached = switch_exist; + priv->msi_mode = msi_mode; + spin_unlock(&dc_ep_lock); + + ret = dc_ep_msi_enable(pdev, nvec); + if (ret) + goto err_iomap; + + spin_lock(&dc_ep_lock); + priv->irq_base = pdev->irq; + spin_unlock(&dc_ep_lock); + +#ifndef CONFIG_OF + adapter = kmalloc(sizeof(struct pcie_ep_adapter), GFP_KERNEL); + if (adapter == NULL) + goto err_iomap; + pci_set_drvdata(pdev, adapter); + adapter->mei_dev = platform_device_register_data(&pdev->dev, "mei_cpe", + PLATFORM_DEVID_AUTO, + NULL, 0); + if (IS_ERR(adapter->mei_dev)) { + dev_err(&pdev->dev, "can not register mei device, err: %li, ignore this\n", + PTR_ERR(adapter->mei_dev)); + goto err_msi; + } +#endif + dc_ep_info_xchange(pdev, cards_found); + /* Disable output clock to save power */ + dc_ep_clkod_disable(priv); + dc_aca_info_init(priv); + return 0; +#ifndef CONFIG_OF +err_msi: + kfree(adapter); +#endif +err_iomap: + pci_iounmap(pdev, mem); +err_master: + pci_clear_master(pdev); +err_region: + pci_release_region(pdev, DC_EP_BAR_NUM); +err_device: + pci_disable_device(pdev); +err_pci: + return ret; +} + +static void dc_ep_remove(struct pci_dev *pdev) +{ + struct dc_ep_priv *priv = pci_get_drvdata(pdev); + +#ifndef CONFIG_OF + struct pcie_ep_adapter *adapter = + (struct pcie_ep_adapter *) pci_get_drvdata(pdev); + + platform_device_unregister(adapter->mei_dev); +#endif + if (priv == NULL) + return; + + if (atomic_read(&priv->refcnt) != 0) { + dev_err(&pdev->dev, "%s still being used, can't remove\n", + __func__); + return; + } + dc_aca_free_fw_file(priv); + dc_aca_shutdown(priv); + dc_ep_icu_disable(priv); + pci_iounmap(pdev, priv->mem); + pci_release_region(pdev, DC_EP_BAR_NUM); + pci_disable_msi(pdev); + wmb(); + pci_clear_master(pdev); + pci_disable_device(pdev); +} + +static const struct pci_device_id dc_ep_id_table[] = { + {0x8086, 0x09a9, PCI_ANY_ID, PCI_ANY_ID}, /* VRX518 */ + {0}, +}; + +MODULE_DEVICE_TABLE(pci, dc_ep_id_table); + +static struct pci_driver dc_ep_driver = { + .name = (char *)dc_ep_driver_name, + .id_table = dc_ep_id_table, + .probe = dc_ep_probe, + .remove = dc_ep_remove, + .shutdown = dc_ep_remove, + /* PM not supported */ + /* AER is controlled by RC */ +}; + +static int __init dc_ep_init(void) +{ + pr_info("%s - version %s\n", + dc_ep_driver_string, dc_ep_driver_version); + + pr_info("%s\n", dc_ep_copyright); + memset(&g_dc_ep_info, 0, sizeof(struct dc_ep_info)); + + if (pci_register_driver(&dc_ep_driver) < 0) { + pr_err("%s: No devices found, driver not installed.\n", + __func__); + return -ENODEV; + } + return 0; +} +module_init(dc_ep_init); + +static void __exit dc_ep_exit(void) +{ + pci_unregister_driver(&dc_ep_driver); + + pr_info("%s: %s driver unloaded\n", __func__, + dc_ep_driver_name); +} +module_exit(dc_ep_exit); + +MODULE_AUTHOR("Intel Corporation, "); +MODULE_DESCRIPTION("Intel(R) SmartPHY PCIe EP/ACA Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/package/kernel/lantiq/vrx518_ep/src/ep.h b/package/kernel/lantiq/vrx518_ep/src/ep.h new file mode 100644 index 00000000000..2e31008ec83 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/ep.h @@ -0,0 +1,127 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef EP_H +#define EP_H + +#include + +#include "aca.h" + +#define DC_EP_MAX_NUM (DC_EP_MAX_PEER + 1) +#define DC_EP_BAR_NUM 0 + +/* Maximum 8, if PCIe switch attached, 4 is used. 8 is also default one */ +#ifdef CONFIG_VRX518_PCIE_SWITCH_BONDING +#define DC_PCIE_SWITCH_ATTACH 1 +#else +#define DC_PCIE_SWITCH_ATTACH 0 +#endif /* CONFIG_VRX518_PCIE_SWITCH_BONDING */ + +#define DC_EP_DEFAULT_MSI_VECTOR 4 + +#define DC_EP_MAX_REFCNT DC_EP_INT_MAX + +#define MS(_v, _f) (((_v) & (_f)) >> _f##_S) +#define SM(_v, _f) (((_v) << _f##_S) & (_f)) + +enum dc_ep_msi_mode { + DC_EP_8_MSI_MODE = 0, + DC_EP_4_MSI_MODE, + DC_EP_1_MSI_MODE, +}; + +/* Structure used to extract attached EP detailed information for + * PPE/DSL_MEI driver/Bonding + */ +struct dc_ep_priv { + struct pci_dev *pdev; + struct device *dev; + u32 ep_idx; /*!< EP logical index, the first found one will be 0 + regardless of RC physical index + */ + u32 irq_base; /*!< The first MSI interrupt number */ + u32 irq_num; /*!< How many MSI interrupt supported */ + enum dc_ep_msi_mode msi_mode; + u8 __iomem *mem; /*!< The EP inbound memory base address + derived from BAR0, SoC virtual address + for PPE/DSL_MEI driver + */ + u32 phymem; /*!< The EP inbound memory base address + derived from BAR0, physical address for + PPE FW + */ + size_t memsize; /*!< The EP inbound memory window size */ + u32 peer_num; /*!< Bonding peer number available */ + /*!< The bonding peer EP inbound memory base address derived from + * its BAR0, SoC virtual address for PPE/DSL_MEI driver + */ + + u8 __iomem *peer_mem[DC_EP_MAX_PEER]; + + /*!< The bonding peer EP inbound memory base address derived from + * its BAR0, physical address for PPE FW + */ + u32 peer_phymem[DC_EP_MAX_PEER]; + + /*!< The bonding peer inbound memory window size */ + size_t peer_memsize[DC_EP_MAX_PEER]; + atomic_t refcnt; /*!< The EP mapping driver referenced times + by other modules + */ + u16 device_id; /* Potential usage for different EP */ + bool switch_attached; + struct dc_aca aca; +}; + +struct dc_ep_info { + int dev_num; + int msi_mode; + struct dc_ep_priv pcie_ep[DC_EP_MAX_NUM]; +}; + +static inline struct dc_aca *to_aca(struct dc_ep_priv *priv) +{ + return &priv->aca; +} + +void dc_aca_shutdown(struct dc_ep_priv *priv); +void dc_aca_info_init(struct dc_ep_priv *priv); +int dc_aca_start(struct dc_ep_priv *priv, u32 func, int start); +int dc_aca_stop(struct dc_ep_priv *priv, u32 *func, int reset); +int dc_aca_init(struct dc_ep_priv *priv, struct aca_param *aca, + struct aca_modem_param *mdm); +void dc_aca_event_addr_get(struct dc_ep_priv *priv, + struct aca_event_reg_addr *regs); +void dc_aca_txin_sub_ack(struct dc_ep_priv *priv, u32 val); +u32 aca_umt_msg_addr(struct dc_ep_priv *priv, u32 endian, u32 type); +u32 dc_aca_txin_hd_cnt(struct dc_ep_priv *priv); +void dc_aca_free_fw_file(struct dc_ep_priv *priv); + +/* Card specific private data structure */ +struct pcie_ep_adapter { + struct platform_device *mei_dev; /* the mei driver */ +}; + +#endif /* EP_H */ + diff --git a/package/kernel/lantiq/vrx518_ep/src/include/net/dc_ep.h b/package/kernel/lantiq/vrx518_ep/src/include/net/dc_ep.h new file mode 100644 index 00000000000..f1142332e19 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/include/net/dc_ep.h @@ -0,0 +1,349 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef DC_EP_H +#define DC_EP_H + +#include +#include +#include + +/* @{ */ +/*! \def DC_EP_MAX_PEER + * \brief how many EP partners existed. In most cases, this number should be + * one for bonding application. For the future extension, it could be bigger + * value. For example, multiple bonding + */ +#define DC_EP_MAX_PEER 1 + +/* Reset related module bit definition */ +#define RST_GPIO BIT(2) +#define RST_DSL_IF BIT(3) +#define RST_DFE BIT(7) +#define RST_PPE BIT(8) +#define RST_CDMA BIT(9) +#define RST_SPI BIT(10) +#define RST_IMCU BIT(11) +#define RST_ACA_DMA BIT(14) +#define RST_AFE BIT(16) +#define RST_ACA_HOSTIF BIT(17) +#define RST_PCIE BIT(22) +#define RST_PPE_ATM_TC BIT(23) +#define RST_FPI_SLAVE BIT(25) +#define RST_GLOBAL BIT(30) + +/* PMU related module definition */ +#define PMU_ADMA BIT(0) +#define PMU_CDMA BIT(2) +#define PMU_SPI BIT(8) +#define PMU_DSL BIT(9) +#define PMU_PPE_QSB BIT(18) +#define PMU_PPE_SLL01 BIT(19) +#define PMU_PPE_TC BIT(21) +#define PMU_EMA BIT(22) +#define PMU_PPM2 BIT(23) +#define PMU_PPE_TOP BIT(29) + +/* IMER bit definition */ +#define PPE2HOST_INT0 BIT(0) +#define PPE2HOST_INT1 BIT(1) +#define DYING_GASP_INT BIT(3) +#define MEI_IRQ BIT(8) +#define ACA_XBAR_INT BIT(9) +#define MODEM_XBAR_INT BIT(12) +#define LED0_INT BIT(13) +#define LED1_INT BIT(14) +#define NMI_PLL BIT(15) +#define DMA_TX BIT(16) +#define DMA_RX BIT(17) +#define ACA_HOSTIF_TX BIT(20) +#define ACA_HOSTIF_RX BIT(21) +#define ACA_RXOUT_PD_RING_FULL BIT(22) +#define ACA_TXOUT_PD_RING_FULL BIT(23) + +/* + * Structure used to specify available pin mux functions for gpio pinx + * It will be used in pinmux_set() function + */ +enum gpio_padc_func { + MUX_FUNC_GPIO = 0, + MUX_FUNC_ALT1, + MUX_FUNC_ALT2, + MUX_FUNC_RES, +}; + +/* + * Structure used to specify interrupt source so that EP can assign unique + * interruot to it +*/ +enum dc_ep_int { + DC_EP_INT_PPE, /*!< PPE2HOST_INT 0/1 */ + DC_EP_INT_MEI, /*!< DSL MEI_IRQ */ + DC_EP_INT_MAX, +}; + +/* Clock setting for system clock */ +enum { + SYS_CLK_36MHZ = 0, + SYS_CLK_288MHZ, + SYS_CLK_MAX, +}; + +/* Clock setting for PPE clock */ +enum { + PPE_CLK_36MHZ = 0, + PPE_CLK_576MHZ, + PPE_CLK_494MHZ, + PPE_CLK_432MHZ, + PPE_CLK_288MHZ, + PPE_CLK_MAX, +}; + +/* GPIO direction IN/OUT */ +enum { + GPIO_DIR_IN = 0, + GPIO_DIR_OUT, + GPIO_DIR_MAX, +}; + +/* GPIO Pullup/Pulldown setting */ +enum { + GPIO_PUPD_DISABLE = 0, + GPIO_PULL_UP, + GPIO_PULL_DOWN, + GPIO_PUPD_BOTH, +}; + +/* GPIO slew rate setting */ +enum { + GPIO_SLEW_RATE_SLOW = 0, + GPIO_SLEW_RATE_FAST, +}; + +/* GPIO driver current setting */ +enum { + GPIO_DRV_CUR_2MA = 0, + GPIO_DRV_CUR_4MA, + GPIO_DRV_CUR_8MA, + GPIO_DRV_CUR_12MA, + GPIO_DRV_CUR_MAX, +}; + +enum { + ACA_LITTLE_ENDIAN = 0, + ACA_BIG_ENDIAN, + ACA_ENDIAN_MAX, +}; + +enum { + ACA_TXIN = 0, + ACA_TXOUT, + ACA_RXIN, + ACA_RXOUT, + ACA_MAX, +}; + +/* ACA four major direction functions for start/stop */ +#define ACA_TXIN_EN BIT(0) +#define ACA_TXOUT_EN BIT(1) +#define ACA_RXIN_EN BIT(2) +#define ACA_RXOUT_EN BIT(3) +#define ACA_ALL_EN 0xF + +struct dc_ep_dev; + +/* + * ACA SoC specific parameters. The caller needs to fill up all necessary info + * according to specific SoC and specific project + * For each function, different parameters are needed. + */ +struct aca_cfg_param { + u32 soc_desc_base; /*!< SoC CBM or DDR descriptor base address */ + u32 soc_desc_num; /*!< SoC and HostIF (same) descriptor number */ + u32 soc_cmlt_cnt_addr; /*! SoC cumulative counter address */ + u32 pp_buf_desc_num; /*!< ACA ping pong buffer descriptor number */ + u32 pd_desc_base; /*!< Packet Descriptor base address in modem */ + u32 pd_desc_num; /*!< Packet Descriptor number in modem */ + u32 hd_size_in_dw; /*!< Host(SoC) descriptor size in dwords */ + u32 pd_size_in_dw; /*!< Packet descriptor size in dwords */ + u32 byteswap; /*!< Byte swap enabled or not in ACA FW */ + u32 prefill_cnt; /*!< Prefill counter special required for some platform */ +}; + +struct aca_param { + struct aca_cfg_param aca_txin; + struct aca_cfg_param aca_txout; + struct aca_cfg_param aca_rxin; + struct aca_cfg_param aca_rxout; +}; + +/* ACA project/modem specific parameters. It is only valid for VRX518 */ +struct aca_proj_param { + u32 stat; /*!< Target state */ + u32 pd; /*!< Target packet descripor */ + u32 acc_cnt; /*!< Target accumulate counter */ +}; + +/* Project specific configuration */ +struct aca_modem_param { + struct aca_proj_param mdm_txout; + struct aca_proj_param mdm_rxin; + struct aca_proj_param mdm_rxout; +}; + +/* Event trigger register address */ +struct aca_event_reg_addr { + u32 txin_acc_sub; + u32 txout_acc_add; + u32 rxin_acc_sub; + u32 rxout_acc_add; +}; + +/* + * ACA common hardware low level APIs, presented as callbacks instead of + * separate APIs to support mulitple instances + */ +struct aca_hw_ops { + /* RCU Callbacks */ + void (*reset_assert)(struct dc_ep_dev *pdev, u32 rd); + void (*reset_deassert)(struct dc_ep_dev *pdev, u32 rd); + /* For hardware self-clear reset, most apply except PCIe */ + int (*reset_device)(struct dc_ep_dev *pdev, u32 hd); + + /* PMU Callbacks */ + int (*clk_on)(struct dc_ep_dev *pdev, u32 cd); + int (*clk_off)(struct dc_ep_dev *pdev, u32 cd); + + /* CGU Callbacks */ + int (*clk_set)(struct dc_ep_dev *pdev, u32 sysclk, u32 ppeclk); + int (*clk_get)(struct dc_ep_dev *pdev, u32 *sysclk, u32 *ppeclk); + + /* GPIO Callbacks */ + int (*gpio_dir)(struct dc_ep_dev *pdev, u32 gpio, int dir); + int (*gpio_set)(struct dc_ep_dev *pdev, u32 gpio, int val); + int (*gpio_get)(struct dc_ep_dev *pdev, u32 gpio, int *val); + + /* PinMux Callbacks */ + int (*pinmux_set)(struct dc_ep_dev *pdev, u32 gpio, int func); + int (*pinmux_get)(struct dc_ep_dev *pdev, u32 gpio, int *func); + int (*gpio_pupd_set)(struct dc_ep_dev *pdev, u32 gpio, u32 val); + int (*gpio_od_set)(struct dc_ep_dev *pdev, u32 gpio, int val); + int (*gpio_src_set)(struct dc_ep_dev *pdev, u32 gpio, int val); + int (*gpio_dcc_set)(struct dc_ep_dev *pdev, u32 gpio, u32 val); + + /* ICU Callbacks */ + void (*icu_en)(struct dc_ep_dev *pdev, u32 bit); + void (*icu_mask)(struct dc_ep_dev *pdev, u32 bit); + + /* ACA related stuff */ + int (*aca_start)(struct dc_ep_dev *pdev, u32 func, int start); + int (*aca_stop)(struct dc_ep_dev *pdev, u32 *func, int reset); + /* If there is no project specific parameters, input NULL */ + int (*aca_init)(struct dc_ep_dev *pdev, struct aca_param *aca, + struct aca_modem_param *mdm); + void (*aca_event_addr_get)(struct dc_ep_dev *pdev, + struct aca_event_reg_addr *regs); + /* UMT address needed for SoC filled in to trigger UMT msg */ + u32 (*umt_msg_addr)(struct dc_ep_dev *pdev, u32 endian, u32 type); + /* TXIN accum sub to ack PPE already processed */ + void (*aca_txin_ack_sub)(struct dc_ep_dev *pdev, u32 val); + u32 (*aca_txin_hd_cnt)(struct dc_ep_dev *pdev); +}; + +/* + * Structure used to extract attached EP detailed information + * for PPE/DSL_MEI driver/Bonding + */ +struct dc_ep_dev { + struct device *dev; + u32 irq; /*!< MSI interrupt number for this device */ + u32 aca_tx_irq; /*!< ACA Non-empty TX irq number for PPE driver */ + u32 aca_rx_irq; /*!< ACA Non-empty RX irq number for PPE driver */ + /*!< The EP inbound memory base address derived from BAR0, SoC + virtual address for PPE/DSL_MEI driver + */ + bool switch_attached; /*!< EP attach switch */ + u8 __iomem *membase; /*!< virtual memory base address to access EP */ + u32 phy_membase; /*!< The EP inbound memory base address derived + from BAR0, physical address for PPE FW + */ + u32 peer_num; /*!< Bonding peer number available */ + /*!< The bonding peer EP inbound memory base address derived from + its BAR0, SoC virtual address for PPE/DSL_MEI driver + */ + u8 __iomem *peer_membase[DC_EP_MAX_PEER]; + /*!< The bonding peer EP inbound memory base address derived from + its BAR0, physical address for PPE FW + */ + u32 peer_phy_membase[DC_EP_MAX_PEER]; + const struct aca_hw_ops *hw_ops; + void *priv; /* Pointer to driver proprietary data for internal use */ +}; + +/* + * This function returns the total number of EPs attached. Normally, + * the number should be one or two . Extended case is also considered + + * \param[in/out] dev_num Pointer to detected EP numbers in total. + * \return -EIO Invalid total EP number which means this + * module is not initialized properly + * \return 0 Successfully return the detected EP numbers + */ +int dc_ep_dev_num_get(int *dev_num); + +/* + * This function returns detailed EP device information for PPE/DSL/Bonding + * partner by its logical index obtained + * by \ref dc_ep_dev_num_get and its interrupt module number + * \ref dc_ep_int + + * \param[in] dev_idx Logical device index referred to the related + * device + * \param[in] module EP interrupt module user + * \param[in/out] dev Pointer to returned detail device structure + * \ref dc_ep_dev + * \return -EIO Invalid logical device index or too many modules + * referred to this module + * \return 0 Successfully return required device information + + * \remarks This function normally will be called to trace the detailed device + * information after calling \ref dc_ep_dev_num_get + */ +int dc_ep_dev_info_req(int dev_idx, enum dc_ep_int module, + struct dc_ep_dev *dev); + +/* + * This function releases the usage of this module by PPE/DSL + + * \param[in] dev_idx Logical device index referred to the related device + * \return -EIO Invalid logical device index or release too many + * times to refer to this module + * \return 0 Successfully release the usage of this module + + * \remarks This function should be called once their reference is over. + * The reference usage must matches \ref dc_ep_dev_info_req + */ +int dc_ep_dev_info_release(int dev_idx); + +#endif /* DC_EP_H */ diff --git a/package/kernel/lantiq/vrx518_ep/src/misc.c b/package/kernel/lantiq/vrx518_ep/src/misc.c new file mode 100644 index 00000000000..9140fe79e4d --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/misc.c @@ -0,0 +1,325 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#include +#include + +#include "regs.h" +#include "ep.h" +#include "misc.h" + +#define padc_getbit(p, r) (!!(rd32(r) & (1 << p))) +#define padc_setbit(p, r) wr32_mask(0, BIT(p), r) +#define padc_clearbit(p, r) wr32_mask(BIT(p), 0, r) + +void dc_ep_clkod_disable(struct dc_ep_priv *priv) +{ + wr32_mask(0, IF_CLKOD_ALL, IF_CLK); +} + +void dc_ep_icu_init(struct dc_ep_priv *priv) +{ + /* Enable all interrupts in ICU level */ + wr32(ICU_DMA_TX_ALL, ICU_DMA_TX_IMER); + wr32(ICU_DMA_RX_ALL, ICU_DMA_RX_IMER); + wr32(ICU_TOP_ALL, ICU_IMER); + + if (priv->msi_mode == DC_EP_4_MSI_MODE) + wr32(PCI_MSI_4_MODE, RCU_MSI); + else + wr32(PCI_MSI_8_MODE, RCU_MSI); + + /* PCIe app has to enable all MSI interrupts regardless of MSI mode */ + wr32(PCIE_MSI_EN_ALL, PCIE_APPL_MSI_EN); +} + +void dc_ep_icu_disable(struct dc_ep_priv *priv) +{ + /* Disable all PCIe related interrupts */ + wr32(0, PCIE_APPL_MSI_EN); + + wr32(PCI_MSI_8_MODE, RCU_MSI); + + /* Disable all interrupts in ICU level */ + wr32(0, ICU_DMA_TX_IMER); + wr32(0, ICU_DMA_RX_IMER); + wr32(0, ICU_IMER); +} + +void dc_ep_icu_dis_intr(struct dc_ep_priv *priv, u32 bits) +{ + wr32_mask(~bits, 0, ICU_IMER); +} + +void dc_ep_icu_en_intr(struct dc_ep_priv *priv, u32 bits) +{ + wr32_mask(0, bits, ICU_IMER); +} + +void dc_ep_assert_device(struct dc_ep_priv *priv, u32 bits) +{ + struct dc_aca *aca = to_aca(priv); + + spin_lock(&aca->rcu_lock); + wr32_mask(0, bits, RCU_REQ); + spin_unlock(&aca->rcu_lock); +} + +void dc_ep_deassert_device(struct dc_ep_priv *priv, u32 bits) +{ + struct dc_aca *aca = to_aca(priv); + + spin_lock(&aca->rcu_lock); + wr32_mask(bits, 0, RCU_REQ); + spin_unlock(&aca->rcu_lock); +} + +int dc_ep_reset_device(struct dc_ep_priv *priv, u32 bits) +{ + int retry = EP_TIMEOUT; + + wr32(bits, RCU_REQ); + do { } while (retry-- && (!(rd32(RCU_STAT) & bits))); + + if (retry == 0) { + dev_err(priv->dev, "%s failed to reset\n", __func__); + return -ETIME; + } + return 0; +} + +int dc_ep_clk_on(struct dc_ep_priv *priv, u32 bits) +{ + int retry = EP_TIMEOUT; + struct dc_aca *aca = to_aca(priv); + + spin_lock(&aca->clk_lock); + wr32_mask(bits, 0, PMU_PWDCR); + spin_unlock(&aca->clk_lock); + + do { } while (--retry && (rd32(PMU_SR) & bits)); + + if (!retry) { + dev_err(priv->dev, "%s failed\n", __func__); + return -ETIME; + } + return 0; +} + +int dc_ep_clk_off(struct dc_ep_priv *priv, u32 bits) +{ + int retry = EP_TIMEOUT; + struct dc_aca *aca = to_aca(priv); + + spin_lock(&aca->clk_lock); + wr32_mask(0, bits, PMU_PWDCR); + spin_unlock(&aca->clk_lock); + + do {} while (--retry + && (!(rd32(PMU_SR) & bits))); + if (!retry) { + dev_err(priv->dev, "%s failed\n", __func__); + return -ETIME; + } + return 0; +} + +int dc_ep_clk_set(struct dc_ep_priv *priv, u32 sysclk, u32 ppeclk) +{ + struct dc_aca *aca = to_aca(priv); + + if (sysclk > SYS_CLK_MAX || ppeclk > PPE_CLK_MAX) + return -EINVAL; + + spin_lock(&aca->clk_lock); + wr32_mask(PPE_CLK | SYS_CLK, + SM(sysclk, SYS_CLK) | SM(ppeclk, PPE_CLK), PLL_OMCFG); + spin_unlock(&aca->clk_lock); + return 0; +} + +int dc_ep_clk_get(struct dc_ep_priv *priv, u32 *sysclk, u32 *ppeclk) +{ + u32 val; + + val = rd32(PLL_OMCFG); + *sysclk = MS(val, SYS_CLK); + *ppeclk = MS(val, PPE_CLK); + return 0; +} + +int dc_ep_gpio_dir(struct dc_ep_priv *priv, u32 gpio, int dir) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + if ((dir != GPIO_DIR_IN) && (dir != GPIO_DIR_OUT)) + return -EINVAL; + + if (dir == GPIO_DIR_IN) + wr32(BIT(gpio), GPIO_DIRCLR); + else + wr32(BIT(gpio), GPIO_DIRSET); + return 0; +} + +int dc_ep_gpio_set(struct dc_ep_priv *priv, u32 gpio, int val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + dc_ep_gpio_dir(priv, gpio, GPIO_DIR_OUT); + + if (val) + wr32(BIT(gpio), GPIO_OUTSET); + else + wr32(BIT(gpio), GPIO_OUTCLR); + return 0; +} + +int dc_ep_gpio_get(struct dc_ep_priv *priv, u32 gpio, int *val) +{ + u32 dir; + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + dir = rd32(GPIO_DIR); + if ((dir >> gpio) & 0x1) + *val = (rd32(GPIO_OUT) >> gpio) & 0x1; + else + *val = (rd32(GPIO_IN) >> gpio) & 0x1; + return 0; +} + +int dc_ep_pinmux_set(struct dc_ep_priv *priv, u32 gpio, int func) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + if (func >= MUX_FUNC_RES) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + wr32_mask(PADC_MUX_M, func, PADC_MUX(gpio)); + mutex_unlock(&aca->pin_lock); + return 0; +} + +int dc_ep_pinmux_get(struct dc_ep_priv *priv, u32 gpio, int *func) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + *func = rd32(PADC_MUX(gpio)); + return 0; +} + +int dc_ep_gpio_pupd_set(struct dc_ep_priv *priv, u32 gpio, u32 val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + /* Not support for both enabled */ + if (val >= GPIO_PUPD_BOTH) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + switch (val) { + case GPIO_PUPD_DISABLE: + padc_clearbit(gpio, PADC_PUEN); + padc_clearbit(gpio, PADC_PDEN); + break; + case GPIO_PULL_UP: + padc_setbit(gpio, PADC_PUEN); + padc_clearbit(gpio, PADC_PDEN); + break; + case GPIO_PULL_DOWN: + padc_setbit(gpio, PADC_PDEN); + padc_clearbit(gpio, PADC_PUEN); + break; + default: + break; + } + mutex_unlock(&aca->pin_lock); + return 0; +} + +int dc_ep_gpio_od_set(struct dc_ep_priv *priv, u32 gpio, int val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + if (!!val) + padc_setbit(gpio, PADC_OD); + else + padc_clearbit(gpio, PADC_OD); + mutex_unlock(&aca->pin_lock); + return 0; +} + +int dc_ep_gpio_src_set(struct dc_ep_priv *priv, u32 gpio, int val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + if (!!val) + padc_setbit(gpio, PADC_SRC); + else + padc_clearbit(gpio, PADC_SRC); + mutex_unlock(&aca->pin_lock); + return 0; +} + +int dc_ep_gpio_dcc_set(struct dc_ep_priv *priv, u32 gpio, u32 val) +{ + struct dc_aca *aca = to_aca(priv); + + if (gpio > aca->max_gpio) + return -EINVAL; + + if (val >= GPIO_DRV_CUR_MAX) + return -EINVAL; + + mutex_lock(&aca->pin_lock); + wr32_mask((0x3 << (gpio * 2)), (val << (gpio * 2)), PADC_DCC); + mutex_unlock(&aca->pin_lock); + return 0; +} diff --git a/package/kernel/lantiq/vrx518_ep/src/misc.h b/package/kernel/lantiq/vrx518_ep/src/misc.h new file mode 100644 index 00000000000..d92ea83e2fc --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/misc.h @@ -0,0 +1,51 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef MISC_H +#define MISC_H + +#define EP_TIMEOUT 10000 + +void dc_ep_clkod_disable(struct dc_ep_priv *priv); +void dc_ep_icu_init(struct dc_ep_priv *priv); +void dc_ep_icu_disable(struct dc_ep_priv *priv); +void dc_ep_assert_device(struct dc_ep_priv *priv, u32 bits); +void dc_ep_deassert_device(struct dc_ep_priv *priv, u32 bits); +int dc_ep_reset_device(struct dc_ep_priv *priv, u32 bits); +int dc_ep_clk_on(struct dc_ep_priv *priv, u32 bits); +int dc_ep_clk_off(struct dc_ep_priv *priv, u32 bits); +int dc_ep_clk_set(struct dc_ep_priv *priv, u32 sysclk, u32 ppeclk); +int dc_ep_clk_get(struct dc_ep_priv *priv, u32 *sysclk, u32 *ppeclk); +int dc_ep_gpio_dir(struct dc_ep_priv *priv, u32 gpio, int dir); +int dc_ep_gpio_set(struct dc_ep_priv *priv, u32 gpio, int val); +int dc_ep_gpio_get(struct dc_ep_priv *priv, u32 gpio, int *val); +int dc_ep_pinmux_set(struct dc_ep_priv *priv, u32 gpio, int func); +int dc_ep_pinmux_get(struct dc_ep_priv *priv, u32 gpio, int *func); +int dc_ep_gpio_pupd_set(struct dc_ep_priv *priv, u32 gpio, u32 val); +int dc_ep_gpio_od_set(struct dc_ep_priv *priv, u32 gpio, int val); +int dc_ep_gpio_src_set(struct dc_ep_priv *priv, u32 gpio, int val); +int dc_ep_gpio_dcc_set(struct dc_ep_priv *priv, u32 gpio, u32 val); +void dc_ep_icu_dis_intr(struct dc_ep_priv *priv, u32 bits); +void dc_ep_icu_en_intr(struct dc_ep_priv *priv, u32 bits); + +#endif /* MISC_H */ diff --git a/package/kernel/lantiq/vrx518_ep/src/regs.h b/package/kernel/lantiq/vrx518_ep/src/regs.h new file mode 100644 index 00000000000..9236453a4f4 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/regs.h @@ -0,0 +1,138 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef REGS_H +#define REGS_H + +#include + +/* APPL defined */ +#define PCIE_APPL_BASE 0x00048000 +#define PCIE_APPL_REG(X) (PCIE_APPL_BASE + (X)) + +#define PCIE_APPL_PHY_CFG1 PCIE_APPL_REG(0x3C) +#define PCIE_APPL_PHY_CFG2 PCIE_APPL_REG(0x40) +#define PCIE_APPL_PHY_CFG3 PCIE_APPL_REG(0x58) +#define PCIE_APPL_PHY_CFG4 PCIE_APPL_REG(0x28) +#define PCIE_APPL_INTR_VEC PCIE_APPL_REG(0x48) +#define PCIE_APPL_MSI_EN PCIE_APPL_REG(0x4C) + +#define PCIE_MSI_EN_ALL 0xFF + +/* RCU defined */ +#define RCU_BASE 0x00008000 +#define RCU_REG(X) (RCU_BASE + (X)) +#define RCU_STAT RCU_REG(0x00) +#define RCU_REQ RCU_REG(0x10) + +#define RCU_MSI RCU_REG(0x80) +#define PCI_MSI_4_MODE 1 +#define PCI_MSI_8_MODE 0 + +/* CGU */ +#define CGU_BASE 0x00000000 +#define CGU_REG(X) (CGU_BASE + (X)) +#define PMU_PWDCR CGU_REG(0x011C) +#define PMU_SR CGU_REG(0x0120) +#define PMU_ALL 0x20ec0305 + +#define PLL_OMCFG CGU_REG(0x0064) + +#define SYS_CLK 0x3 +#define SYS_CLK_S 0 +#define PPE_CLK 0x700 +#define PPE_CLK_S 8 + +#define IF_CLK CGU_REG(0x0024) + +#define CLK_PD BIT(10) +#define CLK_OD BIT(11) +#define PCIE_CLKOD (BIT(12) | BIT(13)) +#define AFE_CLKOD BIT(14) + +#define IF_CLKOD_ALL (CLK_PD | CLK_OD | PCIE_CLKOD | AFE_CLKOD) + +/* GPIO */ +#define GPIO_BASE 0x00020000 +#define GPIO_REG(X) (GPIO_BASE + (X)) +#define GPIO_OUT GPIO_REG(0x00) +#define GPIO_IN GPIO_REG(0x04) +#define GPIO_DIR GPIO_REG(0x08) +#define GPIO_OUTSET GPIO_REG(0x40) +#define GPIO_OUTCLR GPIO_REG(0x44) +#define GPIO_DIRSET GPIO_REG(0x48) +#define GPIO_DIRCLR GPIO_REG(0x4c) + +/* PADC */ +#define PADC_BASE 0x00024000 +#define PADC_REG(X) (PADC_BASE + (X)) +#define PADC_MUX(pin) PADC_REG(((pin) << 2)) +#define PADC_PUEN PADC_REG(0x80) +#define PADC_PDEN PADC_REG(0x84) +#define PADC_SRC PADC_REG(0x88) +#define PADC_DCC PADC_REG(0x8c) +#define PADC_OD PADC_REG(0x94) +#define PADC_AVAIL PADC_REG(0x98) +#define PADC_MUX_M 0x7 + +/* ICU defined */ +#define ICU_BASE 0x00010000 +#define ICU_REG(X) (ICU_BASE + (X)) +#define ICU_IMSR ICU_REG(0x40) +#define ICU_IMER ICU_REG(0x44) +#define ICU_IMOSR ICU_REG(0x48) +#define ICU_DMA_TX_STATUS ICU_REG(0x50) +#define ICU_DMA_RX_STATUS ICU_REG(0x54) +#define ICU_DMA_TX_IMER ICU_REG(0x58) +#define ICU_DMA_RX_IMER ICU_REG(0x5C) +#define ICU_DMA_TX_IMOSR ICU_REG(0x60) +#define ICU_DMA_RX_IMOSR ICU_REG(0x64) + +#define PPE2HOST_INT0 BIT(0) +#define PPE2HOST_INT1 BIT(1) +#define DYING_GASP_INT BIT(3) +#define MEI_IRQ BIT(8) +#define ACA_XBAR_INT BIT(9) +#define MODEM_XBAR_INT BIT(12) +#define LED0_INT BIT(13) +#define LED1_INT BIT(14) +#define NMI_PLL BIT(15) +#define DMA_TX BIT(16) +#define DMA_RX BIT(17) +#define ACA_HOSTIF_TX BIT(20) +#define ACA_HOSTIF_RX BIT(21) +#define ACA_RXOUT_PD_RING_FULL BIT(22) +#define ACA_TXOUT_PD_RING_FULL BIT(23) + +#define ICU_TOP_ALL 0x0003f30B /* Except ACA related */ +#define ICU_DMA_TX_ALL 0x003f03FF +#define ICU_DMA_RX_ALL 0x003F03FF + +#define wr32(value, reg) (writel(value, (priv->mem + (reg)))) +#define rd32(reg) (readl(priv->mem + (reg))) +#define wrfl() ((void)rd32(RCU_STAT)) + +#define wr32_mask(clr, set, reg) \ + wr32(((rd32(reg) & ~(clr)) | (set)), (reg)) + +#endif /* REGS_H */ diff --git a/package/kernel/lantiq/vrx518_ep/src/test/Makefile b/package/kernel/lantiq/vrx518_ep/src/test/Makefile new file mode 100644 index 00000000000..d9e5d43e4aa --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/test/Makefile @@ -0,0 +1,2 @@ + +obj-$(CONFIG_TEST) += ep_test.o \ No newline at end of file diff --git a/package/kernel/lantiq/vrx518_ep/src/test/ep_test.c b/package/kernel/lantiq/vrx518_ep/src/test/ep_test.c new file mode 100644 index 00000000000..ab6139b73ee --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/test/ep_test.c @@ -0,0 +1,924 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux Test driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ep_test.h" + +#define DRV_VERSION "1.0.0" +static const char ep_test_driver_version[] = DRV_VERSION; +static struct dc_ep_dev pcie_dev[DC_EP_MAX_PEER + 1]; +static int ppe_irq_num; + +#define ep_wr32(value, reg) (writel(value, dev->membase + reg)) +#define ep_rd32(reg) (readl(dev->membase + reg)) + +#define ep_wr32_mask(clr, set, reg) \ + ep_wr32(((ep_rd32(reg) & ~(clr)) | (set)), (reg)) + +struct aca_hd_desc { + void *base; + dma_addr_t phy_base; + size_t size;/* in bytes */ +}; + +struct aca_hd_desc_cfg { + struct aca_hd_desc txin; + struct aca_hd_desc txout; + struct aca_hd_desc rxout; +}; + +static struct aca_hd_desc_cfg aca_soc_hd_desc[DC_EP_MAX_PEER + 1]; + +static void ep_mem_write(u8 __iomem *dst, const void *src, size_t len) +{ + int i; + const u32 *src_addr = src; + + if (len % 4) + pr_info("Warning!!: Copy len is not multiple of 4\n"); + + len = len >> 2; + + for (i = 0; i < len; i++) + writel(src_addr[i], (dst + (i << 2))); +} + +static irqreturn_t dc_ep_ppe_intr(int irq, void *dev_id) +{ + struct dc_ep_dev *dev = dev_id; + + ppe_irq_num++; + if (ep_rd32(MBOX_IGU0_ISR) == 0) { + pr_err("Fatal error, dummy interrupt\n"); + return IRQ_NONE; + } + + ep_wr32(PPE_MBOX_TEST_BIT, MBOX_IGU0_ISRC); + ep_rd32(MBOX_IGU0_ISR); + return IRQ_HANDLED; +} + +static void dc_ep_ppe_mbox_reg_dump(struct dc_ep_dev *dev) +{ + pr_info("MBOX_IGU0_ISRS addr %p data 0x%08x\n", + dev->membase + MBOX_IGU0_ISRS, + ep_rd32(MBOX_IGU0_ISRS)); + pr_info("MBOX_IGU0_ISRC addr %p data 0x%08x\n", + dev->membase + MBOX_IGU0_ISRC, + ep_rd32(MBOX_IGU0_ISRC)); + pr_info("MBOX_IGU0_ISR addr %p data 0x%08x\n", + dev->membase + MBOX_IGU0_ISR, + ep_rd32(MBOX_IGU0_ISR)); + pr_info("MBOX_IGU0_IER addr %p data 0x%08x\n", + dev->membase + MBOX_IGU0_IER, + ep_rd32(MBOX_IGU0_IER)); +} + +#define PPE_INT_TIMEOUT 10 +static int dc_ep_ppe_mbox_int_stress_test(struct dc_ep_dev *dev) +{ + int i; + int j; + int ret; + + /* Clear it first */ + ep_wr32(PPE_MBOX_TEST_BIT, MBOX_IGU0_ISRC); + + ret = request_irq(dev->irq, dc_ep_ppe_intr, 0, "PPE_MSI", dev); + if (ret) { + pr_err("%s request irq %d failed\n", __func__, dev->irq); + return -1; + } + pr_info("PPE test\n"); + ep_wr32(PPE_MBOX_TEST_BIT, MBOX_IGU0_IER); + ppe_irq_num = 0; + /* Purposely trigger interrupt */ + for (i = 0; i < PPE_MBOX_IRQ_TEST_NUM; i++) { + j = 0; + while ((ep_rd32(MBOX_IGU0_ISR) & PPE_MBOX_TEST_BIT)) { + j++; + if (j > PPE_INT_TIMEOUT) + break; + } + ep_wr32(PPE_MBOX_TEST_BIT, MBOX_IGU0_ISRS); + /* Write flush */ + ep_rd32(MBOX_IGU0_ISR); + } + mdelay(10); + pr_info("irq triggered %d expected %d\n", ppe_irq_num, + PPE_MBOX_IRQ_TEST_NUM); + dc_ep_ppe_mbox_reg_dump(dev); + ppe_irq_num = 0; + return 0; +} + +static void umt_txin_send(struct dc_ep_dev *dev, + u8 __iomem *soc_dbase, int num) +{ + int i; + struct aca_dma_desc desc; + + memset(&desc, 0, sizeof(desc)); + desc.own = 0; + desc.sop = 1; + desc.eop = 1; + desc.dic = 1; + desc.pdu_type = 1; + desc.data_len = 127; + desc.data_pointer = 0x26000000; + desc.dw1 = 0x700; + desc.dw0 = 0x0000007f; + + for (i = 0; i < num; i++) { + desc.data_pointer += roundup(desc.data_len, 4); + ep_mem_write(soc_dbase + i * sizeof(desc), + (void *)&desc, sizeof(desc)); + } + + ep_wr32(num, TXIN_HD_ACCUM_ADD); +} + +static void ppe_txout_send(struct dc_ep_dev *dev, + u8 __iomem *ppe_sb_base, int num) +{ + int i; + struct aca_dma_desc_2dw desc; + + memset(&desc, 0, sizeof(desc)); + desc.status.field.own = 1; + desc.status.field.sop = 1; + desc.status.field.eop = 1; + desc.status.field.data_len = 127; + desc.data_pointer = 0x26100000; + + for (i = 0; i < num; i++) { + desc.data_pointer += roundup(desc.status.field.data_len, 4); + ep_mem_write(ppe_sb_base + i * sizeof(desc), + (void *)&desc, sizeof(desc)); + } + + ep_wr32(num, TXOUT_ACA_ACCUM_ADD); +} + +static void ppe_rxout_send(struct dc_ep_dev *dev, + u8 __iomem *ppe_sb_base, int num) +{ + int i; + struct aca_dma_desc_2dw desc; + + memset(&desc, 0, sizeof(desc)); + desc.status.field.own = 0; + desc.status.field.sop = 1; + desc.status.field.eop = 1; + desc.status.field.meta_data0 = 0x3; + desc.status.field.meta_data1 = 0x7f; + desc.status.field.data_len = 127; + desc.data_pointer = 0x26200000; + + for (i = 0; i < num; i++) { + desc.data_pointer += roundup(desc.status.field.data_len, 4); + ep_mem_write(ppe_sb_base + i * sizeof(desc), + (void *)&desc, sizeof(desc)); + } + + ep_wr32(num, RXOUT_ACA_ACCUM_ADD); +} + +static void dc_aca_test_init(struct dc_ep_dev *dev, void *soc_base) +{ + umt_txin_send(dev, (u8 __iomem *)soc_base, 8); + ppe_txout_send(dev, (TXOUT_PD_DBASE + dev->membase), 8); + ppe_rxout_send(dev, (RXOUT_PD_DBASE + dev->membase), 8); +} + +static const char *sysclk_str[SYS_CLK_MAX] = { + "36MHz", + "288MHz", +}; + +static const char *ppeclk_str[PPE_CLK_MAX] = { + "36MHz", + "576MHz", + "494MHz", + "432MHz", + "288MHz", +}; + +#define ACA_PMU_CTRL 0x11C +#define ACA_PMU_DMA BIT(2) +#define ACA_PMU_EMA BIT(22) + +enum { + DMA_ENDIAN_TYPE0 = 0, + DMA_ENDIAN_TYPE1, /*!< Byte Swap(B0B1B2B3 => B1B0B3B2) */ + DMA_ENDIAN_TYPE2, /*!< Word Swap (B0B1B2B3 => B2B3B0B1) */ + DMA_ENDIAN_TYPE3, /*!< DWord Swap (B0B1B2B3 => B3B2B1B0) */ + DMA_ENDIAN_MAX, +}; + +#ifdef CONFIG_CPU_BIG_ENDIAN +#define DMA_ENDIAN_DEFAULT DMA_ENDIAN_TYPE3 +#else +#define DMA_ENDIAN_DEFAULT DMA_ENDIAN_TYPE0 +#endif + +enum { + DMA_BURSTL_2DW = 1, /*!< 2 DWORD DMA burst length */ + DMA_BURSTL_4DW = 2, /*!< 4 DWORD DMA burst length */ + DMA_BURSTL_8DW = 3, /*!< 8 DWORD DMA burst length */ + DMA_BURSTL_16DW = 16, +}; + +#define DMA_BURSTL_DEFAULT DMA_BURSTL_16DW + +#define DMA_TX_PORT_DEFAULT_WEIGHT 1 +/** Default Port Transmit weight value */ +#define DMA_TX_CHAN_DEFAULT_WEIGHT 1 + +enum { + DMA_RX_CH = 0, /*!< Rx channel */ + DMA_TX_CH = 1, /*!< Tx channel */ +}; + +enum { + DMA_PKT_DROP_DISABLE = 0, + DMA_PKT_DROP_ENABLE, +}; + +#ifdef CONFIG_CPU_BIG_ENDIAN +/* 2 DWs format descriptor */ +struct rx_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 own:1; + u32 c:1; + u32 sop:1; + u32 eop:1; + u32 meta:2; + u32 byte_offset:3; + u32 meta_data:7; + u32 data_len:16; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); + +struct tx_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 own:1; + u32 c:1; + u32 sop:1; + u32 eop:1; + u32 meta:2; + u32 byte_offset:3; + u32 meta_data:7; + u32 data_len:16; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); +#else +/* 2 DWs format descriptor */ +struct rx_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 data_len:16; + u32 meta_data:7; + u32 byte_offset:3; + u32 meta:2; + u32 eop:1; + u32 sop:1; + u32 c:1; + u32 own:1; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); + +struct tx_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 data_len:16; + u32 meta_data:7; + u32 byte_offset:3; + u32 meta:2; + u32 eop:1; + u32 sop:1; + u32 c:1; + u32 own:1; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); +#endif + +enum { + SOC_TO_EP = 0, + EP_TO_SOC, +}; + +static int dma_pkt_size = 1024; +static int dma_mode = SOC_TO_EP; +static int dma_burst = 16; +static int desc_num = 32; + +module_param(dma_pkt_size, int, 0); +MODULE_PARM_DESC(dma_pkt_size, "Single packet length"); + +module_param(dma_mode, int, 0); +MODULE_PARM_DESC(dma_mode, "mode 0 -- Soc->EP, mode 1-- EP->SoC"); + + +static void dma_ctrl_rst(struct dc_ep_dev *dev) +{ + ep_wr32_mask(ACA_PMU_DMA | ACA_PMU_EMA, 0, ACA_PMU_CTRL); + + udelay(10); + ep_wr32_mask(0, 1, DMA_CTRL); + udelay(10); + ep_wr32(0, DMA_CLC); +} + +static void dma_chan_rst(struct dc_ep_dev *dev, int cn) +{ + ep_wr32(cn, DMA_CS); + ep_wr32(0x2, DMA_CCTRL); + while (ep_rd32(DMA_CCTRL) & 0x01) + udelay(10); +} + +static void dma_port_cfg(struct dc_ep_dev *dev) +{ + u32 reg = 0; + + reg |= (DMA_TX_PORT_DEFAULT_WEIGHT << 12); + reg |= (DMA_ENDIAN_TYPE0 << 10); + reg |= (DMA_ENDIAN_TYPE0 << 8); + reg |= (DMA_PKT_DROP_DISABLE << 6); + reg |= 0x3; + ep_wr32(0, DMA_PS); + ep_wr32(reg, DMA_PCTRL); +} + +static void dma_byte_enable(struct dc_ep_dev *dev, int enable) +{ + if (enable) + ep_wr32_mask(0, BIT(9), DMA_CTRL); + else + ep_wr32_mask(BIT(9), 0, DMA_CTRL); +} + +static void dma_tx_ch_cfg(struct dc_ep_dev *dev, int ch, u32 desc_base, + u32 desc_phys, dma_addr_t data_base, int desc_num) +{ + int i; + struct tx_desc_2dw *tx_desc; + + for (i = 0; i < desc_num; i++) { + tx_desc = (struct tx_desc_2dw *) + (desc_base + (i * sizeof(*tx_desc))); + tx_desc->data_pointer = (((u32)(data_base + + (i * dma_pkt_size))) & 0xfffffff8); + tx_desc->status.word = 0; + tx_desc->status.field.byte_offset = 0; + tx_desc->status.field.data_len = dma_pkt_size; + + tx_desc->status.field.sop = 1; + tx_desc->status.field.eop = 1; + tx_desc->status.field.own = 1; + wmb(); + #if 0 + pr_info("Tx desc num %d word 0x%08x data pointer 0x%08x\n", + i, tx_desc->status.word, tx_desc->data_pointer); + #endif + } + ep_wr32(ch, DMA_CS); + ep_wr32(desc_phys, DMA_CDBA); + ep_wr32(desc_num, DMA_CDLEN); + ep_wr32(0, DMA_CIE); +} + +static void dma_rx_ch_cfg(struct dc_ep_dev *dev, int ch, u32 desc_base, + u32 desc_phys, dma_addr_t data_base, int desc_num) +{ + int i; + struct rx_desc_2dw *rx_desc; + + for (i = 0; i < desc_num; i++) { + rx_desc = (struct rx_desc_2dw *)(desc_base + + (i * sizeof(*rx_desc))); + rx_desc->data_pointer = (((u32)(data_base + + (i * dma_pkt_size))) & 0xfffffff8); + + rx_desc->status.word = 0; + rx_desc->status.field.sop = 1; + rx_desc->status.field.eop = 1; + rx_desc->status.field.byte_offset = 0; + rx_desc->status.field.data_len = dma_pkt_size; + rx_desc->status.field.own = 1; /* DMA own the descriptor */ + wmb(); + #if 0 + pr_info("Rx desc num %d word 0x%08x data pointer 0x%08x\n", + i, rx_desc->status.word, rx_desc->data_pointer); + #endif + } + + ep_wr32(ch, DMA_CS); + ep_wr32(desc_phys, DMA_CDBA); + ep_wr32(desc_num, DMA_CDLEN); + ep_wr32(0, DMA_CIE); +} + +static void dma_chan_on(struct dc_ep_dev *dev, u8 cn) +{ + ep_wr32(cn, DMA_CS); + ep_wr32_mask(0, BIT(0), DMA_CCTRL); +} + +static void dma_chan_off(struct dc_ep_dev *dev, u8 cn) +{ + ep_wr32(cn, DMA_CS); + ep_wr32_mask(BIT(0), 0, DMA_CCTRL); + udelay(10); +} + +#define DEFAULT_TEST_PATTEN 0x12345678 + +#define REG32(addr) (*((volatile u32*)(addr))) + +#ifdef CONFIG_CPU_BIG_ENDIAN +#define ___swab32(x) ((u32)( \ + (((u32)(x) & (u32)0x000000ffUL) << 24) | \ + (((u32)(x) & (u32)0x0000ff00UL) << 8) | \ + (((u32)(x) & (u32)0x00ff0000UL) >> 8) | \ + (((u32)(x) & (u32)0xff000000UL) >> 24))) +#else +#define ___swab32(x) (x) +#endif + +static void dma_sdram_preload(void *sdram_data_tx_ptr, void *sdram_data_rx_ptr) +{ + int i; + int j; + + u32 testaddr = (u32)sdram_data_tx_ptr; + + for (i = 0; i < desc_num; i++) { + for (j = 0; j < dma_pkt_size; j = j + 4) { + REG32(testaddr + i * dma_pkt_size + j) + = DEFAULT_TEST_PATTEN; + } + } + pr_info("SDR Preload(0x55aa00ff) with data on TX location done\n"); + + testaddr = (u32)sdram_data_rx_ptr; + pr_info("RX Preload start address:0x%08x\n", (u32)(testaddr)); + + for (i = 0; i < desc_num; i++) { + for (j = 0; j < roundup(dma_pkt_size, + dma_burst << 2); j = j + 4) + REG32(testaddr + i * dma_pkt_size + j) = 0xcccccccc; + } + pr_info("SDR locations for Memcopy RX preset to 0xcccccccc done\n"); +} + +static void memcopy_data_check(u32 rx_data_addr) +{ + int i, j; + u32 read_data; + + for (i = 0; i < desc_num; i++) { + for (j = 0; j < dma_pkt_size; j = j + 4) { + read_data = REG32(rx_data_addr + i * dma_pkt_size + j); + if (read_data != ___swab32(DEFAULT_TEST_PATTEN)) + pr_info("Memcopy ERROR at addr 0x%08x data 0x%08x\n", + (rx_data_addr + j), read_data); + } + } +} + +static u32 plat_throughput_calc(u32 payload, int cycles) +{ + return (u32)((payload * 300) / cycles); +} + +#define DMA_CPOLL_CNT_MASK 0xFFF0u + +static void dma_ctrl_global_polling_enable(struct dc_ep_dev *dev, int interval) +{ + u32 reg = 0; + + reg |= (1 << 31); + reg |= (interval << 4); + + ep_wr32_mask(DMA_CPOLL_CNT_MASK, + reg, DMA_CPOLL); +} + +static void dma_controller_cfg(struct dc_ep_dev *dev) +{ + ep_wr32_mask(0, BIT(31), DMA_CTRL); + ep_wr32_mask(BIT(30), 0, DMA_CTRL); + ep_wr32_mask(0, BIT(1), DMA_CTRL); + ep_wr32_mask(0, BIT(13), DMA_CTRL); +} + +#define PDRAM_OFFSET 0x200200 +#define PDRAM_TX_DESC_OFFSET 0x200000 +#define PDRAM_RX_DESC_OFFSET 0x200100 +#define ACA_SRAM_OFFSET 0x100000 +#define PPE_SB_TX_DESC_OFFSET 0x280000 +#define PPE_SB_RX_DESC_OFFSET 0x281000 + +#define PPE_FPI_TX_DESC_OFFSET 0x320000 +#define PPE_FPI_RX_DESC_OFFSET 0x321000 + +static void dma_test(struct dc_ep_dev *dev, int mode, int rcn, int tcn) +{ + u32 loop = 0; + void *tx_data; + void *rx_data; + dma_addr_t tx_data_phys = 0; + dma_addr_t rx_data_phys = 0; + u32 start, end; + u32 cycles; + struct rx_desc_2dw *rx_desc; + struct tx_desc_2dw *tx_desc; + struct tx_desc_2dw *last_tx_desc; + struct rx_desc_2dw *last_rx_desc; + dma_addr_t tx_desc_phys; + dma_addr_t rx_desc_phys; + u32 membase = (u32)(dev->membase); + + rx_desc = (struct rx_desc_2dw *)(membase + PDRAM_RX_DESC_OFFSET); + rx_desc_phys = (dev->phy_membase + PDRAM_RX_DESC_OFFSET); + tx_desc = (struct tx_desc_2dw *)(membase + PDRAM_TX_DESC_OFFSET); + tx_desc_phys = (dev->phy_membase + PDRAM_TX_DESC_OFFSET); + last_rx_desc = rx_desc + (desc_num - 1); + last_tx_desc = tx_desc + (desc_num - 1); + + if (mode == SOC_TO_EP) { /* Read from SoC DDR to local PDBRAM */ + tx_data = dma_alloc_coherent(NULL, + desc_num * dma_pkt_size, &tx_data_phys, GFP_DMA); + rx_data_phys = (dma_addr_t)(dev->phy_membase + PDRAM_OFFSET); + rx_data = (void *)(membase + PDRAM_OFFSET); + } else { /* Write from local PDBRAM to remote DDR */ + tx_data_phys = (dma_addr_t)(dev->phy_membase + PDRAM_OFFSET); + tx_data = (void *)(membase + PDRAM_OFFSET); + rx_data = dma_alloc_coherent(NULL, desc_num * dma_pkt_size, + &rx_data_phys, GFP_DMA); + } + + pr_info("tx_desc_base %p tx_desc_phys 0x%08x tx_data %p tx_data_phys 0x%08x\n", + tx_desc, (u32)tx_desc_phys, tx_data, (u32)tx_data_phys); + + pr_info("rx_desc_base %p rx_desc_phys 0x%08x rx_data %p rx_data_phys 0x%08x\n", + rx_desc, (u32)rx_desc_phys, rx_data, (u32)rx_data_phys); + + pr_info("dma burst %d desc number %d packet size %d\n", + dma_burst, desc_num, dma_pkt_size); + + dma_ctrl_rst(dev); + dma_chan_rst(dev, rcn); + dma_chan_rst(dev, tcn); + dma_port_cfg(dev); + dma_controller_cfg(dev); + dma_byte_enable(dev, 1); + + dma_ctrl_global_polling_enable(dev, 24); + + dma_sdram_preload(tx_data, rx_data); + + dma_tx_ch_cfg(dev, tcn, (u32)tx_desc, tx_desc_phys, + tx_data_phys, desc_num); + dma_rx_ch_cfg(dev, rcn, (u32)rx_desc, rx_desc_phys, + rx_data_phys, desc_num); + + udelay(5); /* Make sure that RX descriptor prefetched */ + + start = get_cycles(); + dma_chan_on(dev, rcn); + dma_chan_on(dev, tcn); + + /* wait till tx chan desc own is 0 */ + while (last_tx_desc->status.field.own == 1) { + loop++; + udelay(1); + } + end = get_cycles(); + cycles = end - start; + pr_info("cylces %d throughput %dMb\n", cycles, + plat_throughput_calc(desc_num * dma_pkt_size * 8, cycles)); + pr_info("loop times %d\n", loop); + while (last_rx_desc->status.field.own == 1) { + loop++; + udelay(1); + } + + memcopy_data_check((u32)rx_data); + dma_chan_off(dev, rcn); + dma_chan_off(dev, tcn); + if (mode == SOC_TO_EP) { + dma_free_coherent(NULL, desc_num * dma_pkt_size, + tx_data, tx_data_phys); + } else { + dma_free_coherent(NULL, desc_num * dma_pkt_size, + rx_data, rx_data_phys); + } +} + +static int aca_soc_desc_alloc(int dev) +{ + dma_addr_t phy_addr; + void *base; + u32 size; + + if (dev < 0 || dev > (DC_EP_MAX_PEER + 1)) + return -EINVAL; + + /* TXIN */ + size = TXIN_SOC_DES_NUM * TXIN_HD_DES_SIZE * 4; + base = dma_alloc_coherent(NULL, size, &phy_addr, GFP_DMA); + if (!base) + goto txin; + aca_soc_hd_desc[dev].txin.base = base; + aca_soc_hd_desc[dev].txin.phy_base = phy_addr; + aca_soc_hd_desc[dev].txin.size = size; + pr_info("txin soc desc base %p phy 0x%08x size 0x%08x\n", + base, (u32)phy_addr, size); + + /* TXOUT */ + size = TXOUT_SOC_DES_NUM * TXOUT_HD_DES_SIZE * 4; + base = dma_alloc_coherent(NULL, size, &phy_addr, GFP_DMA); + if (!base) + goto txout; + aca_soc_hd_desc[dev].txout.base = base; + aca_soc_hd_desc[dev].txout.phy_base = phy_addr; + aca_soc_hd_desc[dev].txout.size = size; + pr_info("txout soc desc base %p phy 0x%08x size 0x%08x\n", + base, (u32)phy_addr, size); + /* RXOUT */ + size = RXOUT_SOC_DES_NUM * RXOUT_HD_DES_SIZE * 4; + base = dma_alloc_coherent(NULL, size, &phy_addr, GFP_DMA); + if (!base) + goto rxout; + aca_soc_hd_desc[dev].rxout.base = base; + aca_soc_hd_desc[dev].rxout.phy_base = phy_addr; + aca_soc_hd_desc[dev].rxout.size = size; + pr_info("rxout soc desc base %p phy 0x%08x size 0x%08x\n", + base, (u32)phy_addr, size); + return 0; +rxout: + dma_free_coherent(NULL, aca_soc_hd_desc[dev].txout.size, + aca_soc_hd_desc[dev].txout.base, + aca_soc_hd_desc[dev].txout.phy_base); +txout: + dma_free_coherent(NULL, aca_soc_hd_desc[dev].txin.size, + aca_soc_hd_desc[dev].txin.base, + aca_soc_hd_desc[dev].txin.phy_base); +txin: + return -ENOMEM; +} + +static int aca_soc_desc_free(int dev) +{ + dma_addr_t phy_addr; + void *base; + size_t size; + + if (dev < 0 || dev > (DC_EP_MAX_PEER + 1)) + return -EINVAL; + + /* TXIN */ + base = aca_soc_hd_desc[dev].txin.base; + phy_addr = aca_soc_hd_desc[dev].txin.phy_base; + size = aca_soc_hd_desc[dev].txin.size; + dma_free_coherent(NULL, size, base, phy_addr); + + /* TXOUT */ + base = aca_soc_hd_desc[dev].txout.base; + phy_addr = aca_soc_hd_desc[dev].txout.phy_base; + size = aca_soc_hd_desc[dev].txout.size; + dma_free_coherent(NULL, size, base, phy_addr); + + /* RXOUT */ + base = aca_soc_hd_desc[dev].rxout.base; + phy_addr = aca_soc_hd_desc[dev].rxout.phy_base; + size = aca_soc_hd_desc[dev].rxout.size; + dma_free_coherent(NULL, size, base, phy_addr); + return 0; +} + +static int __init dc_ep_test_init(void) +{ + int i, j; + int dev_num; + struct dc_ep_dev dev; + int func = 0; + u32 sysclk = 0; + u32 ppeclk = 0; + + if (dc_ep_dev_num_get(&dev_num)) { + pr_err("%s failed to get total device number\n", __func__); + return -EIO; + } + + pr_info("%s: total %d EPs found\n", __func__, dev_num); + + for (i = 0; i < dev_num; i++) + aca_soc_desc_alloc(i); + + for (i = 0; i < dev_num; i++) { + struct aca_param aca_cfg = { + .aca_txin = { + .soc_desc_base + = aca_soc_hd_desc[i].txin.phy_base, + .soc_desc_num = TXIN_SOC_DES_NUM, + .pp_buf_desc_num = 32, + .pd_desc_base = TXIN_PD_DBASE, + .pd_desc_num = TXIN_PD_DES_NUM, + .hd_size_in_dw = TXIN_HD_DES_SIZE, + .pd_size_in_dw = TXIN_PD_DES_SIZE, + .byteswap = 1, + }, + .aca_txout = { + .soc_desc_base + = aca_soc_hd_desc[i].txout.phy_base, + .soc_desc_num = TXOUT_SOC_DES_NUM, + .pp_buf_desc_num = 32, + .pd_desc_base = TXOUT_PD_DBASE, + .pd_desc_num = TXOUT_PD_DES_NUM, + .hd_size_in_dw = TXOUT_HD_DES_SIZE, + .pd_size_in_dw = TXOUT_PD_DES_SIZE, + .byteswap = 1, + }, + .aca_rxout = { + .soc_desc_base + = aca_soc_hd_desc[i].rxout.phy_base, + .soc_desc_num = RXOUT_SOC_DES_NUM, + .pp_buf_desc_num = 32, + .pd_desc_base = RXOUT_PD_DBASE, + .pd_desc_num = RXOUT_PD_DES_NUM, + .hd_size_in_dw = RXOUT_HD_DES_SIZE, + .pd_size_in_dw = RXOUT_PD_DES_SIZE, + .byteswap = 1, + }, + }; + struct aca_modem_param modem_cfg = { + .mdm_txout = { + .stat = SB_XBAR_ADDR(__TX_OUT_ACA_ACCUM_STATUS), + .pd = SB_XBAR_ADDR(__TX_OUT_QUEUE_PD_BASE_ADDR_OFFSET), + .acc_cnt = SB_XBAR_ADDR(__TX_OUT_ACA_ACCUM_COUNT), + }, + .mdm_rxout = { + .stat = SB_XBAR_ADDR(__RX_OUT_ACA_ACCUM_STATUS), + .pd = SB_XBAR_ADDR(__RX_OUT_QUEUE_PD_BASE_ADDR_OFFSET), + .acc_cnt = SB_XBAR_ADDR(__RX_OUT_ACA_ACCUM_COUNT), + }, + .mdm_rxin = { + .stat = SB_XBAR_ADDR(__RX_IN_ACA_ACCUM_STATUS), + .pd = SB_XBAR_ADDR(__RX_IN_QUEUE_PD_BASE_ADDR_OFFSET), + .acc_cnt = SB_XBAR_ADDR(__RX_IN_ACA_ACCUM_COUNT), + }, + }; + if (dc_ep_dev_info_req(i, DC_EP_INT_PPE, &dev)) + pr_info("%s failed to get pcie ep %d information\n", + __func__, i); + pr_info("irq %d\n", dev.irq); + pr_info("phyiscal membase 0x%08x virtual membase 0x%p\n", + dev.phy_membase, dev.membase); + if (dev_num > 1) { + for (j = 0; j < dev.peer_num; j++) { + pr_info("phyiscal peer membase 0x%08x virtual peer membase 0x%p\n", + dev.peer_phy_membase[j], dev.peer_membase[j]); + } + } + /* For module unload perpose */ + memcpy(&pcie_dev[i], &dev, sizeof(struct dc_ep_dev)); + dc_ep_ppe_mbox_int_stress_test(&pcie_dev[i]); + dev.hw_ops->clk_on(&dev, PMU_CDMA | PMU_EMA | PMU_PPM2); + dev.hw_ops->clk_set(&dev, SYS_CLK_288MHZ, PPE_CLK_576MHZ); + dev.hw_ops->pinmux_set(&dev, 14, MUX_FUNC_ALT1); + dev.hw_ops->pinmux_set(&dev, 15, MUX_FUNC_ALT2); + dev.hw_ops->pinmux_get(&dev, 15, &func); + pr_info("gpio 15 func %d\n", func); + dev.hw_ops->pinmux_set(&dev, 13, MUX_FUNC_GPIO); + dev.hw_ops->gpio_dir(&dev, 13, GPIO_DIR_OUT); + dev.hw_ops->gpio_set(&dev, 13, 1); + dev.hw_ops->gpio_get(&dev, 13, &func); + pr_info("gpio 13 value %d\n", func); + dev.hw_ops->gpio_pupd_set(&dev, 14, GPIO_PULL_DOWN); + dev.hw_ops->gpio_od_set(&dev, 0, 1); + dev.hw_ops->gpio_src_set(&dev, 0, GPIO_SLEW_RATE_FAST); + dev.hw_ops->gpio_dcc_set(&dev, 0, GPIO_DRV_CUR_8MA); + dev.hw_ops->clk_get(&dev, &sysclk, &ppeclk); + pr_info("ppe clk %s sys clk %s\n", ppeclk_str[ppeclk], + sysclk_str[sysclk]); + dev.hw_ops->aca_init(&dev, &aca_cfg, &modem_cfg); + dev.hw_ops->aca_start(&dev, ACA_ALL_EN, 1); + + pr_info("ACA test\n"); + dc_aca_test_init(&dev, aca_soc_hd_desc[i].txin.base); + + pr_info("DMA test\n"); + dma_pkt_size = 64; + dma_test(&dev, dma_mode, 0, 1); +#if 0 + dma_pkt_size = 128; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 256; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 512; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 1024; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 2048; + dma_test(&dev, dma_mode, 0, 1); + + dma_mode = EP_TO_SOC; + dma_pkt_size = 64; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 128; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 256; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 512; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 1024; + dma_test(&dev, dma_mode, 0, 1); + dma_pkt_size = 2048; + dma_test(&dev, dma_mode, 0, 1); +#endif + } + + pr_info("Intel(R) SmartPHY DSL(VRX518) PCIe EP Test Driver - %s\n", + ep_test_driver_version); + return 0; +} + +static void __exit dc_ep_test_exit(void) +{ + int i; + int dev_num; + u32 func = ACA_ALL_EN; + struct dc_ep_dev *dev; + + if (dc_ep_dev_num_get(&dev_num)) { + pr_err("%s failed to get total device number\n", __func__); + return; + } + pr_info("%s: total %d EPs found\n", __func__, dev_num); + for (i = 0; i < dev_num; i++) { + dev = &pcie_dev[i]; + free_irq(dev->irq, dev); + dev->hw_ops->aca_stop(dev, &func, 1); + dev->hw_ops->clk_off(dev, PMU_EMA); + if (dc_ep_dev_info_release(i)) { + pr_info("%s failed to release pcie ep %d information\n", + __func__, i); + } + aca_soc_desc_free(i); + } +} + +module_init(dc_ep_test_init); +module_exit(dc_ep_test_exit); + +MODULE_AUTHOR("Intel Corporation, "); +MODULE_DESCRIPTION("Intel(R) SmartPHY (VRX518) PCIe EP/ACA test driver"); +MODULE_LICENSE("GPL"); diff --git a/package/kernel/lantiq/vrx518_ep/src/test/ep_test.h b/package/kernel/lantiq/vrx518_ep/src/test/ep_test.h new file mode 100644 index 00000000000..ef2b847bb26 --- /dev/null +++ b/package/kernel/lantiq/vrx518_ep/src/test/ep_test.h @@ -0,0 +1,273 @@ +/******************************************************************************* + + Intel SmartPHY DSL PCIe Endpoint/ACA Linux driver + Copyright(c) 2016 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + +*******************************************************************************/ + +#ifndef EP_TEST_H +#define EP_TEST_H + +/* SB address on xBar */ +#define SB_XBAR_BASE 0x280000 +#define SB_XBAR_DES_RXBASE SB_XBAR_BASE +#define SB_XBAR_DES_TXBASE (SB_XBAR_BASE + 0x400) +#define SB_XBAR_DATA_BASE (SB_XBAR_BASE + 0x800) +#define SB_XBAR_ADDR(x) (SB_XBAR_BASE + ((((x) - 0xA000)) << 2)) + +/*---------------------------------------------------------- + * ACA Shadow Registers + * 3 * 4 = 12 + * *_STATUS need to be initialized to nonzero by PPE driver + *---------------------------------------------------------- + */ + +#define __ACA_SHADOW_REG_BASE 0xADF0 + +#define __TX_IN_ACA_ACCUM_COUNT 0xADF0 + +#define __TX_IN_ACA_ACCUM_STATUS 0xADF1 + +#define __TX_IN_QUEUE_PD_BASE_ADDR_OFFSET 0xADF2 + +#define __TX_OUT_ACA_ACCUM_COUNT 0xADF3 + +#define __TX_OUT_ACA_ACCUM_STATUS 0xADF4 + +#define __TX_OUT_QUEUE_PD_BASE_ADDR_OFFSET 0xADF5 + +#define __RX_IN_ACA_ACCUM_COUNT 0xADF6 + +#define __RX_IN_ACA_ACCUM_STATUS 0xADF7 + +#define __RX_IN_QUEUE_PD_BASE_ADDR_OFFSET 0xADF8 + +#define __RX_OUT_ACA_ACCUM_COUNT 0xADF9 + +#define __RX_OUT_ACA_ACCUM_STATUS 0xADFA + +#define __RX_OUT_QUEUE_PD_BASE_ADDR_OFFSET 0xADFB + +#define TXIN_PD_DES_NUM 64 +#define TXIN_PD_DBASE 0x105400 +#define TXIN_SOC_DES_NUM 32 +#define TXIN_SOC_DBASE 0x24000000 +#define TXIN_HOST_DES_NUM 32 +#define TXIN_HD_DES_SIZE 4 /* size in DWORD */ +#define TXIN_PD_DES_SIZE 2 /* size in DWORD */ + +#define TXOUT_PD_DES_NUM 32 +#define TXOUT_PD_DBASE 0x105700 +#define TXOUT_SOC_DES_NUM 32 +#define TXOUT_SOC_DBASE 0x24001000 +#define TXOUT_HOST_DES_NUM 32 +#define TXOUT_HD_DES_SIZE 1 /* size in DWORD */ +#define TXOUT_PD_DES_SIZE 2 /* size in DWORD */ + +#define RXOUT_PD_DES_NUM 32 +#define RXOUT_PD_DBASE 0x105C00 +#define RXOUT_SOC_DES_NUM 32 +#define RXOUT_SOC_DBASE 0x24002000 +#define RXOUT_HOST_DES_NUM 32 +#define RXOUT_HD_DES_SIZE 4 /* size in DWORD */ +#define RXOUT_PD_DES_SIZE 2 /* size in DWORD */ + +/* PPE interrupt */ +#define PPE_MBOX_TEST_BIT 0x1 +#define PPE_MBOX_IRQ_TEST_NUM 100 + +#define PPE_MBOX_BASE 0x334800 + +#define MBOX_REG(X) (PPE_MBOX_BASE + (X)) +#define MBOX_IGU0_ISRS MBOX_REG(0x0) +#define MBOX_IGU0_ISRC MBOX_REG(0x4) +#define MBOX_IGU0_ISR MBOX_REG(0x8) +#define MBOX_IGU0_IER MBOX_REG(0xc) + +#define HOST_IF_BASE 0x50000 +#define HOST_IF_REG(X) (HOST_IF_BASE + (X)) +#define TXIN_CONV_CFG HOST_IF_REG(0x14) +#define RXIN_HD_ACCUM_ADD HOST_IF_REG(0xC8) /* UMT Message trigger */ +#define TXIN_HD_ACCUM_ADD HOST_IF_REG(0xCC) /* UMT Message trigger */ +#define RXOUT_ACA_ACCUM_ADD HOST_IF_REG(0xE0) /* PPE FW tigger */ +#define TXOUT_ACA_ACCUM_ADD HOST_IF_REG(0xE4) /* PPE FW tigger */ + +#define CDMA_BASE 0x2D0000 +#define CDMA_REG(X) (CDMA_BASE + (X)) + +#define DMA_CLC CDMA_REG(0x00) +#define DMA_ID CDMA_REG(0x08) +#define DMA_CTRL CDMA_REG(0x10) + +#define DMA_CTRL_RST BIT(0) +#define DMA_CTRL_DSRAM_PATH BIT(1) +#define DMA_CTRL_CH_FL BIT(6) +#define DMA_CTRL_DS_FOD BIT(7) +#define DMA_CTRL_DRB BIT(8) +#define DMA_CTRL_ENBE BIT(9) +#define DMA_CTRL_PRELOAD_INT_S 10 +#define DMA_CTRL_PRELOAD_INT 0x0C00u +#define DMA_CTRL_PRELOAD_EN BIT(12) +#define DMA_CTRL_MBRST_CNT_S 16 +#define DMA_CTRL_MBRST_CNT 0x3FF0000u +#define DMA_CTRL_MBRSTARB BIT(30) +#define DMA_CTRL_PKTARB BIT(31) + +#define DMA_CPOLL CDMA_REG(0x14) +#define DMA_CPOLL_CNT_S 4 +#define DMA_CPOLL_CNT 0xFFF0u +#define DMA_CPOLL_EN BIT(31) + +#define DMA_CS CDMA_REG(0x18) +#define DMA_CCTRL CDMA_REG(0x1C) +#define DMA_CCTRL_ON BIT(0) +#define DMA_CCTRL_RST BIT(1) +#define DMA_CCTRL_DIR_TX BIT(8) +#define DMA_CCTRL_CLASS_S 9 +#define DMA_CCTRL_CLASS 0xE00u +#define DMA_CCTRL_PRTNR_S 12 +#define DMA_CCTRL_PRTNR 0xF000u +#define DMA_CCTRL_TXWGT_S 16 +#define DMA_CCTRL_TXWGT 0x30000u +#define DMA_CCTRL_CLASSH_S 18 +#define DMA_CCTRL_CLASSH 0xC0000u +#define DMA_CCTRL_PDEN BIT(23) +#define DMA_CCTRL_P2PCPY BIT(24) +#define DMA_CCTRL_LBEN BIT(25) +#define DMA_CCTRL_LBCHNR_S 26 +#define DMA_CCTRL_LBCHNR 0xFC000000u + +#define DMA_CDBA CDMA_REG(0x20) +#define DMA_CDLEN CDMA_REG(0x24) +#define DMA_CIS CDMA_REG(0x28) +#define DMA_CIE CDMA_REG(0x2C) + +#define DMA_CI_EOP BIT(1) +#define DMA_CI_DUR BIT(2) +#define DMA_CI_DESCPT BIT(3) +#define DMA_CI_CHOFF BIT(4) +#define DMA_CI_RDERR BIT(5) +#define DMA_CI_ALL (DMA_CI_EOP | DMA_CI_DUR | DMA_CI_DESCPT\ + | DMA_CI_CHOFF | DMA_CI_RDERR) + +#define DMA_CI_DEFAULT (DMA_CI_EOP | DMA_CI_DESCPT) +#define DMA_CDPTNRD CDMA_REG(0x34) + +#define DMA_PS CDMA_REG(0x40) +#define DMA_PCTRL CDMA_REG(0x44) +#define DMA_PCTRL_RXBL16 BIT(0) +#define DMA_PCTRL_TXBL16 BIT(1) +#define DMA_PCTRL_RXBL_S 2 +#define DMA_PCTRL_RXBL 0xCu +#define DMA_PCTRL_TXBL_S 4 +#define DMA_PCTRL_TXBL 0x30u +#define DMA_PCTRL_PDEN BIT(6) +#define DMA_PCTRL_PDEN_S 6 +#define DMA_PCTRL_RXENDI_S 8 +#define DMA_PCTRL_RXENDI 0x300u +#define DMA_PCTRL_TXENDI_S 10 +#define DMA_PCTRL_TXENDI 0xC00u +#define DMA_PCTRL_TXWGT_S 12 +#define DMA_PCTRL_TXWGT 0x7000u +#define DMA_PCTRL_MEM_FLUSH BIT(16) + +#define DMA_IRNEN CDMA_REG(0xF4) +#define DMA_IRNCR CDMA_REG(0xF8) +#define DMA_IRNICR CDMA_REG(0xFC) + +#ifdef CONFIG_CPU_BIG_ENDIAN +struct aca_dma_desc { + /* DW0 */ + u32 dw0; + /* DW1 */ + u32 dw1; + /* DW2 */ + u32 data_pointer; + /* DW3 */ + u32 own:1; + u32 c:1; + u32 sop:1; + u32 eop:1; + u32 dic:1; + u32 pdu_type:1; + u32 byte_off:3; + u32 qid:4; + u32 mpoa_pt:1; + u32 mpoa_mode:2; + u32 data_len:16; +}__packed __aligned(16); + +/* 2 DWs format descriptor */ +struct aca_dma_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 own:1; + u32 c:1; + u32 sop:1; + u32 eop:1; + u32 meta_data0:2; + u32 byte_offset:3; + u32 meta_data1:7; + u32 data_len:16; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); +#else +struct aca_dma_desc { + /* DW0 */ + u32 dw0; + /* DW1 */ + u32 dw1; + /* DW2 */ + u32 data_pointer; + /* DW 3 */ + u32 data_len:16; + u32 mpoa_mode:2; + u32 mpoa_pt:1; + u32 qid:4; + u32 byte_off:3; + u32 pdu_type:1; + u32 dic:1; + u32 eop:1; + u32 sop:1; + u32 c:1; + u32 own:1; +}__packed __aligned(16); + +/* 2 DWs format descriptor */ +struct aca_dma_desc_2dw { + u32 data_pointer; /* Descriptor data pointer */ + union { + struct { + u32 data_len:16; + u32 meta_data1:7; + u32 byte_offset:3; + u32 meta_data0:2; + u32 eop:1; + u32 sop:1; + u32 c:1; + u32 own:1; + } __packed field; + u32 word; + } __packed status; +} __packed __aligned(8); +#endif +#endif /* EP_TEST_H */ From cfd42a00984dd9a354a8dc3eaaff4deda4c70f2c Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Wed, 21 Aug 2019 08:33:43 +0200 Subject: [PATCH 09/21] ipq40xx: add Intel/Lantiq ATM hacks Similar to the lantiq platform, these are required for DSL support. Signed-off-by: Martin Schiller [switch to kernel 5.10 and 5.15] Signed-off-by: Jan Hoffmann [update patches based on UGW 8.5.2.10, remove 5.10 support] Signed-off-by: Andre Heider --- .../patches-5.15/998-lantiq-atm-hacks.patch | 43 ++++++ .../999-atm-mpoa-intel-dsl-phy-support.patch | 137 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 target/linux/ipq40xx/patches-5.15/998-lantiq-atm-hacks.patch create mode 100644 target/linux/ipq40xx/patches-5.15/999-atm-mpoa-intel-dsl-phy-support.patch diff --git a/target/linux/ipq40xx/patches-5.15/998-lantiq-atm-hacks.patch b/target/linux/ipq40xx/patches-5.15/998-lantiq-atm-hacks.patch new file mode 100644 index 00000000000..c15a4b3ae3e --- /dev/null +++ b/target/linux/ipq40xx/patches-5.15/998-lantiq-atm-hacks.patch @@ -0,0 +1,43 @@ +From: John Crispin +Date: Fri, 3 Aug 2012 10:27:25 +0200 +Subject: [PATCH 04/36] MIPS: lantiq: add atm hack + +Signed-off-by: John Crispin +--- a/include/uapi/linux/atm.h ++++ b/include/uapi/linux/atm.h +@@ -131,8 +131,14 @@ + #define ATM_ABR 4 + #define ATM_ANYCLASS 5 /* compatible with everything */ + ++#define ATM_VBR_NRT ATM_VBR ++#define ATM_VBR_RT 6 ++#define ATM_UBR_PLUS 7 ++#define ATM_GFR 8 ++ + #define ATM_MAX_PCR -1 /* maximum available PCR */ + ++ + struct atm_trafprm { + unsigned char traffic_class; /* traffic class (ATM_UBR, ...) */ + int max_pcr; /* maximum PCR in cells per second */ +@@ -155,6 +161,9 @@ struct atm_trafprm { + unsigned int adtf :10; /* ACR Decrease Time Factor (10-bit) */ + unsigned int cdf :3; /* Cutoff Decrease Factor (3-bit) */ + unsigned int spare :9; /* spare bits */ ++ int scr; /* sustained rate in cells per second */ ++ int mbs; /* maximum burst size (MBS) in cells */ ++ int cdv; /* Cell delay variation */ + }; + + struct atm_qos { +--- a/net/atm/proc.c ++++ b/net/atm/proc.c +@@ -141,7 +141,7 @@ static void *vcc_seq_next(struct seq_fil + static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc) + { + static const char *const class_name[] = { +- "off", "UBR", "CBR", "VBR", "ABR"}; ++ "off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR"}; + static const char *const aal_name[] = { + "---", "1", "2", "3/4", /* 0- 3 */ + "???", "5", "???", "???", /* 4- 7 */ diff --git a/target/linux/ipq40xx/patches-5.15/999-atm-mpoa-intel-dsl-phy-support.patch b/target/linux/ipq40xx/patches-5.15/999-atm-mpoa-intel-dsl-phy-support.patch new file mode 100644 index 00000000000..b774fc39d8c --- /dev/null +++ b/target/linux/ipq40xx/patches-5.15/999-atm-mpoa-intel-dsl-phy-support.patch @@ -0,0 +1,137 @@ +From: Subhra Banerjee +Date: Fri, 31 Aug 2018 12:01:19 +0530 +Subject: [PATCH] UGW_SW-29163: ATM oam support + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2952,6 +2952,22 @@ char *ppp_dev_name(struct ppp_channel *c + return name; + } + ++/* ++ * Return the PPP device interface pointer ++ */ ++struct net_device *ppp_device(struct ppp_channel *chan) ++{ ++ struct channel *pch = chan->ppp; ++ struct net_device *dev = NULL; ++ ++ if (pch) { ++ read_lock_bh(&pch->upl); ++ if (pch->ppp && pch->ppp->dev) ++ dev = pch->ppp->dev; ++ read_unlock_bh(&pch->upl); ++ } ++ return dev; ++} + + /* + * Disconnect a channel from the generic layer. +@@ -3598,6 +3614,7 @@ EXPORT_SYMBOL(ppp_unregister_channel); + EXPORT_SYMBOL(ppp_channel_index); + EXPORT_SYMBOL(ppp_unit_number); + EXPORT_SYMBOL(ppp_dev_name); ++EXPORT_SYMBOL(ppp_device); + EXPORT_SYMBOL(ppp_input); + EXPORT_SYMBOL(ppp_input_error); + EXPORT_SYMBOL(ppp_output_wakeup); +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -74,6 +74,9 @@ extern int ppp_unit_number(struct ppp_ch + /* Get the device name associated with a channel, or NULL if none */ + extern char *ppp_dev_name(struct ppp_channel *); + ++/* Get the device pointer associated with a channel, or NULL if none */ ++extern struct net_device *ppp_device(struct ppp_channel *); ++ + /* + * SMP locking notes: + * The channel code must ensure that when it calls ppp_unregister_channel, +--- a/net/atm/Kconfig ++++ b/net/atm/Kconfig +@@ -56,6 +56,12 @@ config ATM_MPOA + subnetwork boundaries. These shortcut connections bypass routers + enhancing overall network performance. + ++config ATM_MPOA_INTEL_DSL_PHY_SUPPORT ++ bool "Intel DSL Phy MPOA support" ++ depends on ATM && INET && ATM_MPOA!=n ++ help ++ Add support for Intel DSL Phy ATM MPOA ++ + config ATM_BR2684 + tristate "RFC1483/2684 Bridged protocols" + depends on ATM && INET +--- a/net/atm/br2684.c ++++ b/net/atm/br2684.c +@@ -596,6 +596,11 @@ static int br2684_regvcc(struct atm_vcc + atmvcc->push = br2684_push; + atmvcc->pop = br2684_pop; + atmvcc->release_cb = br2684_release_cb; ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* IPoA or EoA w/o FCS */ ++ atm_hook_mpoa_setup(atmvcc, brdev->payload == p_routed ? 3 : 0, ++ brvcc->encaps == BR2684_ENCAPS_LLC ? 1 : 0, net_dev); ++#endif + atmvcc->owner = THIS_MODULE; + + /* initialize netdev carrier state */ +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -137,6 +137,11 @@ static struct proto vcc_proto = { + .release_cb = vcc_release_cb, + }; + ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *) = NULL; ++EXPORT_SYMBOL(atm_hook_mpoa_setup); ++#endif ++ + int vcc_create(struct net *net, struct socket *sock, int protocol, int family, int kern) + { + struct sock *sk; +--- a/net/atm/common.h ++++ b/net/atm/common.h +@@ -53,4 +53,6 @@ int svc_change_qos(struct atm_vcc *vcc,s + + void atm_dev_release_vccs(struct atm_dev *dev); + ++extern void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *); ++ + #endif +--- a/net/atm/mpc.c ++++ b/net/atm/mpc.c +@@ -31,6 +31,7 @@ + /* Modular too */ + #include + ++#include "common.h" + #include "lec.h" + #include "mpc.h" + #include "resources.h" +@@ -645,6 +646,10 @@ static int atm_mpoa_vcc_attach(struct at + vcc->proto_data = mpc->dev; + vcc->push = mpc_push; + ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* IPoA, LLC */ ++ atm_hook_mpoa_setup(vcc, 3, 1, mpc->dev); ++#endif + return 0; + } + +--- a/net/atm/pppoatm.c ++++ b/net/atm/pppoatm.c +@@ -422,6 +422,12 @@ static int pppoatm_assign_vcc(struct atm + atmvcc->user_back = pvcc; + atmvcc->push = pppoatm_push; + atmvcc->pop = pppoatm_pop; ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* PPPoA */ ++ atm_hook_mpoa_setup(atmvcc, 2, ++ pvcc->encaps == e_llc ? 1 : 0, ++ ppp_device(&pvcc->chan)); ++#endif + atmvcc->release_cb = pppoatm_release_cb; + __module_get(THIS_MODULE); + atmvcc->owner = THIS_MODULE; From 474bbe23b7ec72ba84b9b7c91e17a69f58bd88b2 Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Wed, 21 Aug 2019 08:36:05 +0200 Subject: [PATCH 10/21] kernel: add Intel/Lantiq VRX518 TC driver This driver version is also included in Intel UGW 8.5.2.10. Signed-off-by: Martin Schiller [updated for kernel 5.10] Signed-off-by: Jan Hoffmann [update to 1.5.12.4, switch to tag tarball] Signed-off-by: Andre Heider [add working software data path] Signed-off-by: Jan Hoffmann Signed-off-by: Andre Heider --- package/kernel/lantiq/vrx518_tc/Makefile | 74 + .../lantiq/vrx518_tc/patches/100-compat.patch | 859 +++++++++++ .../lantiq/vrx518_tc/patches/200-swplat.patch | 1356 +++++++++++++++++ .../vrx518_tc/patches/201-desc-length.patch | 342 +++++ .../lantiq/vrx518_tc/patches/202-napi.patch | 423 +++++ .../lantiq/vrx518_tc/patches/203-dbg.patch | 120 ++ 6 files changed, 3174 insertions(+) create mode 100644 package/kernel/lantiq/vrx518_tc/Makefile create mode 100644 package/kernel/lantiq/vrx518_tc/patches/100-compat.patch create mode 100644 package/kernel/lantiq/vrx518_tc/patches/200-swplat.patch create mode 100644 package/kernel/lantiq/vrx518_tc/patches/201-desc-length.patch create mode 100644 package/kernel/lantiq/vrx518_tc/patches/202-napi.patch create mode 100644 package/kernel/lantiq/vrx518_tc/patches/203-dbg.patch diff --git a/package/kernel/lantiq/vrx518_tc/Makefile b/package/kernel/lantiq/vrx518_tc/Makefile new file mode 100644 index 00000000000..fde4c07e448 --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/Makefile @@ -0,0 +1,74 @@ +# +# Copyright (C) 2019 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=vrx518_tc +PKG_VERSION:=1.5.12.4 +PKG_RELEASE:=$(AUTORELEASE) +PKG_BASE_NAME:=vrx518_tc_drv + +UGW_VERSION=8.5.2.10 +UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION) + +PKG_SOURCE:=$(UGW_BASENAME).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/ +PKG_HASH:=0c5bb0f9a06dc4cc4bbb8b930d01a673daba1b66615e8328818356d32c8f1548 +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(UGW_BASENAME) +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=LICENSE + +include $(INCLUDE_DIR)/package.mk + +PLAT_DIR:=dcdp +PKG_EXTMOD_SUBDIRS:=$(PLAT_DIR) + +# TODO this driver depends on the vrx518 ppe firmware, add this dependency if +# that ever gets a compatible license +define KernelPackage/$(PKG_NAME) + SECTION:=sys + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=VRX518 TC driver + KCONFIG:= \ + CONFIG_ATM_LANE=m \ + CONFIG_ATM_MPOA=m \ + CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT=y + DEPENDS:=@TARGET_ipq40xx +kmod-vrx518_ep +kmod-crypto-md5 +kmod-atm +kmod-ipoa +br2684ctl + AUTOLOAD:=$(call AutoLoad,27,vrx518_tc) + FILES:=$(PKG_BUILD_DIR)/$(PLAT_DIR)/$(PKG_NAME).ko +endef + +define KernelPackage/$(PKG_NAME)/description + VRX518 TC Driver +endef + +define Build/Prepare + $(PKG_UNPACK) + # eliminate all carriage returns / convert to unix encoding + (cd $(PKG_BUILD_DIR) && find . -type f -exec sed -i 's/\r//g' {} +) + $(Build/Patch) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/net/ + $(CP) $(PKG_BUILD_DIR)/$(PLAT_DIR)/inc/dsl_tc.h $(1)/usr/include/net/ +endef + +EXTRA_CFLAGS:= \ + -I$(STAGING_DIR)/usr/include + +define Build/Compile + $(KERNEL_MAKE) \ + M="$(PKG_BUILD_DIR)/$(PLAT_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + FEATURE_VRX518_CPU=y \ + modules +endef + +$(eval $(call KernelPackage,$(PKG_NAME))) diff --git a/package/kernel/lantiq/vrx518_tc/patches/100-compat.patch b/package/kernel/lantiq/vrx518_tc/patches/100-compat.patch new file mode 100644 index 00000000000..2c92912adef --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/100-compat.patch @@ -0,0 +1,859 @@ +--- a/dcdp/atm_tc.c ++++ b/dcdp/atm_tc.c +@@ -44,9 +44,9 @@ + #include + #include + #include "inc/dsl_tc.h" +-#include ++// #include + #include +-#include ++// #include + #include + #include + #include +@@ -730,20 +730,16 @@ static void atm_aca_init(struct atm_priv + ACA_TXOUT_EN | ACA_RXIN_EN | ACA_RXOUT_EN, 1); + } + +-static int print_datetime(char *buffer, const struct timespec *datetime) ++static int print_datetime(char *buffer, const struct timespec64 *datetime) + { +- struct timeval tv; + struct tm nowtm; + char tmbuf[64]; +- s64 nsec; + + if (buffer == NULL || datetime == NULL) { + pr_err("%s : Invalid arguments\n", __func__); + return -1; + } +- nsec = timespec_to_ns(datetime); +- tv = ns_to_timeval(nsec); +- time_to_tm(tv.tv_sec, 0, &nowtm); ++ time64_to_tm(datetime->tv_sec, 0, &nowtm); + memset(tmbuf, 0, 64); + + snprintf(tmbuf, sizeof(tmbuf), "%ld-%d-%d %d:%d:%d", +@@ -753,7 +749,7 @@ static int print_datetime(char *buffer, + nowtm.tm_hour, + nowtm.tm_min, + nowtm.tm_sec); +- snprintf(buffer, sizeof(buffer), "%s.%06d", tmbuf, (int)tv.tv_usec); ++ snprintf(buffer, sizeof(buffer), "%s.%06d", tmbuf, (int)datetime->tv_nsec / 1000); + + return 0; + } +@@ -1313,7 +1309,7 @@ static int ppe_send(struct atm_vcc *vcc, + /* assume LLC header + Ethernet ID: 6+2 */ + if ((priv->conn[conn].mpoa_type == MPOA_TYPE_EOA_WO_FCS) || + (priv->conn[conn].mpoa_type == MPOA_TYPE_EOA_W_FCS)) { +- if (__skb_put_padto(skb, ETH_ZLEN + 8)) ++ if (__skb_put_padto(skb, ETH_ZLEN + 8, false)) + goto CHECK_SHOWTIME_FAIL; + } + +@@ -1418,7 +1414,7 @@ int ppe_send_oam(struct atm_vcc *vcc, vo + struct atm_priv *priv = g_atm_tc; + struct sk_buff *skb; + unsigned int conn; +- dp_subif_t dp_id; ++// dp_subif_t dp_id; + #ifdef OAM_FIX_GRX750 + unsigned char *dest_cell; + #endif +@@ -1465,8 +1461,8 @@ int ppe_send_oam(struct atm_vcc *vcc, vo + priv->tc_priv->param.oam_prio = 0; + qid = priv->conn[conn].prio_queue_map[priv->tc_priv->param.oam_prio]; + vid = priv->conn[conn].subif_id; +- dp_id.subif = (vid & (~0x7f)) | +- ATM_DESC_SUBIF_ID(qid, mpoa_pt, mpoa_type); ++// dp_id.subif = (vid & (~0x7f)) | ++// ATM_DESC_SUBIF_ID(qid, mpoa_pt, mpoa_type); + #ifdef OAM_FIX_GRX750 + dest_cell = kmalloc(CELL_SIZE, GFP_KERNEL); + if (dest_cell == NULL) { +@@ -1494,18 +1490,18 @@ int ppe_send_oam(struct atm_vcc *vcc, vo + #else + memcpy(skb->data, cell, CELL_SIZE); + #endif +- /* SET SUBIFID */ +- skb->DW0 = (skb->DW0 & ~0x7FFF) | dp_id.subif; +- skb->dev = priv->conn[conn].dev; +- tc_dbg(priv->tc_priv, MSG_TX, "conn: %d, dev name: %s, qid: 0x%x len:%d\n", +- conn, skb->dev->name, dp_id.subif, skb->len); +- #ifdef OAM_FIX_GRX750 +- if (priv->tc_priv->tc_ops.send(NULL, +- skb, dp_id.subif, ATM_OAM_PKT) == 0) { +- #else ++// /* SET SUBIFID */ ++// skb->DW0 = (skb->DW0 & ~0x7FFF) | dp_id.subif; ++// skb->dev = priv->conn[conn].dev; ++// tc_dbg(priv->tc_priv, MSG_TX, "conn: %d, dev name: %s, qid: 0x%x len:%d\n", ++// conn, skb->dev->name, dp_id.subif, skb->len); ++// #ifdef OAM_FIX_GRX750 ++// if (priv->tc_priv->tc_ops.send(NULL, ++// skb, dp_id.subif, ATM_OAM_PKT) == 0) { ++// #else + if (priv->tc_priv->tc_ops.send(NULL, + skb, qid, ATM_OAM_PKT) == 0) { +- #endif ++// #endif + priv->stats.oam_tx_pkts++; + priv->stats.oam_tx_bytes += skb->len; + priv->conn[conn].stats.oam_tx_pkts++; +@@ -1604,7 +1600,7 @@ static void oam_push(struct atm_priv *pr + conn = -1; /* invalid */ + if (conn_valid(conn) && priv->conn[conn].vcc != NULL) { + vcc = priv->conn[conn].vcc; +- priv->conn[conn].access_time = current_kernel_time(); ++ ktime_get_coarse_ts64(&priv->conn[conn].access_time); + + tc_dbg(priv->tc_priv, MSG_OAM_RX, "conn=%d, vpi: %d, vci:%d\n", + conn, header->vpi, header->vci); +@@ -2547,30 +2543,29 @@ static void ppe_atm_fw_hw_init(struct at + static int atm_dev_init(struct atm_priv *atm_priv, int ep_id) + { + int i, err; +- struct atm_dev *dev; +- dev = atm_dev_register(g_atm_dev_name, +- atm_priv->tc_priv->ep_dev[ep_id].dev, +- &g_ppe_atm_ops, -1, NULL); +- if (!dev) { +- err = -EIO; +- goto ATM_DEV_REGISTER_FAIL; +- } +- dev->ci_range.vpi_bits = 8; +- dev->ci_range.vci_bits = 16; +- /* assume 3200 cell rate +- * before get real information +- */ +- dev->link_rate = +- DEFAULT_CELL_RATE; +- dev->dev_data = atm_priv; +- dev->phy_data = +- (void *)(unsigned long)0; + + for (i = 0; i < ATM_PORT_NUMBER; i++) { + if (atm_priv->port[i].dev) + continue; + atm_priv->port[i].tx_max_cell_rate = DEFAULT_CELL_RATE; +- atm_priv->port[i].dev = dev; ++ atm_priv->port[i].dev = atm_dev_register(g_atm_dev_name, ++ atm_priv->tc_priv->ep_dev[ep_id].dev, ++ &g_ppe_atm_ops, -1, NULL); ++ if (!atm_priv->port[i].dev) { ++ err = -EIO; ++ goto ATM_DEV_REGISTER_FAIL; ++ } else { ++ atm_priv->port[i].dev->ci_range.vpi_bits = 8; ++ atm_priv->port[i].dev->ci_range.vci_bits = 16; ++ /* assume 3200 cell rate ++ * before get real information ++ */ ++ atm_priv->port[i].dev->link_rate = ++ DEFAULT_CELL_RATE; ++ atm_priv->port[i].dev->dev_data = atm_priv; ++ atm_priv->port[i].dev->phy_data = ++ (void *)(unsigned long)i; ++ } + } + //TODO : check for SoC PMAC, current fix + #ifdef CONFIG_SOC_TYPE_XWAY +@@ -2985,7 +2980,8 @@ static unsigned int atm_get_pvc_id(struc + return -EINVAL; + } + +- return (skb->DW0 >> 3) & 0xF; ++// return (skb->DW0 >> 3) & 0xF; ++ return 1; + } + + static int atm_get_qid_by_vcc(struct net_device *dev, struct sk_buff *skb, +@@ -3292,7 +3288,7 @@ static void atm_push(struct net_device * + += skb->len; + } else + priv->stats.aal5_rx_errors++; +- priv->conn[conn].access_time = current_kernel_time(); ++ ktime_get_coarse_ts64(&priv->conn[conn].access_time); + spin_unlock_bh(&priv->atm_lock); + + vcc->push(vcc, skb); +--- a/dcdp/inc/atm_tc.h ++++ b/dcdp/inc/atm_tc.h +@@ -449,7 +449,7 @@ struct atm_port { + struct atm_pvc { + struct atm_vcc *vcc; /* opened VCC */ + struct net_device *dev; /* net device associated with atm VCC */ +- struct timespec access_time; /* time when last user cell arrived */ ++ struct timespec64 access_time; /* time when last user cell arrived */ + int prio_queue_map[ATM_PRIO_Q_NUM]; + unsigned int prio_tx_packets[ATM_PRIO_Q_NUM]; + struct atm_stats stats; +--- a/dcdp/inc/tc_api.h ++++ b/dcdp/inc/tc_api.h +@@ -196,19 +196,6 @@ static inline void aca_ring_addr_init(st + ring->aca_cnt_phyaddr = ep_dev->phy_membase + addr; + } + +-static inline int __skb_put_padto(struct sk_buff *skb, unsigned int len) +-{ +- unsigned int size = skb->len; +- +- if (unlikely(size < len)) { +- len -= size; +- if (skb_pad(skb, len)) +- return -ENOMEM; +- __skb_put(skb, len); +- } +- return 0; +-} +- + extern int showtime_stat(struct tc_priv *); + extern void dump_skb_info(struct tc_priv *, struct sk_buff *, u32); + extern void *tc_buf_alloc(void *, size_t, u32 *, +--- a/dcdp/inc/tc_proc.h ++++ b/dcdp/inc/tc_proc.h +@@ -23,6 +23,8 @@ + #ifndef __TC_PROC_H__ + #define __TC_PROC_H__ + ++#include ++ + #define TC_PROC_DIR "driver/vrx518" + #define TC_PROC_ATM_DIR "atm" + #define TC_PROC_PTM_DIR "ptm" +@@ -41,7 +43,7 @@ enum { + struct tc_proc_list { + char proc_name[32]; + umode_t mode; +- const struct file_operations *fops; ++ const struct proc_ops *fops; + int is_folder; + }; + +--- a/dcdp/ptm_tc.c ++++ b/dcdp/ptm_tc.c +@@ -39,7 +39,7 @@ + #include + #include + #include +-#include ++// #include + + #include "inc/tc_main.h" + #include "inc/reg_addr.h" +@@ -182,8 +182,8 @@ static int ptm_get_qid(struct net_device + return qid; + } + +-static struct rtnl_link_stats64 *ptm_get_stats(struct net_device *dev, +- struct rtnl_link_stats64 *storage) ++static void ptm_get_stats(struct net_device *dev, ++ struct rtnl_link_stats64 *storage) + { + struct ptm_priv *ptm_tc = netdev_priv(dev); + +@@ -191,8 +191,6 @@ static struct rtnl_link_stats64 *ptm_get + memcpy(storage, &ptm_tc->stats64, sizeof(ptm_tc->stats64)); + else + storage->tx_errors += ptm_tc->stats64.tx_errors; +- +- return storage; + } + + static int ptm_set_mac_address(struct net_device *dev, void *p) +@@ -209,7 +207,7 @@ static int ptm_set_mac_address(struct ne + return 0; + } + +-static void ptm_tx_timeout(struct net_device *dev) ++static void ptm_tx_timeout(struct net_device *dev, unsigned int txqueue) + { + struct ptm_priv *ptm_tc = netdev_priv(dev); + +@@ -503,7 +501,7 @@ static int ptm_xmit(struct sk_buff *skb, + if (!showtime_stat(ptm_tc->tc_priv)) + goto PTM_XMIT_DROP; + +- if (__skb_put_padto(skb, ETH_ZLEN)) ++ if (__skb_put_padto(skb, ETH_ZLEN, false)) + goto PTM_XMIT_DROP; + + dump_skb_info(ptm_tc->tc_priv, skb, (MSG_TX | MSG_TXDATA)); +@@ -632,11 +630,8 @@ static int ptm_dev_init(struct tc_priv * + struct ptm_priv *ptm_tc; + const char macaddr[ETH_ALEN] + = {0xAC, 0x9A, 0x96, 0x11, 0x22, 0x33}; +-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) +- dev = alloc_netdev_mq(sizeof(*ptm_tc), "ptm%d", ptm_setup, 4); +-#else +- dev = alloc_netdev_mq(sizeof(*ptm_tc), "ptm%d", NET_NAME_ENUM, ptm_setup, 4); +-#endif ++ ++ dev = alloc_netdev_mq(sizeof(*ptm_tc), "dsl%d", NET_NAME_ENUM, ptm_setup, 4); + if (!dev) { + tc_dbg(tc_priv, MSG_INIT, "Cannot alloc net device\n"); + return -ENOMEM; +@@ -2103,7 +2098,6 @@ static int ptm_showtime_exit(const unsig + struct ptm_ep_priv *priv = tc_ep_priv(idx); + u32 stop = ACA_TXIN_EN; + struct dc_ep_dev *ep; +- int i = 0; + + tc_info(priv->tc_priv, MSG_EVENT, "Line[%d]: show time exit!\n", idx); + ep = priv->ep; +--- a/dcdp/tc_api.c ++++ b/dcdp/tc_api.c +@@ -52,18 +52,24 @@ static const char ppe_fw_name[] = "ppe_f + #define VRX518_PPE_FW_ID 0xB + #define MD5_LEN 16 + ++enum tc_multicast_groups { ++ TC_MCGRP, ++}; ++ ++/* TC message multicast group */ ++static const struct genl_multicast_group tc_ml_grps[] = { ++ [TC_MCGRP] = { .name = TC_MCAST_GRP_NAME, }, ++}; ++ + /* TC message genelink family */ + static struct genl_family tc_gnl_family = { +- .id = GENL_ID_GENERATE, /* To generate an id for the family*/ ++// .id = GENL_ID_GENERATE, /* To generate an id for the family*/ + .hdrsize = 0, + .name = TC_FAMILY_NAME, /*family name, used by userspace application*/ + .version = 1, /*version number */ + .maxattr = TC_A_MAX - 1, +-}; +- +-/* TC message multicast group */ +-static struct genl_multicast_group tc_ml_grp = { +- .name = TC_MCAST_GRP_NAME, ++ .mcgrps = tc_ml_grps, ++ .n_mcgrps = ARRAY_SIZE(tc_ml_grps), + }; + + /** +@@ -568,7 +574,8 @@ int tc_ntlk_msg_send(struct tc_priv *pri + nla_put_u32(skb, TC_A_LINENO, ln_no); + + genlmsg_end(skb, msg_head); +- ret = genlmsg_multicast(skb, pid, tc_ml_grp.id, GFP_KERNEL); ++ ret = genlmsg_multicast(&tc_gnl_family, skb, pid, TC_MCGRP, ++ GFP_KERNEL); + if (ret) { + tc_err(priv, MSG_EVENT, "Sent TC multicast message Fail!\n"); + goto err1; +@@ -590,21 +597,11 @@ int tc_gentlk_init(struct tc_priv *priv) + return ret; + } + +- ret = genl_register_mc_group(&tc_gnl_family, &tc_ml_grp); +- if (ret) { +- tc_err(priv, MSG_EVENT, "register mc group fail: %i, grp name: %s\n", +- ret, tc_ml_grp.name); +- genl_unregister_family(&tc_gnl_family); +- return ret; +- } +- + return 0; + } + + void tc_gentlk_exit(void) + { +- /* unregister mc groups */ +- genl_unregister_mc_group(&tc_gnl_family, &tc_ml_grp); + /*unregister the family*/ + genl_unregister_family(&tc_gnl_family); + } +@@ -666,7 +663,7 @@ void dump_skb_info(struct tc_priv *tcpri + (u32)skb->end, skb->len); + tc_dbg(tcpriv, type, + "skb: clone: %d, users: %d\n", +- skb->cloned, atomic_read(&skb->users)); ++ skb->cloned, refcount_read(&skb->users)); + tc_dbg(tcpriv, type, + "skb: nfrag: %d\n", skb_shinfo(skb)->nr_frags); + +@@ -936,7 +933,6 @@ static int fw_md5_check(struct tc_priv * + } + + desc->tfm = md5; +- desc->flags = 0; + + ret = crypto_shash_init(desc); + if (ret) { +--- a/dcdp/tc_proc.c ++++ b/dcdp/tc_proc.c +@@ -22,7 +22,9 @@ + *******************************************************************************/ + #include + #include +-#include ++// #include ++#include ++#include + #include + #include + #include "inc/tc_main.h" +@@ -353,7 +355,7 @@ static ssize_t mem_proc_write(struct fil + } + addr = set_val = repeat_cnt = 0; + +- if (!access_ok(VERIFY_READ, buf, count)) ++ if (!access_ok(buf, count)) + return -EFAULT; + + len = count < sizeof(str) ? count : sizeof(str) - 1; +@@ -450,13 +452,12 @@ static int proc_read_mem_seq_open(struct + return single_open(file, proc_read_mem, NULL); + } + +-static const struct file_operations mem_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_mem_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .write = mem_proc_write, ++static const struct proc_ops mem_proc_fops = { ++ .proc_open = proc_read_mem_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = mem_proc_write, + }; + + static ssize_t pp32_proc_write(struct file *file, const char __user *buf, +@@ -748,13 +749,12 @@ static int proc_read_pp32_seq_open(struc + return single_open(file, proc_read_pp32, PDE_DATA(inode)); + } + +-static const struct file_operations pp32_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_pp32_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .write = pp32_proc_write, ++static const struct proc_ops pp32_proc_fops = { ++ .proc_open = proc_read_pp32_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = pp32_proc_write, + }; + + static int proc_read_tc_cfg(struct seq_file *seq, void *v) +@@ -865,13 +865,12 @@ static int proc_read_tc_cfg_seq_open(str + return single_open(file, proc_read_tc_cfg, PDE_DATA(inode)); + } + +-static const struct file_operations tc_cfg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_tc_cfg_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .write = proc_write_cfg, ++static const struct proc_ops tc_cfg_proc_fops = { ++ .proc_open = proc_read_tc_cfg_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++ .proc_write = proc_write_cfg, + }; + + static ssize_t proc_write_dbg(struct file *file, const char __user *buf, +@@ -951,13 +950,12 @@ static int proc_read_dbg_seq_open(struct + return single_open(file, proc_read_dbg, PDE_DATA(inode)); + } + +-static const struct file_operations tc_dbg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_dbg_seq_open, +- .read = seq_read, +- .write = proc_write_dbg, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops tc_dbg_proc_fops = { ++ .proc_open = proc_read_dbg_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_dbg, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static ssize_t proc_write_tc_switch(struct file *file, const char __user *buf, +@@ -1018,11 +1016,11 @@ proc_tc_switch_help: + return count; + } + +-static const struct file_operations tc_switch_proc_fops = { +- .owner = THIS_MODULE, +- .write = proc_write_tc_switch, +- .llseek = noop_llseek, ++static const struct proc_ops tc_switch_proc_fops = { ++ .proc_write = proc_write_tc_switch, ++ .proc_lseek = noop_llseek, + }; ++ + static ssize_t proc_write_show_time(struct file *file, const char __user *buf, + size_t count, loff_t *data) + { +@@ -1077,10 +1075,9 @@ proc_show_time_help: + return count; + } + +-static const struct file_operations tc_show_time_proc_fops = { +- .owner = THIS_MODULE, +- .write = proc_write_show_time, +- .llseek = noop_llseek, ++static const struct proc_ops tc_show_time_proc_fops = { ++ .proc_write = proc_write_show_time, ++ .proc_lseek = noop_llseek, + }; + + static int proc_read_ver(struct seq_file *seq, void *v) +@@ -1128,12 +1125,11 @@ static int proc_read_ver_seq_open(struct + return single_open(file, proc_read_ver, PDE_DATA(inode)); + } + +-static const struct file_operations tc_ver_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_ver_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops tc_ver_proc_fops = { ++ .proc_open = proc_read_ver_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_read_soc(struct seq_file *seq, void *v) +@@ -1142,20 +1138,18 @@ static int proc_read_soc(struct seq_file + + tcpriv = (struct tc_priv *)seq->private; + +-#if 0 + seq_printf(seq, "TXIN Base: 0x%08x, TXIN num: %d\n", +- tcpriv->cfg.txin_dbase, +- tcpriv->cfg.txin_dnum); ++ tcpriv->cfg.txin.soc_phydbase, ++ tcpriv->cfg.txin.soc_dnum); + seq_printf(seq, "TXOUT Base: 0x%08x, TXOUT num: %d\n", +- tcpriv->cfg.txout_dbase, +- tcpriv->cfg.txout_dnum); ++ tcpriv->cfg.txout.soc_phydbase, ++ tcpriv->cfg.txout.soc_dnum); + seq_printf(seq, "RXIN Base: 0x%08x, RXIN num: %d\n", +- tcpriv->cfg.rxin_dbase, +- tcpriv->cfg.rxin_dnum); ++ tcpriv->cfg.rxin.soc_phydbase, ++ tcpriv->cfg.rxin.soc_dnum); + seq_printf(seq, "RXOUT Base: 0x%08x, RXOUT num: %d\n", +- tcpriv->cfg.rxout_dbase, +- tcpriv->cfg.rxout_dnum); +-#endif ++ tcpriv->cfg.rxout.soc_phydbase, ++ tcpriv->cfg.rxout.soc_dnum); + + return 0; + } +@@ -1165,15 +1159,13 @@ static int proc_read_soc_seq_open(struct + return single_open(file, proc_read_soc, PDE_DATA(inode)); + } + +-static const struct file_operations tc_soc_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_soc_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops tc_soc_proc_fops = { ++ .proc_open = proc_read_soc_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + +- + static struct tc_proc_list tc_procs[] = { + {TC_PROC_DIR, 0, NULL, 1}, + {"cfg", 0644, &tc_cfg_proc_fops, 0}, +@@ -1241,13 +1233,12 @@ static int proc_read_ptm_wanmib_seq_open + return single_open(file, proc_read_ptm_wanmib, PDE_DATA(inode)); + } + +-static const struct file_operations ptm_wanmib_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_ptm_wanmib_seq_open, +- .read = seq_read, +- .write = proc_write_ptm_wanmib, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops ptm_wanmib_proc_fops = { ++ .proc_open = proc_read_ptm_wanmib_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_ptm_wanmib, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_ptm_read_cfg(struct seq_file *seq, void *v) +@@ -1300,7 +1291,7 @@ static ssize_t ptm_cfg_proc_write(struct + return -EINVAL; + } + +- if (!access_ok(VERIFY_READ, buf, count)) ++ if (!access_ok(buf, count)) + return -EFAULT; + + len = count < sizeof(str) ? count : sizeof(str) - 1; +@@ -1343,13 +1334,12 @@ proc_ptm_cfg_help: + } + + +-static const struct file_operations ptm_cfg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_cfg_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = ptm_cfg_proc_write, +- .release = single_release, ++static const struct proc_ops ptm_cfg_proc_fops = { ++ .proc_open = proc_read_cfg_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = ptm_cfg_proc_write, ++ .proc_release = single_release, + }; + + static ssize_t proc_ptm_write_prio(struct file *file, const char __user *buf, +@@ -1455,13 +1445,12 @@ static int proc_ptm_read_prio_seq_open(s + return single_open(file, proc_ptm_read_prio, PDE_DATA(inode)); + } + +-static const struct file_operations ptm_prio_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_ptm_read_prio_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = proc_ptm_write_prio, +- .release = single_release, ++static const struct proc_ops ptm_prio_proc_fops = { ++ .proc_open = proc_ptm_read_prio_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = proc_ptm_write_prio, ++ .proc_release = single_release, + }; + + static int proc_ptm_read_bond_seq_open(struct inode *inode, struct file *file) +@@ -1469,12 +1458,11 @@ static int proc_ptm_read_bond_seq_open(s + return single_open(file, proc_ptm_read_bond, PDE_DATA(inode)); + } + +-static const struct file_operations ptm_bond_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_ptm_read_bond_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops ptm_bond_proc_fops = { ++ .proc_open = proc_ptm_read_bond_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_ptm_read_bondmib_seq_open(struct inode *inode, +@@ -1483,13 +1471,12 @@ static int proc_ptm_read_bondmib_seq_ope + return single_open(file, proc_ptm_read_bondmib, PDE_DATA(inode)); + } + +-static const struct file_operations ptm_bondmib_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_ptm_read_bondmib_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = proc_ptm_write_bondmib, +- .release = single_release, ++static const struct proc_ops ptm_bondmib_proc_fops = { ++ .proc_open = proc_ptm_read_bondmib_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = proc_ptm_write_bondmib, ++ .proc_release = single_release, + }; + + struct fwdbg_t { +@@ -1910,14 +1897,14 @@ static int proc_read_fwdbg_seq_open(stru + { + return single_open(file, proc_read_fwdbg, NULL); + } +-static const struct file_operations fwdbg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_fwdbg_seq_open, +- .read = seq_read, +- .write = proc_write_fwdbg_seq, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops fwdbg_proc_fops = { ++ .proc_open = proc_read_fwdbg_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_fwdbg_seq, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; ++ + static struct tc_proc_list ptm_sl_procs[] = { + {TC_PROC_PTM_DIR, 0, NULL, 1}, + {"mem", 0644, &mem_proc_fops, 0}, +@@ -2077,7 +2064,7 @@ static ssize_t atm_cfg_proc_write(struct + + priv = (struct atm_priv *)PDE_DATA(file_inode(file)); + +- if (!access_ok(VERIFY_READ, buf, count)) ++ if (!access_ok(buf, count)) + return -EFAULT; + + len = count < sizeof(str) ? count : sizeof(str) - 1; +@@ -2119,13 +2106,12 @@ proc_atm_cfg_help: + return count; + } + +-static const struct file_operations atm_cfg_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_atm_cfg_seq_open, +- .read = seq_read, +- .write = atm_cfg_proc_write, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops atm_cfg_proc_fops = { ++ .proc_open = proc_read_atm_cfg_seq_open, ++ .proc_read = seq_read, ++ .proc_write = atm_cfg_proc_write, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static ssize_t proc_write_atm_wanmib(struct file *file, const char __user *buf, +@@ -2173,13 +2159,12 @@ static int proc_read_atm_wanmib_seq_open + + + +-static const struct file_operations atm_wanmib_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_atm_wanmib_seq_open, +- .read = seq_read, +- .write = proc_write_atm_wanmib, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops atm_wanmib_proc_fops = { ++ .proc_open = proc_read_atm_wanmib_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_atm_wanmib, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_read_htu_seq_open(struct inode *inode, struct file *file) +@@ -2187,12 +2172,11 @@ static int proc_read_htu_seq_open(struct + return single_open(file, proc_read_htu, PDE_DATA(inode)); + } + +-static const struct file_operations htu_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_htu_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops htu_proc_fops = { ++ .proc_open = proc_read_htu_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static int proc_read_queue_seq_open(struct inode *inode, struct file *file) +@@ -2200,12 +2184,11 @@ static int proc_read_queue_seq_open(stru + return single_open(file, proc_read_queue, PDE_DATA(inode)); + } + +-static const struct file_operations queue_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_queue_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops queue_proc_fops = { ++ .proc_open = proc_read_queue_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static void set_q_prio(struct atm_priv *priv, +@@ -2428,13 +2411,12 @@ static const struct seq_operations pvc_m + .show = pvc_mib_seq_show, + }; + +-static const struct file_operations atm_prio_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_atm_read_prio_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = proc_atm_write_prio, +- .release = single_release, ++static const struct proc_ops atm_prio_proc_fops = { ++ .proc_open = proc_atm_read_prio_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = proc_atm_write_prio, ++ .proc_release = single_release, + }; + + static int proc_read_pvc_mib_seq_open(struct inode *inode, struct file *file) +@@ -2447,12 +2429,11 @@ static int proc_read_pvc_mib_seq_open(st + return ret; + } + +-static const struct file_operations atm_pvc_mib_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_pvc_mib_seq_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = seq_release, ++static const struct proc_ops atm_pvc_mib_proc_fops = { ++ .proc_open = proc_read_pvc_mib_seq_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = seq_release, + }; + + static ssize_t proc_write_cell(struct file *file, +@@ -2592,13 +2573,12 @@ static int proc_read_cell_seq_open(struc + return single_open(file, proc_read_cell, NULL); + } + +-static const struct file_operations atm_cell_proc_fops = { +- .owner = THIS_MODULE, +- .open = proc_read_cell_seq_open, +- .read = seq_read, +- .write = proc_write_cell, +- .llseek = seq_lseek, +- .release = single_release, ++static const struct proc_ops atm_cell_proc_fops = { ++ .proc_open = proc_read_cell_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_cell, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, + }; + + static struct tc_proc_list atm_procs[] = { diff --git a/package/kernel/lantiq/vrx518_tc/patches/200-swplat.patch b/package/kernel/lantiq/vrx518_tc/patches/200-swplat.patch new file mode 100644 index 00000000000..793adefdd65 --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/200-swplat.patch @@ -0,0 +1,1356 @@ +The existing software receive and transmit path does not actually work. +This replaces it by a basic working implementation. + +--- a/dcdp/atm_tc.c ++++ b/dcdp/atm_tc.c +@@ -603,7 +603,11 @@ static void atm_aca_init(struct atm_priv + cfg = &priv->tc_priv->cfg; + + txin = ¶m.aca_txin; ++#if defined(__LITTLE_ENDIAN) ++ txin->byteswap = 0; ++#else + txin->byteswap = 1; ++#endif + txin->hd_size_in_dw = cfg->txin.soc_desc_dwsz; + txin->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_IN_PD_LIST_BASE); + txin->pd_desc_num = __ACA_TX_IN_PD_LIST_NUM; +@@ -625,7 +629,11 @@ static void atm_aca_init(struct atm_priv + txin->soc_cmlt_cnt_addr); + + txout = ¶m.aca_txout; ++#if defined(__LITTLE_ENDIAN) ++ txout->byteswap = 0; ++#else + txout->byteswap = 1; ++#endif + txout->hd_size_in_dw = cfg->txout.soc_desc_dwsz; + txout->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_OUT_PD_LIST_BASE); + txout->pd_desc_num = __ACA_TX_OUT_PD_LIST_NUM; +@@ -647,7 +655,11 @@ static void atm_aca_init(struct atm_priv + txout->soc_cmlt_cnt_addr); + + rxout = ¶m.aca_rxout; ++#if defined(__LITTLE_ENDIAN) ++ rxout->byteswap = 0; ++#else + rxout->byteswap = 1; ++#endif + rxout->hd_size_in_dw = cfg->rxout.soc_desc_dwsz; + rxout->pd_desc_base = SB_XBAR_ADDR(__ACA_RX_OUT_PD_LIST_BASE); + rxout->pd_desc_num = __ACA_RX_OUT_PD_LIST_NUM; +@@ -669,7 +681,11 @@ static void atm_aca_init(struct atm_priv + rxout->soc_cmlt_cnt_addr); + + rxin = ¶m.aca_rxin; ++#if defined(__LITTLE_ENDIAN) ++ rxin->byteswap = 0; ++#else + rxin->byteswap = 1; ++#endif + rxin->hd_size_in_dw = cfg->rxin.soc_desc_dwsz; + rxin->pd_desc_base = SB_XBAR_ADDR(__RX_IN_PD_DES_LIST_BASE); + rxin->pd_desc_num = __ACA_RX_IN_PD_LIST_NUM; +@@ -1261,7 +1277,7 @@ static int ppe_ioctl(struct atm_dev *dev + static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb) + { + int ret, qid, mpoa_pt, mpoa_type, vid; +- unsigned int prio, conn; ++ unsigned int prio, conn, len; + struct atm_priv *priv; + + if (!vcc) { +@@ -1327,12 +1343,14 @@ static int ppe_send(struct atm_vcc *vcc, + tc_dbg(priv->tc_priv, MSG_TX, "vid: 0x%x, qid: 0x%x\n", + vid, qid); + ++ len = skb->len; ++ + if (priv->tc_priv->tc_ops.send(NULL, + skb, qid, ATM_SL_PKT) == 0) { + priv->stats.aal5_tx_pkts++; +- priv->stats.aal5_tx_bytes += skb->len; ++ priv->stats.aal5_tx_bytes += len; + priv->conn[conn].stats.aal5_tx_pkts++; +- priv->conn[conn].stats.aal5_tx_bytes += skb->len; ++ priv->conn[conn].stats.aal5_tx_bytes += len; + priv->conn[conn].prio_tx_packets[prio]++; + } else { + tc_dbg(priv->tc_priv, MSG_TX, "ATM: TX fail\n"); +--- a/dcdp/ptm_tc.c ++++ b/dcdp/ptm_tc.c +@@ -497,6 +497,7 @@ static int ptm_xmit(struct sk_buff *skb, + struct ptm_priv *ptm_tc = netdev_priv(dev); + int qid; + enum tc_pkt_type type; ++ unsigned int len; + + if (!showtime_stat(ptm_tc->tc_priv)) + goto PTM_XMIT_DROP; +@@ -510,11 +511,13 @@ static int ptm_xmit(struct sk_buff *skb, + type = ptm_tc->tc_priv->tc_mode == TC_PTM_BND_MODE + ? PTM_BOND_PKT : PTM_SL_PKT; + ++ len = skb->len; ++ + if (ptm_tc->tc_priv->tc_ops.send(dev, skb, qid, type) < 0) + ptm_tc->stats64.tx_dropped++; + else { + ptm_tc->stats64.tx_packets++; +- ptm_tc->stats64.tx_bytes += skb->len; ++ ptm_tc->stats64.tx_bytes += len; + } + + return 0; +@@ -631,7 +634,7 @@ static int ptm_dev_init(struct tc_priv * + const char macaddr[ETH_ALEN] + = {0xAC, 0x9A, 0x96, 0x11, 0x22, 0x33}; + +- dev = alloc_netdev_mq(sizeof(*ptm_tc), "dsl%d", NET_NAME_ENUM, ptm_setup, 4); ++ dev = alloc_netdev(sizeof(*ptm_tc), "dsl%d", NET_NAME_ENUM, ptm_setup); + if (!dev) { + tc_dbg(tc_priv, MSG_INIT, "Cannot alloc net device\n"); + return -ENOMEM; +@@ -2324,7 +2327,11 @@ static void ptm_aca_init(struct ptm_ep_p + cfg = &priv->tc_priv->cfg; + + txin = ¶m.aca_txin; ++#if defined(__LITTLE_ENDIAN) ++ txin->byteswap = 0; ++#else + txin->byteswap = 1; ++#endif + txin->hd_size_in_dw = cfg->txin.soc_desc_dwsz; + txin->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_IN_PD_LIST_BASE); + txin->pd_desc_num = __ACA_TX_IN_PD_LIST_NUM; +@@ -2347,7 +2354,11 @@ static void ptm_aca_init(struct ptm_ep_p + txin->soc_cmlt_cnt_addr); + + txout = ¶m.aca_txout; ++#if defined(__LITTLE_ENDIAN) ++ txout->byteswap = 0; ++#else + txout->byteswap = 1; ++#endif + txout->hd_size_in_dw = cfg->txout.soc_desc_dwsz; + if (priv->tc_priv->param.cdma_desc_loc == LOC_IN_FPI) + txout->pd_desc_base = sb_r32(__TX_OUT_SHADOW_PTR) - phybase; +@@ -2373,7 +2384,11 @@ static void ptm_aca_init(struct ptm_ep_p + txout->soc_cmlt_cnt_addr); + + rxout = ¶m.aca_rxout; ++#if defined(__LITTLE_ENDIAN) ++ rxout->byteswap = 0; ++#else + rxout->byteswap = 1; ++#endif + rxout->hd_size_in_dw = cfg->rxout.soc_desc_dwsz; + if (priv->tc_priv->param.cdma_desc_loc == LOC_IN_FPI) + rxout->pd_desc_base = sb_r32(__RX_OUT_SHADOW_PTR) - phybase; +@@ -2399,7 +2414,11 @@ static void ptm_aca_init(struct ptm_ep_p + rxout->soc_cmlt_cnt_addr); + + rxin = ¶m.aca_rxin; ++#if defined(__LITTLE_ENDIAN) ++ rxin->byteswap = 0; ++#else + rxin->byteswap = 1; ++#endif + rxin->hd_size_in_dw = cfg->rxin.soc_desc_dwsz; + rxin->pd_desc_base = SB_XBAR_ADDR(__RX_IN_PD_DES_LIST_BASE); + rxin->pd_desc_num = __ACA_RX_IN_PD_LIST_NUM; +--- a/dcdp/platform/sw_plat.c ++++ b/dcdp/platform/sw_plat.c +@@ -36,10 +36,13 @@ + #include + #include + #include +-#include "inc/dsl_tc.h" ++#include "../inc/dsl_tc.h" + + #include "../inc/tc_main.h" + #include "../inc/reg_addr.h" ++#include "../inc/tc_common.h" ++ ++#include "../inc/fw/vrx518_addr_def.h" + + + #define PMAC_SIZE 8 +@@ -70,7 +73,7 @@ enum { + #define TXIN_DNUM 128 + #define TXOUT_DNUM 128 + #define RXOUT_DNUM 1024 +-#define RXIN_DNUM 1024 ++#define RXIN_DNUM 0 + + #define TXIN_CHECK_NUM 32 + +@@ -80,22 +83,32 @@ struct aca_ring { + void *umt_dst; + u32 umt_phydst; + u32 dnum; ++ u32 dsize; + int idx; /* SoC RX/TX index */ +- int cnt; +- void *cnt_addr; +- u32 cnt_phyaddr; + int ep_dev_idx; + }; + ++struct tx_list_item { ++ size_t len; ++ void *buf; ++ dma_addr_t phyaddr; ++}; ++ ++struct tx_list { ++ struct tx_list_item *data; ++ u32 dnum; ++}; ++ + struct aca_ring_grp { + struct aca_ring rxin; + struct aca_ring txin; + struct aca_ring rxout; + struct aca_ring txout; ++ struct tx_list txlist; + }; + +-#if 1 +-struct dma_desc { ++#if defined(__LITTLE_ENDIAN) ++struct dma_tx_desc { + /* DW 0 */ + u32 qid; + /* DW 1 */ +@@ -112,8 +125,26 @@ struct dma_desc { + u32 c:1; + u32 own:1; + }__packed; ++ ++struct dma_rx_desc { ++ /* DW 0 */ ++ u32 qid; ++ /* DW 1 */ ++ u32 res2; ++ /* DW 2 */ ++ u32 data_len:16; ++ u32 res0:7; ++ u32 byte_off:3; ++ u32 res1:2; ++ u32 eop:1; ++ u32 sop:1; ++ u32 c:1; ++ u32 own:1; ++ /* DW 3 */ ++ u32 data_ptr; ++}__packed; + #else +-struct dma_desc { ++struct dma_tx_desc { + /* DW 0 */ + u32 qid; + /* DW 1 */ +@@ -131,14 +162,25 @@ struct dma_desc { + u32 data_len:16; + }__packed; + ++struct dma_rx_desc { ++ /* DW 0 */ ++ u32 qid; ++ /* DW 1 */ ++ u32 res; ++ /* DW 2 */ ++ u32 own:1; ++ u32 c:1; ++ u32 sop:1; ++ u32 eop:1; ++ u32 res1:2; ++ u32 byte_off:3; ++ u32 res0:7; ++ u32 data_len:16; ++ /* DW 3 */ ++ u32 data_ptr; ++}__packed; + #endif + +-struct plat_dma { +- u32 chan; /* CHAN IID */ +- u32 dma_chan; /* CONTROLLER/PORT/CHAN ID */ +- u32 ds_dnum; /* DS descriptor number */ +-}; +- + struct plat_umt { + u32 id; + u32 cbm_id; +@@ -152,28 +194,28 @@ struct tc_req { + enum dsl_tc_mode tc_mode; + }; + +-#if 0 +-struct tc_coc { +- enum ltq_cpufreq_state coc_stat; +- struct tasklet_struct coc_task; ++struct mem_map_entry { ++ dma_addr_t phyaddr; ++ void *mem; ++ size_t size; ++ struct hlist_node node; + }; +-#endif + + struct plat_priv { + struct tc_priv *tc_priv; + struct plat_umt umt[EP_MAX_NUM]; +- struct plat_dma dma[EP_MAX_NUM]; + struct ltq_mei_atm_showtime_info dsl_ops; + struct tc_req req_work; + struct aca_ring_grp soc_rings; +- /* struct tc_coc coc;*/ ++ struct net_device *netdev; ++ DECLARE_HASHTABLE(mem_map, 8); + }; + + static struct plat_priv *g_plat_priv; + struct tasklet_struct txout_task; + struct tasklet_struct rxout_task; + +-static void txout_action(struct tc_priv *priv, struct aca_ring *txout); ++static DEFINE_SPINLOCK(tx_spinlock); + + void *ppa_callback_get(e_ltq_mei_cb_type type) + { +@@ -259,122 +301,65 @@ static inline struct tc_priv *plat_to_tc + return g_plat_priv->tc_priv; + } + +-static int32_t plat_rx(struct net_device *rxdev, struct net_device *txdev, +- struct sk_buff *skb, int32_t len) +-{ +- int32_t err; +- struct tc_priv *tc_priv = plat_to_tcpriv(); +- +- if (unlikely(!rxdev)) { +- if (txdev != NULL) +- tc_dbg(tc_priv, MSG_RX, +- "Recv undelivered packet from DP lib\n"); +- else +- tc_dbg(tc_priv, MSG_RX, "Recv unknown packet\n"); +- err = -ENODEV; +- goto err1; +- } +- +- tc_priv->tc_ops.recv(rxdev, skb); +- return 0; +- +-err1: +- dev_kfree_skb_any(skb); +- +- return err; +-} +- +-#if 0 +-static int32_t plat_get_subifid(struct net_device *dev, struct sk_buff *skb, +- void *subif_data, uint8_t dst_mac[MAX_ETH_ALEN], +- dp_subif_t *subif, uint32_t flags) +-{ +- int qid; +- struct tc_priv *priv = plat_to_tcpriv(); +- +- qid = priv->tc_ops.get_qid(dev, skb, subif_data, flags); +- if (qid < 0) +- return qid; +- else +- subif->subif = qid; +- +- return 0; +-} +-#endif +- +-#if 0 +-static void plat_coc_tasklet(unsigned long arg) +-{ +- /* change state to D0 */ +- if (g_plat_priv->coc.coc_stat == LTQ_CPUFREQ_PS_D0) +- return; +- +- g_plat_priv->coc.coc_stat = LTQ_CPUFREQ_PS_D0; +-} +- +-static void plat_coc_req(void) +-{ +- tasklet_schedule(&g_plat_priv->coc.coc_task); +-} ++static void *plat_mem_alloc(size_t size, enum tc_dir dir, u32 *phyaddr); ++static void *plat_mem_virt(u32 phyaddr); ++static void plat_mem_free(u32 phyaddr, enum tc_dir dir); + ++static void txlist_free(struct tx_list *list); + +-static int32_t plat_coc_stat(enum ltq_cpufreq_state new_state, +- enum ltq_cpufreq_state old_state, uint32_t flags) ++static int txlist_init(struct tx_list *list, u32 dnum) + { +- struct tc_priv *priv = plat_to_tcpriv(); +- tc_dbg(priv, MSG_COC, +- "COC current state: %d, new state: %d, old state: %d\n", +- g_plat_priv->coc.coc_stat, new_state, old_state); ++ struct tx_list_item *item; ++ int i; + +- if (g_plat_priv->coc.coc_stat != new_state) { +- g_plat_priv->coc.coc_stat = new_state; ++ list->dnum = dnum; + +- if (new_state == LTQ_CPUFREQ_PS_D3) { +- /* Enable interrupt for DS packet */ +- priv->tc_ops.irq_on(MBOX_PKT_RX); +- } else { +- /* Disable interrupt for DS packet */ +- priv->tc_ops.irq_off(MBOX_PKT_RX); ++ list->data = kcalloc(dnum, sizeof(struct tx_list_item), GFP_KERNEL); ++ if (!list->data) { ++ pr_err("Failed to allocate TX list!\n"); ++ goto err; ++ } ++ ++ for (i = 0; i < list->dnum; i++) { ++ item = &list->data[i]; ++ ++ // use plat_mem_alloc as these buffers will be mixed with buffers allocated in ptm_tc.c / atm_tc.c ++ item->buf = plat_mem_alloc(DMA_PACKET_SZ, US_DIR, &item->phyaddr); ++ if (!item->buf) { ++ pr_err("Failed to allocate TX buffer!\n"); ++ goto err; + } + } + + return 0; +-} +-#endif +- +-static inline int ring_dist(int idx1, int idx2, int size) +-{ +- if (idx1 >= idx2) +- return (idx1 - idx2); +- else +- return (idx1 + size - idx2); +-} + +-static inline int __ring_full(int idx, int cnt, u32 dnum) +-{ +- if (ring_dist(idx, cnt, dnum) < dnum - 1) +- return 0; +- else +- return 1; ++err: ++ txlist_free(list); ++ return -1; + } + +-static inline int ring_full(struct aca_ring *ring) ++static void txlist_free(struct tx_list *list) + { +- if (!__ring_full(ring->idx, ring->cnt, ring->dnum)) +- return 0; ++ struct tx_list_item *item; ++ int i; + +- /* if ring full, update cumulative counter and check again */ +- ring->cnt = readl(ring->cnt_addr) % ring->dnum; ++ if (list->data) { ++ for (i = 0; i < list->dnum; i++) { ++ item = &list->data[i]; ++ ++ if (item->buf) { ++ // use plat_mem_free as these buffers are mixed with buffers allocated in ptm_tc.c / atm_tc.c ++ plat_mem_free(item->phyaddr, US_DIR); ++ } ++ } ++ } + +- return __ring_full(ring->idx, ring->cnt, ring->dnum); ++ kfree(list->data); + } + +-#define ring_idx_inc(ring, idx) \ +- do { ring->idx = (ring->idx + 1) % ring->dnum; } while (0); +- +-static inline void ring_cnt_update(struct aca_ring *ring) ++static inline void ring_idx_inc(struct aca_ring *ring) + { +- ring->cnt = readl(ring->cnt_addr) % ring->dnum; ++ ring->idx = (ring->idx + 1) % ring->dnum; + } + + static struct sk_buff *txin_skb_prepare(struct sk_buff *skb) +@@ -399,252 +384,220 @@ static struct sk_buff *txin_skb_prepare( + return nskb; + } + +-static int ring_mmap(void *mem, int size, +- enum dma_data_direction dir, u32 *addr) +-{ +- struct device *pdev; +- dma_addr_t phy_addr; +- struct tc_priv *priv; +- u32 addr1; +- +- priv = g_plat_priv->tc_priv; +- pdev = priv->ep_dev[0].dev; +- +- phy_addr = dma_map_single(pdev, mem, size, dir); +- if (unlikely(dma_mapping_error(pdev, phy_addr))) { +- tc_err(priv, MSG_INIT, +- "DMA address mapping error: buf: 0x%x, size: %d, dir: %d\n", +- (u32)mem, size, dir); +- return -ENOMEM; +- } +- dma_unmap_single(pdev, phy_addr, size, dir); +- +- pr_info("vaddr: 0x%x, phyaddr: 0x%lx\n", (u32)mem, phy_addr); +- addr1 = (u32)phy_addr; +- +- if (addr) +- *addr = addr1; +- +- return 0; +-} +- +-static void txin_action(struct tc_priv *priv, struct aca_ring *txin, ++static int txin_action(struct tc_priv *priv, struct aca_ring *txin, + struct sk_buff *skb, int qid, enum tc_pkt_type type) + { +- struct dma_desc *desc, desc1; +- u32 phyaddr, *dst, *src; +- int i; ++ struct device *pdev = priv->ep_dev[0].dev; ++ struct aca_ring *txout = &g_plat_priv->soc_rings.txout; ++ struct tx_list *txlist = &g_plat_priv->soc_rings.txlist; ++ struct dma_tx_desc *desc; ++ struct tx_list_item *txlist_item; ++ unsigned long flags; ++ ++ if (!g_plat_priv->netdev) { ++ spin_lock_irqsave(&tx_spinlock, flags); ++ } + +- if (ring_full(txin)) { +- tc_dbg(priv, MSG_TX, +- "TXIN Ring Full!: idx: %d, cnt: %d\n", +- txin->idx, txin->cnt); ++ if ((txin->idx + 2) % txin->dnum == txout->idx) { ++ if (g_plat_priv->netdev) { ++ netif_stop_queue(g_plat_priv->netdev); ++ } ++ } else if ((txin->idx + 1) % txin->dnum == txout->idx) { ++ tc_err(priv, MSG_TX, "TXIN ring full: txin: %d, txout: %d\n", ++ txin->idx, txout->idx); + goto err1; + } + ++ desc = (struct dma_tx_desc *)txin->dbase_mem; ++ desc += txin->idx; ++ ++ txlist_item = &txlist->data[txin->idx]; ++ + skb = txin_skb_prepare(skb); + if (!skb) +- return; ++ goto err2; + +- if (ring_mmap(skb->data, skb->len, DMA_TO_DEVICE, &phyaddr) < 0) { +- tc_err(priv, MSG_TX, "TXIN data mmap failed: 0x%x\n", +- (unsigned int)skb->data); +- goto err1; +- } ++ /* ++ * Copy the data to a buffer in the driver. This is necessary because there doesn't seem to be a timely signal ++ * from the device when it has consumed a buffer, which would allow to safely free it. The data_ptr is only ++ * returned in TXOUT after another fixed number of packets (depending on the size of internal buffers) has been ++ * transmitted, which may not happen in the near future. Making a copy allows to free the SKB here. ++ */ ++ memcpy(txlist_item->buf, skb->data, skb->len); + +- /* init a new descriptor for the new skb */ +- desc = (struct dma_desc *)txin->dbase_mem; +- desc += txin->idx; ++ dma_sync_single_range_for_device(pdev, txlist_item->phyaddr, 0, skb->len, DMA_TO_DEVICE); + +- memset(desc, 0, sizeof(*desc)); +- memset(&desc1, 0, sizeof(desc1)); +- desc1.own = 1; +- desc1.c = 1; +- desc1.sop = 1; +- desc1.eop = 1; +- desc1.byte_off = phyaddr & 0x7; +- desc1.data_len = skb->len; +- +- desc1.data_ptr = phyaddr & (~(0x7)); +- desc1.qid = qid; +- +- dst = (u32 *)desc; +- src = (u32 *)&desc1; +- for (i = 0; i < DW_SZ(desc1); i++) +- dst[i] = cpu_to_be32(src[i]); +- +- pr_info("txin idx: %d\n", txin->idx); +- pr_info("descriptor dst val:(DW0-DW3): 0x%x, 0x%x, 0x%x, 0x%x\n", +- dst[0], dst[1], dst[2], dst[3]); +- pr_info("descriptor src val: (DW0-DW3): 0x%x, 0x%x, 0x%x, 0x%x\n", +- src[0], src[1], src[2], src[3]); +- +- if (ring_mmap(desc, sizeof(*desc), DMA_TO_DEVICE, NULL) < 0) { +- tc_err(priv, MSG_TX, "TXIN descriptor mmap failed: 0x%x\n", +- (unsigned int)desc); ++ // this should never happen, the buffers are already aligned by kmalloc ++ if (WARN_ON((txlist_item->phyaddr & 0x7) != 0)) + goto err1; ++ ++ if (g_plat_priv->netdev) { ++ netdev_sent_queue(g_plat_priv->netdev, skb->len); + } ++ txlist_item->len = skb->len; ++ ++ memset(desc, 0, sizeof(*desc)); + +- ring_idx_inc(txin, idx); ++ desc->data_ptr = txlist_item->phyaddr; ++ desc->byte_off = 0; ++ desc->data_len = skb->len; ++ desc->qid = qid; ++ ++ desc->sop = 1; ++ desc->eop = 1; ++ desc->c = 0; ++ desc->own = 1; ++ ++ dev_consume_skb_any(skb); ++ ++ ring_idx_inc(txin); + + /* update TXIN UMT by 1 */ + writel(1, txin->umt_dst); +- pr_info("TXIN send txin packet 1 packet\n"); + +- /* Free skb */ +- dev_kfree_skb_any(skb); ++ if (!g_plat_priv->netdev) { ++ spin_unlock_irqrestore(&tx_spinlock, flags); ++ } + +- /* check txout for testing*/ +- //txout_action(plat_to_tcpriv(), &g_plat_priv->soc_rings.txout); +- return; ++ return 0; + + err1: +- //skb->delay_free = 0; + dev_kfree_skb_any(skb); ++ ++err2: ++ if (!g_plat_priv->netdev) { ++ spin_unlock_irqrestore(&tx_spinlock, flags); ++ } ++ ++ return -1; + } + + static void txout_action(struct tc_priv *priv, struct aca_ring *txout) + { +- int i, cnt; +- struct dma_desc *desc; +- u32 ptr; +- void *mem; +- +- ring_cnt_update(txout); +- cnt = ring_dist(txout->idx, txout->cnt, txout->dnum); ++ struct aca_ring *txin = &g_plat_priv->soc_rings.txin; ++ struct tx_list *txlist = &g_plat_priv->soc_rings.txlist; ++ struct tx_list_item *txlist_item; ++ int i, cnt, bytes; ++ u32 *desc; ++ unsigned long flags; ++ ++ cnt = 0; ++ bytes = 0; ++ ++ if (g_plat_priv->netdev) { ++ netif_tx_lock(g_plat_priv->netdev); ++ } else { ++ spin_lock_irqsave(&tx_spinlock, flags); ++ } + +- for (i = 0; i < cnt; i++) { ++ for (i = 0; i < txout->dnum; i++) { + desc = txout->dbase_mem; + desc += txout->idx; +- /* read from memory */ +- if (ring_mmap(desc, sizeof(*desc), DMA_FROM_DEVICE, NULL) < 0) { +- tc_err(priv, MSG_TX, +- "map TXOUT DMA descriptor failed\n"); +- continue; ++ ++ // *desc seems to be a pointer to a QoSQ buffer or the data_ptr of some previously sent packet ++ if (*desc == 0) { ++ break; + } +- ptr = desc->data_ptr + desc->byte_off; +- mem = (void * __force)__va(ptr); +- kfree(mem); +- ring_idx_inc(txout, idx); +- } + +- if (cnt) +- writel(cnt, txout->umt_dst); +- pr_info("TXOUT received %d descriptors\n", cnt); +-} ++ if (txout->idx == txin->idx) { ++ tc_err(priv, MSG_TX, "TXOUT unexpected non-zero descriptor: txin: %d, txout: %d\n", ++ txin->idx, txout->idx); ++ break; ++ } + +-static void rxin_action(struct tc_priv *priv, +- struct aca_ring *rxin, int size, int cnt) +-{ +- int i, dist; +- struct dma_desc *desc; +- void *data_ptr; +- u32 phyaddr; +- +- if (ring_full(rxin)) { +- tc_dbg(priv, MSG_RX, +- "RXIN Ring Full!: idx: %d, cnt: %d\n", +- rxin->idx, rxin->cnt); +- return; +- } ++ txlist_item = &txlist->data[txout->idx]; + +- dist = ring_dist(rxin->idx, rxin->cnt, rxin->dnum); +- if (cnt > dist) { +- WARN_ONCE(1, "RXIN NO enough room for free buffers: free: %d, room: %d\n", +- cnt, dist); +- cnt = dist; ++ cnt++; ++ bytes += txlist_item->len; ++ ++ /* ++ * Reuse the returned buffer. The previous buffer should still be referenced by another descriptor. ++ * When the driver is unloaded, all buffers in the txlist as well as those referenced by the ++ * descriptors managed in ptm_tc.c or atm_tc.c will be freed. ++ */ ++ txlist_item->buf = plat_mem_virt(*desc); ++ txlist_item->phyaddr = *desc; ++ ++ *desc = 0; ++ ++ ring_idx_inc(txout); + } + +- for (i = 0; i < cnt; i++) { +- data_ptr = kmalloc(size, GFP_ATOMIC); +- if (!data_ptr) { +- tc_err(priv, MSG_RX, +- "RXIN kmalloc data buffer failed: %d\n", size); +- goto err1; +- } ++ if (cnt) { ++ writel(cnt, txout->umt_dst+0x28); // TXOUT_HD_ACCUM_SUB instead of TXOUT_HD_ACCUM_ADD + +- if (ring_mmap(data_ptr, size, DMA_FROM_DEVICE, &phyaddr) < 0) { +- tc_err(priv, MSG_RX, +- "RXIN kmalloc data buffer failed: %d\n", size); +- goto err2; ++ if (g_plat_priv->netdev) { ++ netdev_completed_queue(g_plat_priv->netdev, cnt, bytes); + } ++ } + +- desc = (struct dma_desc *)rxin->dbase_mem; +- desc += rxin->idx; +- memset(desc, 0, sizeof(*desc)); +- +- desc->data_len = size; +- desc->byte_off = phyaddr & 0x7; +- desc->eop = 1; +- desc->sop = 1; +- desc->own = 1; +- +- desc->data_ptr = phyaddr; +- +- +- if (ring_mmap(desc, sizeof(*desc), DMA_TO_DEVICE, NULL) < 0) { +- tc_err(priv, MSG_RX, "RXIN descriptor mmap failed: 0x%x\n", +- (unsigned int)desc); +- goto err2; +- } +- +- ring_idx_inc(rxin, idx); ++ if (g_plat_priv->netdev) { ++ netif_tx_unlock(g_plat_priv->netdev); ++ } else { ++ spin_unlock_irqrestore(&tx_spinlock, flags); + } + +- /* update RXIN UMT*/ +- writel(i, rxin->umt_dst); +- pr_info("rxin refill %d descriptors\n", i); +- return; ++ if (cnt && g_plat_priv->netdev && netif_queue_stopped(g_plat_priv->netdev)) { ++ netif_wake_queue(g_plat_priv->netdev); ++ } ++} + +-err2: +- kfree(data_ptr); +-err1: +- if (i) +- writel(i, rxin->umt_dst); +- return; ++static void rxin_action(struct tc_priv *priv, ++ struct aca_ring *rxin, int size, int cnt) ++{ ++ /* update RXIN UMT*/ ++ writel(cnt, rxin->umt_dst); + } + + static int rxout_action(struct tc_priv *priv, struct aca_ring *rxout) + { ++ struct device *pdev = priv->ep_dev[0].dev; + int i, cnt; +- struct dma_desc *desc; +- u32 ptr; +- void *mem; ++ struct dma_rx_desc *desc; ++ dma_addr_t phyaddr; ++ void *ptr, *dst; ++ size_t len; + struct sk_buff *skb; + +- ring_cnt_update(rxout); +- cnt = ring_dist(rxout->idx, rxout->cnt, rxout->dnum); +- +- for (i = 0; i < cnt; i++) { ++ cnt = 0; ++ for (i = 0; i < rxout->dnum; i++) { + desc = rxout->dbase_mem; + desc += rxout->idx; + +- /* read from memory */ +- if (ring_mmap(desc, sizeof(*desc), DMA_FROM_DEVICE, NULL) < 0) { +- tc_err(priv, MSG_RX, +- "map RXOUT DMA descriptor failed\n"); +- continue; ++ if (!desc->own) { ++ break; + } +- ptr = desc->data_ptr + desc->byte_off; +- mem = __va(ptr); +- skb = build_skb(mem, 0); +- if (!skb) { +- tc_err(priv, MSG_RX, +- "RXOUT build skb failed\n"); +- kfree(mem); +- continue; ++ ++ // this seems to be a pointer to a DS PKT buffer ++ phyaddr = desc->data_ptr + desc->byte_off; ++ ptr = plat_mem_virt(phyaddr); ++ ++ len = desc->data_len; ++ ++ dma_sync_single_range_for_cpu(pdev, phyaddr, 0, len, DMA_FROM_DEVICE); ++ ++ skb = netdev_alloc_skb(g_plat_priv->netdev, len); ++ if (unlikely(!skb)) { ++ tc_err(priv, MSG_RX, "RXOUT SKB allocation failed\n"); ++ break; + } +- priv->tc_ops.recv(NULL, skb); +- ring_idx_inc(rxout, idx); ++ ++ dst = skb_put(skb, len); ++ memcpy(dst, ptr, len); ++ ++ priv->tc_ops.recv(g_plat_priv->netdev, skb); ++ ++ desc->own = 0; ++ ++ cnt++; ++ ring_idx_inc(rxout); + } + + if (!cnt) +- tc_err(priv, MSG_RX, "RXOUT dummy interrupt: dbase: 0x%x, idx: %d, cnt: %d\n", +- (unsigned int)rxout->dbase_mem, rxout->idx, rxout->cnt); ++ tc_err(priv, MSG_RX, "RXOUT spurious interrupt\n"); + else +- writel(cnt, rxout->umt_dst); ++ writel(cnt, rxout->umt_dst+0x28); // RXOUT_HD_ACCUM_SUB instead of RXOUT_HD_ACCUM_ADD + +- pr_info("txout received %d packets\n", cnt); + return cnt; + } + +@@ -669,7 +622,6 @@ static void plat_rxout_tasklet(unsigned + struct aca_ring *rxin = &priv->soc_rings.rxin; + struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[rxout->ep_dev_idx]; + int cnt; +- + + cnt = rxout_action(tcpriv, rxout); + if (cnt) +@@ -687,68 +639,144 @@ static int plat_send(struct net_device * + { + struct plat_priv *priv = g_plat_priv; + struct aca_ring *txin = &priv->soc_rings.txin; ++ int res; + +- txin_action(priv->tc_priv, txin, skb, qid, type); ++ res = txin_action(priv->tc_priv, txin, skb, qid, type); + +- return 0; ++ return res; ++} ++ ++static void plat_mem_init(void) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ ++ hash_init(priv->mem_map); + } + + /* return virtual address */ +-static void *plat_mem_alloc(size_t size, enum tc_dir dir) ++static void *plat_mem_alloc(size_t size, enum tc_dir dir, u32 *phyaddr) + { +- return kmalloc(size, GFP_KERNEL); ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = priv->tc_priv; ++ struct device *pdev = tcpriv->ep_dev[0].dev; ++ enum dma_data_direction dma_dir; ++ struct mem_map_entry *entry; ++ ++ entry = kzalloc(sizeof(struct mem_map_entry), GFP_KERNEL); ++ if (!entry) ++ goto err; ++ ++ entry->size = size; ++ ++ entry->mem = kmalloc(size, GFP_KERNEL); ++ if (!entry->mem) ++ goto err_alloc; ++ ++ dma_dir = (dir == DS_DIR) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; ++ ++ entry->phyaddr = dma_map_single(pdev, entry->mem, entry->size, dma_dir); ++ if (unlikely(dma_mapping_error(pdev, entry->phyaddr))) { ++ tc_err(priv, MSG_INIT, ++ "plat_mem_alloc: DMA mapping error: buf: 0x%x, size: %d, dir: %d\n", ++ (u32)entry->mem, size, dir); ++ ++ goto err_map; ++ } ++ ++ hash_add(g_plat_priv->mem_map, &entry->node, entry->phyaddr); ++ ++ *phyaddr = entry->phyaddr; ++ return entry->mem; ++ ++err_map: ++ kfree(entry->mem); ++ ++err_alloc: ++ kfree(entry); ++ ++err: ++ return NULL; + } + +-static void plat_mem_free(u32 phy_addr, enum tc_dir dir) ++static void *plat_mem_virt(u32 phyaddr) + { +- void *mem; ++ struct mem_map_entry *entry; ++ ++ hash_for_each_possible(g_plat_priv->mem_map, entry, node, phyaddr) ++ if (entry->phyaddr == phyaddr) ++ return entry->mem; ++ ++ WARN_ON(1); ++ return NULL; ++} ++ ++static struct mem_map_entry *plat_mem_entry(u32 phyaddr) ++{ ++ struct mem_map_entry *entry; ++ ++ hash_for_each_possible(g_plat_priv->mem_map, entry, node, phyaddr) ++ if (entry->phyaddr == phyaddr) ++ return entry; + +- mem = (void * __force)__va(phy_addr); +- kfree(mem); ++ return NULL; + } + +-static void aca_soc_ring_init(struct tc_priv *priv, +- struct aca_ring *ring, u32 dnum, u32 dsize) ++static void plat_mem_free(u32 phyaddr, enum tc_dir dir) + { ++ struct tc_priv *priv = g_plat_priv->tc_priv; ++ struct device *pdev = priv->ep_dev[0].dev; ++ enum dma_data_direction dma_dir; ++ struct mem_map_entry *entry; ++ ++ entry = plat_mem_entry(phyaddr); ++ if (WARN_ON(!entry)) ++ return; ++ ++ hash_del(&entry->node); ++ ++ dma_dir = (dir == DS_DIR) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; ++ dma_unmap_single(pdev, entry->phyaddr, entry->size, dma_dir); ++ ++ kfree(entry->mem); ++ ++ kfree(entry); ++} ++ ++static int ring_init(struct tc_priv *priv, struct aca_ring *ring, u32 dnum, u32 dsize) ++{ ++ struct device *pdev = priv->ep_dev[0].dev; + int size; +- struct device *pdev; + + memset(ring, 0, sizeof(*ring)); + ring->dnum = dnum; ++ ring->dsize = dsize; ++ ++ if (ring->dnum == 0) { ++ return 0; ++ } ++ + size = dsize * dnum; +- pdev = priv->ep_dev[0].dev; + +- ring->dbase_mem = kmalloc(size, GFP_KERNEL); ++ ring->dbase_mem = dma_alloc_coherent(pdev, size, &(ring->dbase_phymem), GFP_KERNEL); + if (!ring->dbase_mem) { +- tc_err(priv, MSG_INIT, "Allocate SoC Ring fail: %d\n", dnum); +- return; ++ tc_err(priv, MSG_INIT, "Ring allocation failed: %d\n", dnum); ++ return -1; + } + +- ring_mmap(ring->dbase_mem, size, DMA_FROM_DEVICE, &(ring->dbase_phymem)); +- tc_dbg(priv, MSG_INIT, "ring: membase: 0x%x, phybase: 0x%x, dnum: %d\n", +- (u32)ring->dbase_mem, ring->dbase_phymem, ring->dnum); +- +- size = sizeof(u32); +- ring->cnt_addr = kzalloc(size, GFP_KERNEL); +- if (!ring->cnt_addr) { +- tc_err(priv, MSG_INIT, "Allocate cumulative counter fail!\n"); +- return; +- } ++ return 0; ++} + +- ring_mmap(ring->cnt_addr, size, DMA_TO_DEVICE, &(ring->cnt_phyaddr)); +- tc_dbg(priv, MSG_INIT, "ring: cumulative cnt addr: 0x%x, phy address: 0x%x\n", +- (u32)ring->cnt_addr, ring->cnt_phyaddr); ++#define ring_dnum(tcpriv, name1, name2) ((!tcpriv->param.name1##_dnum) ? name2##_DNUM : tcpriv->param.name1##_dnum) + +- return; +-} ++static void ring_free(struct tc_priv *priv, struct aca_ring *ring) ++{ ++ struct device *pdev = priv->ep_dev[0].dev; + +-#define ring_init(tcpriv, ring, name1, name2, num, size) \ +-{ \ +- if (!tcpriv->param.name1##_dnum) \ +- num = name2##_DNUM; \ +- else \ +- num = tcpriv->param.name1##_dnum; \ +- aca_soc_ring_init(tcpriv, ring, num, size); \ ++ if (ring->dnum == 0) { ++ return; ++ } ++ ++ dma_free_coherent(pdev, ring->dsize * ring->dnum, ring->dbase_mem, ring->dbase_phymem); + } + + static irqreturn_t aca_rx_irq_handler(int irq, void *dev_id) +@@ -777,39 +805,55 @@ static irqreturn_t aca_tx_irq_handler(in + return IRQ_HANDLED; + } + +-static void irq_init(struct tc_priv *priv, const char *dev_name) ++static void plat_irq_init(struct tc_priv *priv, const char *dev_name) + { + int ret; + int i; +- char name[IFNAMSIZ]; ++ //char name[IFNAMSIZ]; + + for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { +- sprintf(name, "%s%d", dev_name, i); ++ //snprintf(name, sizeof(name), "aca-rxo%d", i); + + ret = devm_request_irq(priv->ep_dev[i].dev, priv->ep_dev[i].aca_rx_irq, +- aca_rx_irq_handler, 0, name, &priv->ep_dev[i]); ++ aca_rx_irq_handler, 0, "aca-rxo", &priv->ep_dev[i]); + + if (ret) { + tc_err(priv, MSG_INIT, + "ACA RX IRQ request Fail!: irq: %d, ep_id: %d\n", + priv->ep_dev[i].aca_rx_irq, i); + //return; +- } ++ } ++ ++ //snprintf(name, sizeof(name), "aca-txo%d", i); + + ret = devm_request_irq(priv->ep_dev[i].dev, priv->ep_dev[i].aca_tx_irq, +- aca_tx_irq_handler, 0, name, &priv->ep_dev[i]); ++ aca_tx_irq_handler, 0, "aca-txo", &priv->ep_dev[i]); + + if (ret) { + tc_err(priv, MSG_INIT, + "ACA TX IRQ request Fail!: irq: %d, ep_id: %d\n", + priv->ep_dev[i].aca_tx_irq, i); + //return; +- } ++ } + } + + return; + } + ++static void plat_irq_free(struct tc_priv *priv) ++{ ++ int i; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ ++ /* Unregister RX irq handler */ ++ devm_free_irq(priv->ep_dev[i].dev, priv->ep_dev[i].aca_rx_irq, &priv->ep_dev[i]); ++ ++ /* Unregister TX irq handler */ ++ devm_free_irq(priv->ep_dev[i].dev, priv->ep_dev[i].aca_tx_irq, &priv->ep_dev[i]); ++ } ++} ++ + /** + * Decide txin/rxout queue size + * Create a tx/rx queue +@@ -819,29 +863,68 @@ static int plat_dp_init(struct plat_priv + struct tc_priv *tcpriv; + struct aca_ring_grp *soc_rings; + struct aca_ring *ring; +- int size; + u32 dnum; ++ int i; ++ int ret = 0; + + tcpriv = priv->tc_priv; + +- size = sizeof(struct dma_desc); ++ plat_mem_init(); ++ + soc_rings = &priv->soc_rings; + + /* txin ring */ + ring = &soc_rings->txin; +- ring_init(tcpriv, ring, txin, TXIN, dnum, size); ++ dnum = ring_dnum(tcpriv, txin, TXIN); ++ ret = txlist_init(&soc_rings->txlist, dnum); ++ if (ret < 0) ++ goto err5; ++ ret = ring_init(tcpriv, ring, dnum, sizeof(struct dma_tx_desc)); ++ if (ret < 0) ++ goto err4; + + /* txout ring */ + ring = &soc_rings->txout; +- ring_init(tcpriv, ring, txout, TXOUT, dnum, size); ++ dnum = ring_dnum(tcpriv, txout, TXOUT); ++ ret = ring_init(tcpriv, ring, dnum, sizeof(u32)); ++ if (ret < 0) ++ goto err3; ++ + /* rxin ring */ + ring = &soc_rings->rxin; +- ring_init(tcpriv, ring, rxin, RXIN, dnum, size); ++ dnum = ring_dnum(tcpriv, rxin, RXIN); ++ ret |= ring_init(tcpriv, ring, dnum, sizeof(struct dma_rx_desc)); ++ if (ret < 0) ++ goto err2; ++ + /* rxout ring */ + ring = &soc_rings->rxout; +- ring_init(tcpriv, ring, rxout, RXOUT, dnum, size); ++ dnum = ring_dnum(tcpriv, rxout, RXOUT); ++ ret = ring_init(tcpriv, ring, dnum, sizeof(struct dma_rx_desc)); ++ if (ret < 0) ++ goto err1; ++ ++ for (i = 0; i < EP_MAX_NUM && i < tcpriv->ep_num; i++) { ++ ++ /* Enable RX interrupt */ ++ tcpriv->ep_dev[i].hw_ops->icu_en(&tcpriv->ep_dev[i], ACA_HOSTIF_RX); ++ ++ /* Enable TX interrupt */ ++ tcpriv->ep_dev[i].hw_ops->icu_en(&tcpriv->ep_dev[i], ACA_HOSTIF_TX); ++ } + + return 0; ++ ++err1: ++ ring_free(tcpriv, &soc_rings->rxin); ++err2: ++ ring_free(tcpriv, &soc_rings->txout); ++err3: ++ ring_free(tcpriv, &soc_rings->txin); ++err4: ++ txlist_free(&soc_rings->txlist); ++err5: ++ return ret; + } + + /** +@@ -850,6 +933,26 @@ static int plat_dp_init(struct plat_priv + */ + static void plat_dp_exit(struct plat_priv *priv) + { ++ struct tc_priv *tcpriv = priv->tc_priv; ++ struct aca_ring_grp *soc_rings = &priv->soc_rings; ++ int i; ++ ++ for (i = 0; i < EP_MAX_NUM && i < tcpriv->ep_num; i++) { ++ ++ /* Disable RX interrupt */ ++ tcpriv->ep_dev[i].hw_ops->icu_mask(&tcpriv->ep_dev[i], ACA_HOSTIF_RX); ++ ++ /* Disable TX interrupt */ ++ tcpriv->ep_dev[i].hw_ops->icu_mask(&tcpriv->ep_dev[i], ACA_HOSTIF_TX); ++ } ++ ++ ring_free(tcpriv, &soc_rings->txin); ++ ring_free(tcpriv, &soc_rings->txout); ++ ring_free(tcpriv, &soc_rings->rxin); ++ ring_free(tcpriv, &soc_rings->rxout); ++ ++ txlist_free(&soc_rings->txlist); ++ + return; + } + +@@ -858,45 +961,45 @@ static int plat_soc_cfg_get(struct soc_c + struct plat_priv *priv = g_plat_priv; + + /* TXIN */ +- cfg->txin_dbase = priv->soc_rings.txin.dbase_phymem; +- cfg->txin_dnum = priv->soc_rings.txin.dnum; +- cfg->txin_desc_dwsz = DW_SZ(struct dma_desc); +- cfg->txin_cnt_phyaddr = priv->soc_rings.txin.cnt_phyaddr; ++ cfg->txin.soc_phydbase = priv->soc_rings.txin.dbase_phymem; ++ cfg->txin.soc_dnum = priv->soc_rings.txin.dnum; ++ cfg->txin.soc_desc_dwsz = DW_SZ(struct dma_tx_desc); + /* TXOUT */ +- cfg->txout_dbase = priv->soc_rings.txout.dbase_phymem; +- cfg->txout_dnum = priv->soc_rings.txout.dnum; +- cfg->txout_desc_dwsz = DW_SZ(struct dma_desc); +- cfg->txout_cnt_phyaddr = priv->soc_rings.txout.cnt_phyaddr; ++ cfg->txout.soc_phydbase = priv->soc_rings.txout.dbase_phymem; ++ cfg->txout.soc_dnum = priv->soc_rings.txout.dnum; ++ cfg->txout.soc_desc_dwsz = DW_SZ(u32); + /* RXOUT */ +- cfg->rxout_dbase = priv->soc_rings.rxout.dbase_phymem; +- cfg->rxout_dnum = priv->soc_rings.rxout.dnum; +- cfg->rxout_desc_dwsz = DW_SZ(struct dma_desc); +- cfg->rxout_cnt_phyaddr = priv->soc_rings.rxout.cnt_phyaddr; ++ cfg->rxout.soc_phydbase = priv->soc_rings.rxout.dbase_phymem; ++ cfg->rxout.soc_dnum = priv->soc_rings.rxout.dnum; ++ cfg->rxout.soc_desc_dwsz = DW_SZ(struct dma_rx_desc); + /* RXIN */ +- cfg->rxin_dbase = priv->soc_rings.rxin.dbase_phymem; +- cfg->rxin_dnum = priv->soc_rings.rxin.dnum; +- cfg->rxin_desc_dwsz = DW_SZ(struct dma_desc); +- cfg->rxin_cnt_phyaddr = priv->soc_rings.rxin.cnt_phyaddr; ++ cfg->rxin.soc_phydbase = priv->soc_rings.rxin.dbase_phymem; ++ cfg->rxin.soc_dnum = priv->soc_rings.rxin.dnum; ++ cfg->rxin.soc_desc_dwsz = DW_SZ(struct dma_rx_desc); + + tc_info(priv->tc_priv, MSG_INIT, + "id: %d, txin(0x%x: %d, 0x%x), txout(0x%x: %d, 0x%x), rxin(0x%x: %d, 0x%x), rxout(0x%x: %d, 0x%x)\n", +- id, cfg->txin_dbase, cfg->txin_dnum, cfg->txin_cnt_phyaddr, +- cfg->txout_dbase, cfg->txout_dnum, cfg->txout_cnt_phyaddr, +- cfg->rxin_dbase, cfg->rxout_dnum, cfg->rxin_cnt_phyaddr, +- cfg->rxout_dbase, cfg->rxout_dnum, cfg->rxout_cnt_phyaddr); ++ id, cfg->txin.soc_phydbase, cfg->txin.soc_dnum, cfg->txin.soc_cnt_phyaddr, ++ cfg->txout.soc_phydbase, cfg->txout.soc_dnum, cfg->txout.soc_cnt_phyaddr, ++ cfg->rxin.soc_phydbase, cfg->rxin.soc_dnum, cfg->rxin.soc_cnt_phyaddr, ++ cfg->rxout.soc_phydbase, cfg->rxout.soc_dnum, cfg->rxout.soc_cnt_phyaddr); + + return 0; + } + +-static int plat_open(struct net_device *pdev, char *dev_name, +- int *subif, int flag) ++static int plat_open(struct net_device *pdev, const char *dev_name, ++ int id, int flag) + { ++ g_plat_priv->netdev = pdev; ++ + return 0; + } + +-static void plat_close(struct net_device *pdev, char *dev_name, +- int subif, int flag) ++static void plat_close(struct net_device *pdev, const char *dev_name, ++ int flag) + { ++ g_plat_priv->netdev = NULL; ++ + return; + } + +@@ -971,7 +1074,6 @@ static void plat_disable_us(int en) + static int plat_get_mib(struct net_device *pdev, + struct rtnl_link_stats64 *stat) + { +- pr_info("%s is not supported\n", __func__); + return -ENOTSUPP; + } + +@@ -1181,8 +1283,8 @@ int platform_init(struct tc_priv *tc_pri + INIT_WORK(&priv->req_work.work, plat_tc_req_workqueue); + tasklet_init(&txout_task, plat_txout_tasklet, 0); + tasklet_init(&rxout_task, plat_rxout_tasklet, 0); +- irq_init(tc_priv, drv_name); +- //tasklet_init(&priv->coc.coc_task, plat_coc_tasklet, 0); ++ plat_irq_init(tc_priv, drv_name); ++ + plat_tc_ops_setup(tc_priv); + plat_dsl_ops_setup(); + +@@ -1201,8 +1303,15 @@ void platform_dsl_exit(void) + + void platform_exit(void) + { +- //tasklet_kill(&g_plat_priv->coc.coc_task); ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ ++ tasklet_kill(&txout_task); ++ tasklet_kill(&rxout_task); ++ ++ plat_irq_free(tcpriv); ++ + plat_dp_exit(g_plat_priv); ++ + g_plat_priv = NULL; + } + diff --git a/package/kernel/lantiq/vrx518_tc/patches/201-desc-length.patch b/package/kernel/lantiq/vrx518_tc/patches/201-desc-length.patch new file mode 100644 index 00000000000..8b30914df96 --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/201-desc-length.patch @@ -0,0 +1,342 @@ +Port FEATURE_CONF_DESC_LENGTH from the grx500 variant of the driver. +This also reduces the default length of some descriptors, resulting in +significantly lower latencies when the line is saturated. + +--- a/dcdp/inc/tc_common.h ++++ b/dcdp/inc/tc_common.h +@@ -27,7 +27,11 @@ + #define UMT_DEF_PERIOD 400 /* microseconds */ + + #define MAX_MTU (DMA_PACKET_SZ - ETH_HLEN - HD_RSRV_SZ) ++#ifdef FEATURE_CONF_DESC_LENGTH ++#define QOSQ_NUM 8 ++#else + #define QOSQ_NUM 2 ++#endif + #define FW_STOP_TIMEOUT 20 /* millisecond */ + #define QOS_DISPATCH_OWN 0 + #define ACA_TXIN_POLL_INTVAL 10 /* millisecond */ +--- a/dcdp/inc/tc_main.h ++++ b/dcdp/inc/tc_main.h +@@ -30,6 +30,7 @@ + #define TCPRIV_ALIGN 32 + #define DMA_PACKET_SZ 2048 + ++#define FEATURE_CONF_DESC_LENGTH 1 + #define FEATURE_POWER_DOWN 1 + + enum { +@@ -157,6 +158,25 @@ struct tc_param { + unsigned int txout_dnum; + unsigned int rxin_dnum; + unsigned int rxout_dnum; ++ ++#ifdef FEATURE_CONF_DESC_LENGTH ++ /* __US_FAST_PATH_DES_LIST_NUM:64 ++ * __ACA_TX_IN_PD_LIST_NUM ++ * __ACA_TX_OUT_PD_LIST_NUM ++ * */ ++ u32 conf_us_fp_desq_len; ++ /* ++ * Number of queue per QoS queue: QOS_DES_NUM / QOSQ_NUM ++ * */ ++ u32 conf_us_qos_queue_len; ++ /* __US_OUTQ0_DES_LIST_NUM: 32 ++ * __US_OUTQ1_DES_LIST_NUM: 32 ++ * OUTQ_DESC_PER_Q ++ * */ ++ u32 conf_us_outq_len; ++ /**/ ++ u32 conf_us_local_q0_desq_len; ++#endif + }; + + struct cdma { +--- a/dcdp/ptm_tc.c ++++ b/dcdp/ptm_tc.c +@@ -75,7 +75,11 @@ static const u32 tx_kvec[] = { + 0x30B1B233, 0xB43536B7, 0xB8393ABB, 0x3CBDBE3F, + 0xC04142C3, 0x44C5C647, 0x48C9CA4B, 0xCC4D4ECF + }; ++#ifndef FEATURE_CONF_DESC_LENGTH + static const u32 def_outq_map[OUTQ_PNUM] = {0x1, 0xFE}; ++#else ++static const u32 def_outq_map[OUTQ_PNUM] = {0x0, 0xFF}; ++#endif + static const char ptm_drv_name[] = "PTM SL"; + static const char ptm_bond_name[][IFNAMSIZ] = {"PTM US BOND", "PTM DS BOND"}; + +@@ -1005,6 +1009,10 @@ static void us_fp_desq_cfg_ctxt_init(str + int i; + u32 desc_addr; + rx_descriptor_t desc; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++#endif + + memset(&desq_cfg, 0, sizeof(desq_cfg)); + /* Initialize US Fast-Path Descriptor Queue Config/Context */ +@@ -1012,7 +1020,11 @@ static void us_fp_desq_cfg_ctxt_init(str + desq_cfg.fast_path = 1; + desq_cfg.mbox_int_en = 0; + desq_cfg.des_sync_needed = 0; ++#ifndef FEATURE_CONF_DESC_LENGTH + desq_cfg.des_num = __US_FAST_PATH_DES_LIST_NUM; ++#else ++ desq_cfg.des_num = tc_priv->param.conf_us_fp_desq_len; ++#endif + desq_cfg.des_base_addr = __US_FAST_PATH_DES_LIST_BASE; + + tc_mem_write(priv, fpi_addr(__US_FP_INQ_DES_CFG_CTXT), +@@ -1036,12 +1048,20 @@ static void us_qos_desq_cfg_ctxt_init(st + int offset, i; + rx_descriptor_t desc; + u32 phy_addr; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++#endif + + /* Setup QoSQ_CFG_CTXT */ + memset(&qosq_cfg_ctxt, 0, sizeof(qosq_cfg_ctxt)); + + qosq_cfg_ctxt.threshold = 8; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ qosq_cfg_ctxt.des_num = tc_priv->param.conf_us_qos_queue_len; ++#else + qosq_cfg_ctxt.des_num = QOS_DES_NUM / QOSQ_NUM; ++#endif + + offset = 0; + for (i = 0; i < QOSQ_NUM; i++) { +@@ -1080,6 +1100,10 @@ static void us_outq_desq_cfg_ctxt_init(s + u32 phy_addr; + int i; + u32 offset; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++#endif + + /* Setup OUTQ_QoS_CFG_CTXT */ + /* NOTE: By default, Shaping & WFQ both are DISABLED!! */ +@@ -1108,7 +1132,11 @@ static void us_outq_desq_cfg_ctxt_init(s + desq_cfg.des_in_own_val = US_OUTQ_DES_OWN; + desq_cfg.mbox_int_en = 0; + desq_cfg.des_sync_needed = 0; +- desq_cfg.des_num = 32; ++#ifndef FEATURE_CONF_DESC_LENGTH ++ desq_cfg.des_num = OUTQ_DESC_PER_Q; ++#else ++ desq_cfg.des_num = tc_priv->param.conf_us_outq_len; ++#endif + /** + * Only BC0 is used in VRX518 + */ +@@ -1174,7 +1202,11 @@ static void us_qos_cfg_init(struct ptm_e + /* Set QoS NO DROP */ + sb_w32(1, __QOSQ_NO_DROP); + /* Enable Preemption function/Disable QoS by default */ ++#ifdef FEATURE_CONF_DESC_LENGTH ++ sb_w32(0, _CHK_PREEMP_MAP); ++#else + sb_w32(1, _CHK_PREEMP_MAP); ++#endif + /* By default, all qid mappint to non-preemption queue */ + sb_w32(0x0, _QID2PREEMP_MAP); + +@@ -1376,6 +1408,11 @@ static void ptm_local_desq_cfg_ctxt_init + u32 dcnt, addr, pdbram_base; + unsigned int us_des_alloc[] = { + __US_TC_LOCAL_Q0_DES_LIST_NUM, __US_TC_LOCAL_Q1_DES_LIST_NUM}; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++ us_des_alloc[0] = tc_priv->param.conf_us_local_q0_desq_len; ++#endif + + /* Setup the Local DESQ Configuration/Context for UpStream Queues */ + memset(&desq_cfg, 0, sizeof(desq_cfg)); +@@ -2321,6 +2358,10 @@ static void ptm_aca_init(struct ptm_ep_p + u32 phybase = priv->ep->phy_membase; + u32 start; + u32 type; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ struct tc_priv *tc_priv; ++ tc_priv = priv->tc_priv; ++#endif + + priv->tc_priv->tc_ops.soc_cfg_get(&priv->tc_priv->cfg, ptm_id(priv)); + memset(¶m, 0, sizeof(param)); +@@ -2334,7 +2375,11 @@ static void ptm_aca_init(struct ptm_ep_p + #endif + txin->hd_size_in_dw = cfg->txin.soc_desc_dwsz; + txin->pd_desc_base = SB_XBAR_ADDR(__ACA_TX_IN_PD_LIST_BASE); ++#ifndef FEATURE_CONF_DESC_LENGTH + txin->pd_desc_num = __ACA_TX_IN_PD_LIST_NUM; ++#else ++ txin->pd_desc_num = tc_priv->param.conf_us_fp_desq_len; ++#endif + txin->pd_size_in_dw = DESC_DWSZ; + txin->soc_desc_base = cfg->txin.soc_phydbase; + txin->soc_desc_num = cfg->txin.soc_dnum; +--- a/dcdp/tc_main.c ++++ b/dcdp/tc_main.c +@@ -182,6 +182,12 @@ static inline void init_local_param(stru + priv->param.txout_dnum = txout_num; + priv->param.rxin_dnum = rxin_num; + priv->param.rxout_dnum = rxout_num; ++#ifdef FEATURE_CONF_DESC_LENGTH ++ priv->param.conf_us_fp_desq_len = 32; ++ priv->param.conf_us_qos_queue_len = 32; ++ priv->param.conf_us_outq_len = 32; ++ priv->param.conf_us_local_q0_desq_len = 16; ++#endif + priv->tc_mode = TC_NONE_MODE; + priv->tc_stat = NO_TC; + +--- a/dcdp/tc_proc.c ++++ b/dcdp/tc_proc.c +@@ -1114,6 +1114,9 @@ static int proc_read_ver(struct seq_file + (date >> 16) & 0xff, + (date & 0xffff)); + ++#ifdef FEATURE_CONF_DESC_LENGTH ++ seq_puts(seq, " + Support QoS and Configurable descriptor length\n"); ++#endif + #ifdef FEATURE_POWER_DOWN + seq_puts(seq, " + Support Power Down enhancement feature\n"); + #endif +@@ -1166,6 +1169,113 @@ static const struct proc_ops tc_soc_proc + .proc_release = single_release, + }; + ++#ifdef FEATURE_CONF_DESC_LENGTH ++static ssize_t proc_write_desc_conf(struct file *file, const char __user *buf, ++ size_t count, loff_t *data) ++{ ++ struct tc_priv *priv; ++ char str[32]; ++ int len, rlen, temp; ++ int num, temp_num; ++ char *param_list[20]; ++ len = count < sizeof(str) ? count : sizeof(str) - 1; ++ rlen = len - copy_from_user(str, buf, len); ++ str[rlen] = 0; ++ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ priv = (struct tc_priv *)PDE_DATA(file_inode(file)); ++ if (priv == NULL) ++ return count; ++ ++ num = vrx_split_buffer(str, param_list, ARRAY_SIZE(param_list)); ++ if (num < 1 || num > 4) ++ goto proc_dbg_desc_conf; ++ ++ temp_num = num; ++ if (num-- != 0) { ++ temp = vrx_atoi(param_list[0]); ++ if (temp < 1 || temp > 128) { ++ pr_info("Fastpath valid range: 1 -> 128\n"); ++ goto proc_dbg_desc_conf; ++ } ++ } ++ if (num-- != 0) { ++ temp = vrx_atoi(param_list[1]); ++ if (temp < 1 || temp > 63) { ++ pr_info("QoS valid range: 1 -> 63\n"); ++ goto proc_dbg_desc_conf; ++ } ++ } ++ if (num-- != 0) { ++ temp = vrx_atoi(param_list[2]); ++ if (temp < 1 || temp > 128) { ++ pr_info("OutQ valid range: 1 -> 128\n"); ++ goto proc_dbg_desc_conf; ++ } ++ } ++ if (num-- != 0) { ++ temp = vrx_atoi(param_list[3]); ++ if (temp < 4 || temp > 16) { ++ pr_info("Local Q0 valid range: 4 -> 16\n"); ++ goto proc_dbg_desc_conf; ++ } ++ } ++ num = temp_num; ++ if (num-- != 0) { ++ priv->param.conf_us_fp_desq_len = vrx_atoi(param_list[0]); ++ } ++ if (num-- != 0) { ++ priv->param.conf_us_qos_queue_len = vrx_atoi(param_list[1]); ++ } ++ if (num-- != 0) { ++ priv->param.conf_us_outq_len = vrx_atoi(param_list[2]); ++ } ++ if (num-- != 0) { ++ priv->param.conf_us_local_q0_desq_len = vrx_atoi(param_list[3]); ++ } ++ ++ return count; ++ ++proc_dbg_desc_conf: ++ pr_info("echo [FP] [QoS] [OutQ] [LocalQ0]> desc_conf\n"); ++ return count; ++} ++ ++static int proc_read_desc_conf(struct seq_file *seq, void *v) ++{ ++ struct tc_priv *priv; ++ priv = (struct tc_priv *)seq->private; ++ if (priv == NULL) ++ return -1; ++ seq_puts(seq, "Upstream descriptor length information:\n"); ++ seq_printf(seq, " - Fastpath: %d\n", ++ priv->param.conf_us_fp_desq_len); ++ seq_printf(seq, " - QoS: %d\n", ++ priv->param.conf_us_qos_queue_len); ++ seq_printf(seq, " - OutQ: %d\n", ++ priv->param.conf_us_outq_len); ++ seq_printf(seq, " - Local Q0: %d\n", ++ priv->param.conf_us_local_q0_desq_len); ++ seq_puts(seq, "\n"); ++ return 0; ++} ++ ++static int proc_read_desc_conf_seq_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, proc_read_desc_conf, PDE_DATA(inode)); ++} ++#endif ++ ++static const struct proc_ops tc_desc_conf_proc_fops = { ++ .proc_open = proc_read_desc_conf_seq_open, ++ .proc_read = seq_read, ++ .proc_write = proc_write_desc_conf, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++ + static struct tc_proc_list tc_procs[] = { + {TC_PROC_DIR, 0, NULL, 1}, + {"cfg", 0644, &tc_cfg_proc_fops, 0}, +@@ -1174,6 +1284,9 @@ static struct tc_proc_list tc_procs[] = + {"showtime", 0200, &tc_show_time_proc_fops, 0}, + {"ver", 0644, &tc_ver_proc_fops, 0}, + {"soc", 0644, &tc_soc_proc_fops, 0}, ++#ifdef FEATURE_CONF_DESC_LENGTH ++ {"desc_conf", 0644, &tc_desc_conf_proc_fops, 0}, ++#endif + }; + + int tc_proc_init(struct tc_priv *priv) +@@ -1333,7 +1446,6 @@ proc_ptm_cfg_help: + return count; + } + +- + static const struct proc_ops ptm_cfg_proc_fops = { + .proc_open = proc_read_cfg_seq_open, + .proc_read = seq_read, diff --git a/package/kernel/lantiq/vrx518_tc/patches/202-napi.patch b/package/kernel/lantiq/vrx518_tc/patches/202-napi.patch new file mode 100644 index 00000000000..55f0cc10667 --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/202-napi.patch @@ -0,0 +1,423 @@ +--- a/dcdp/platform/sw_plat.c ++++ b/dcdp/platform/sw_plat.c +@@ -208,6 +208,8 @@ struct plat_priv { + struct tc_req req_work; + struct aca_ring_grp soc_rings; + struct net_device *netdev; ++ struct napi_struct *napi_tx; ++ struct napi_struct *napi_rx; + DECLARE_HASHTABLE(mem_map, 8); + }; + +@@ -472,7 +474,7 @@ err2: + return -1; + } + +-static void txout_action(struct tc_priv *priv, struct aca_ring *txout) ++static int txout_action(struct tc_priv *priv, struct aca_ring *txout, int budget) + { + struct aca_ring *txin = &g_plat_priv->soc_rings.txin; + struct tx_list *txlist = &g_plat_priv->soc_rings.txlist; +@@ -490,7 +492,10 @@ static void txout_action(struct tc_priv + spin_lock_irqsave(&tx_spinlock, flags); + } + +- for (i = 0; i < txout->dnum; i++) { ++ if (budget == 0 || budget > txout->dnum) ++ budget = txout->dnum; ++ ++ for (i = 0; i < budget; i++) { + desc = txout->dbase_mem; + desc += txout->idx; + +@@ -540,6 +545,8 @@ static void txout_action(struct tc_priv + if (cnt && g_plat_priv->netdev && netif_queue_stopped(g_plat_priv->netdev)) { + netif_wake_queue(g_plat_priv->netdev); + } ++ ++ return cnt; + } + + static void rxin_action(struct tc_priv *priv, +@@ -549,7 +556,7 @@ static void rxin_action(struct tc_priv * + writel(cnt, rxin->umt_dst); + } + +-static int rxout_action(struct tc_priv *priv, struct aca_ring *rxout) ++static int rxout_action(struct tc_priv *priv, struct aca_ring *rxout, int budget) + { + struct device *pdev = priv->ep_dev[0].dev; + int i, cnt; +@@ -559,8 +566,11 @@ static int rxout_action(struct tc_priv * + size_t len; + struct sk_buff *skb; + ++ if (budget == 0 || budget > rxout->dnum) ++ budget = rxout->dnum; ++ + cnt = 0; +- for (i = 0; i < rxout->dnum; i++) { ++ for (i = 0; i < budget; i++) { + desc = rxout->dbase_mem; + desc += rxout->idx; + +@@ -593,14 +603,30 @@ static int rxout_action(struct tc_priv * + ring_idx_inc(rxout); + } + +- if (!cnt) +- tc_err(priv, MSG_RX, "RXOUT spurious interrupt\n"); +- else ++ if (cnt) + writel(cnt, rxout->umt_dst+0x28); // RXOUT_HD_ACCUM_SUB instead of RXOUT_HD_ACCUM_ADD + + return cnt; + } + ++static int plat_txout_napi(struct napi_struct *napi, int budget) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ struct aca_ring *txout = &priv->soc_rings.txout; ++ struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[txout->ep_dev_idx]; ++ int cnt; ++ ++ cnt = txout_action(tcpriv, txout, budget); ++ ++ if (cnt < budget) { ++ if (napi_complete_done(napi, cnt)) ++ ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_TX); ++ } ++ ++ return cnt; ++} ++ + static void plat_txout_tasklet(unsigned long arg) + { + struct plat_priv *priv = g_plat_priv; +@@ -608,12 +634,33 @@ static void plat_txout_tasklet(unsigned + struct aca_ring *txout = &priv->soc_rings.txout; + struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[txout->ep_dev_idx]; + +- txout_action(tcpriv, txout); ++ txout_action(tcpriv, txout, 0); + + /* Enable interrupt */ + ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_TX); + } + ++static int plat_rxout_napi(struct napi_struct *napi, int budget) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ struct aca_ring *rxout = &priv->soc_rings.rxout; ++ struct aca_ring *rxin = &priv->soc_rings.rxin; ++ struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[rxout->ep_dev_idx]; ++ int cnt; ++ ++ cnt = rxout_action(tcpriv, rxout, budget); ++ if (cnt) ++ rxin_action(tcpriv, rxin, DMA_PACKET_SZ, cnt); ++ ++ if (cnt < budget) { ++ if (napi_complete_done(napi, cnt)) ++ ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_RX); ++ } ++ ++ return cnt; ++} ++ + static void plat_rxout_tasklet(unsigned long arg) + { + struct plat_priv *priv = g_plat_priv; +@@ -623,7 +670,7 @@ static void plat_rxout_tasklet(unsigned + struct dc_ep_dev *ep_dev = &tcpriv->ep_dev[rxout->ep_dev_idx]; + int cnt; + +- cnt = rxout_action(tcpriv, rxout); ++ cnt = rxout_action(tcpriv, rxout, 0); + if (cnt) + rxin_action(tcpriv, rxin, DMA_PACKET_SZ, cnt); + +@@ -783,11 +830,22 @@ static irqreturn_t aca_rx_irq_handler(in + { + struct dc_ep_dev *ep_dev = dev_id; + +- /* Disable IRQ in IMCU */ +- ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_RX); ++ if (g_plat_priv->napi_rx) { ++ ++ if (napi_schedule_prep(g_plat_priv->napi_rx)) { ++ ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_RX); ++ __napi_schedule(g_plat_priv->napi_rx); ++ } ++ ++ } else { ++ ++ /* Disable IRQ in IMCU */ ++ ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_RX); + +- /* Start tasklet */ +- tasklet_schedule(&rxout_task); ++ /* Start tasklet */ ++ tasklet_schedule(&rxout_task); ++ ++ } + + return IRQ_HANDLED; + } +@@ -796,15 +854,62 @@ static irqreturn_t aca_tx_irq_handler(in + { + struct dc_ep_dev *ep_dev = dev_id; + +- /* Disable IRQ in IMCU */ +- ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_TX); ++ if (g_plat_priv->napi_tx) { + +- /* Start tasklet */ +- tasklet_schedule(&txout_task); ++ if (napi_schedule_prep(g_plat_priv->napi_tx)) { ++ ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_TX); ++ __napi_schedule(g_plat_priv->napi_tx); ++ } ++ ++ } else { ++ ++ /* Disable IRQ in IMCU */ ++ ep_dev->hw_ops->icu_mask(ep_dev, ACA_HOSTIF_TX); ++ ++ /* Start tasklet */ ++ tasklet_schedule(&txout_task); ++ ++ } + + return IRQ_HANDLED; + } + ++static void plat_net_open(void) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ struct aca_ring *rxout = &priv->soc_rings.rxout; ++ struct aca_ring *txout = &priv->soc_rings.txout; ++ struct dc_ep_dev *ep_dev_rx = &tcpriv->ep_dev[rxout->ep_dev_idx]; ++ struct dc_ep_dev *ep_dev_tx = &tcpriv->ep_dev[txout->ep_dev_idx]; ++ ++ if (priv->napi_rx) ++ napi_enable(priv->napi_rx); ++ ep_dev_rx->hw_ops->icu_en(ep_dev_rx, ACA_HOSTIF_RX); ++ ++ if (priv->napi_tx) ++ napi_enable(priv->napi_tx); ++ ep_dev_tx->hw_ops->icu_en(ep_dev_tx, ACA_HOSTIF_TX); ++} ++ ++static void plat_net_stop(void) ++{ ++ struct plat_priv *priv = g_plat_priv; ++ struct tc_priv *tcpriv = plat_to_tcpriv(); ++ struct aca_ring *rxout = &priv->soc_rings.rxout; ++ struct aca_ring *txout = &priv->soc_rings.txout; ++ struct dc_ep_dev *ep_dev_rx = &tcpriv->ep_dev[rxout->ep_dev_idx]; ++ struct dc_ep_dev *ep_dev_tx = &tcpriv->ep_dev[txout->ep_dev_idx]; ++ ++ if (priv->napi_tx) ++ napi_disable(priv->napi_tx); ++ ep_dev_tx->hw_ops->icu_mask(ep_dev_tx, ACA_HOSTIF_TX); ++ ++ if (priv->napi_rx) ++ napi_disable(priv->napi_rx); ++ ep_dev_rx->hw_ops->icu_mask(ep_dev_rx, ACA_HOSTIF_RX); ++} ++ + static void plat_irq_init(struct tc_priv *priv, const char *dev_name) + { + int ret; +@@ -988,17 +1093,49 @@ static int plat_soc_cfg_get(struct soc_c + } + + static int plat_open(struct net_device *pdev, const char *dev_name, ++ struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int id, int flag) + { ++ struct tc_priv *priv = g_plat_priv->tc_priv; ++ int i; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ disable_irq(priv->ep_dev[i].aca_rx_irq); ++ disable_irq(priv->ep_dev[i].aca_tx_irq); ++ } ++ + g_plat_priv->netdev = pdev; ++ g_plat_priv->napi_tx = napi_tx; ++ g_plat_priv->napi_rx = napi_rx; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ enable_irq(priv->ep_dev[i].aca_rx_irq); ++ enable_irq(priv->ep_dev[i].aca_tx_irq); ++ } + + return 0; + } + + static void plat_close(struct net_device *pdev, const char *dev_name, ++ struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int flag) + { ++ struct tc_priv *priv = g_plat_priv->tc_priv; ++ int i; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ disable_irq(priv->ep_dev[i].aca_rx_irq); ++ disable_irq(priv->ep_dev[i].aca_tx_irq); ++ } ++ + g_plat_priv->netdev = NULL; ++ g_plat_priv->napi_tx = NULL; ++ g_plat_priv->napi_rx = NULL; ++ ++ for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { ++ enable_irq(priv->ep_dev[i].aca_rx_irq); ++ enable_irq(priv->ep_dev[i].aca_tx_irq); ++ } + + return; + } +@@ -1084,6 +1221,10 @@ static void plat_tc_ops_setup(struct tc_ + priv->tc_ops.free = plat_mem_free; + priv->tc_ops.dev_reg = plat_open; + priv->tc_ops.dev_unreg = plat_close; ++ priv->tc_ops.net_open = plat_net_open; ++ priv->tc_ops.net_stop = plat_net_stop; ++ priv->tc_ops.napi_tx = plat_txout_napi; ++ priv->tc_ops.napi_rx = plat_rxout_napi; + priv->tc_ops.umt_init = plat_umt_init; + priv->tc_ops.umt_exit = plat_umt_exit; + priv->tc_ops.umt_start = plat_umt_start; +--- a/dcdp/atm_tc.c ++++ b/dcdp/atm_tc.c +@@ -3650,7 +3650,7 @@ static void atm_aca_ring_config_init(str + static int atm_ring_init(struct atm_priv *priv) + { + atm_aca_ring_config_init(priv); +- return priv->tc_priv->tc_ops.dev_reg(NULL, g_atm_dev_name, 0, 0); ++ return priv->tc_priv->tc_ops.dev_reg(NULL, g_atm_dev_name, NULL, NULL, 0, 0); + } + + static int atm_init(struct tc_priv *tcpriv, u32 ep_id) +@@ -4020,7 +4020,7 @@ void atm_tc_unload(void) + /* unregister device */ + if (priv->tc_priv->tc_ops.dev_unreg != NULL) + priv->tc_priv->tc_ops.dev_unreg(NULL, +- g_atm_dev_name, 0); ++ g_atm_dev_name, NULL, NULL, 0); + + /* atm_dev_deinit(priv); */ + /* modem module power off */ +--- a/dcdp/inc/tc_main.h ++++ b/dcdp/inc/tc_main.h +@@ -209,9 +209,15 @@ struct tc_hw_ops { + void (*subif_unreg)(struct net_device *pdev, const char *dev_name, + int subif_id, int flag); + int (*dev_reg)(struct net_device *pdev, const char *dev_name, ++ struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int id, int flag); + void (*dev_unreg)(struct net_device *pdev, const char *dev_name, ++ struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int flag); ++ void (*net_open)(void); ++ void (*net_stop)(void); ++ int (*napi_tx)(struct napi_struct *napi, int budget); ++ int (*napi_rx)(struct napi_struct *napi, int budget); + + /*umt init/exit including the corresponding DMA init/exit */ + int (*umt_init)(u32 umt_id, u32 umt_period, u32 umt_dst); +--- a/dcdp/ptm_tc.c ++++ b/dcdp/ptm_tc.c +@@ -141,7 +141,11 @@ static int ptm_open(struct net_device *d + struct ptm_priv *ptm_tc = netdev_priv(dev); + + tc_info(ptm_tc->tc_priv, MSG_EVENT, "ptm open\n"); ++ ++ ptm_tc->tc_priv->tc_ops.net_open(); ++ + netif_tx_start_all_queues(dev); ++ + #ifdef CONFIG_SOC_TYPE_XWAY + xet_phy_wan_port(7, NULL, 1, 1); + if (ppa_hook_ppa_phys_port_add_fn) +@@ -158,7 +162,11 @@ static int ptm_stop(struct net_device *d + struct ptm_priv *ptm_tc = netdev_priv(dev); + + tc_info(ptm_tc->tc_priv, MSG_EVENT, "ptm stop\n"); ++ + netif_tx_stop_all_queues(dev); ++ ++ ptm_tc->tc_priv->tc_ops.net_stop(); ++ + #ifdef CONFIG_SOC_TYPE_XWAY + if (ppa_drv_datapath_mac_entry_setting) + ppa_drv_datapath_mac_entry_setting(dev->dev_addr, 0, 6, 10, 1, 2); +@@ -555,7 +563,7 @@ static void ptm_rx(struct net_device *de + ptm_tc->stats64.rx_packets++; + ptm_tc->stats64.rx_bytes += skb->len; + +- if (netif_rx(skb) == NET_RX_DROP) ++ if (netif_receive_skb(skb) == NET_RX_DROP) + ptm_tc->stats64.rx_dropped++; + + return; +@@ -651,6 +659,9 @@ static int ptm_dev_init(struct tc_priv * + memcpy(ptm_tc->outq_map, def_outq_map, sizeof(def_outq_map)); + SET_NETDEV_DEV(ptm_tc->dev, tc_priv->ep_dev[id].dev); + ++ netif_napi_add(ptm_tc->dev, &ptm_tc->napi_rx, tc_priv->tc_ops.napi_rx, NAPI_POLL_WEIGHT); ++ netif_tx_napi_add(ptm_tc->dev, &ptm_tc->napi_tx, tc_priv->tc_ops.napi_tx, NAPI_POLL_WEIGHT); ++ + err = register_netdev(ptm_tc->dev); + if (err) + goto err1; +@@ -2605,7 +2616,9 @@ static int ptm_ring_init(struct ptm_ep_p + { + ptm_aca_ring_config_init(priv, id, bonding); + return priv->tc_priv->tc_ops.dev_reg(priv->ptm_tc->dev, +- priv->ptm_tc->dev->name, id, bonding); ++ priv->ptm_tc->dev->name, ++ &priv->ptm_tc->napi_tx, &priv->ptm_tc->napi_rx, ++ id, bonding); + } + + /** +@@ -2960,7 +2973,9 @@ void ptm_tc_unload(enum dsl_tc_mode tc_m + /* unregister device */ + if (ptm_tc->tc_priv->tc_ops.dev_unreg != NULL) + ptm_tc->tc_priv->tc_ops.dev_unreg(ptm_tc->dev, +- ptm_tc->dev->name, 0); ++ ptm_tc->dev->name, ++ &priv->ptm_tc->napi_tx, &priv->ptm_tc->napi_rx, ++ 0); + + /* remove PTM callback function */ + ptm_cb_setup(ptm_tc, 0); +@@ -2978,6 +2993,10 @@ void ptm_exit(void) + + if (!priv) + return; ++ ++ netif_napi_del(&priv->napi_tx); ++ netif_napi_del(&priv->napi_rx); ++ + unregister_netdev(priv->dev); + free_netdev(priv->dev); + +--- a/dcdp/inc/ptm_tc.h ++++ b/dcdp/inc/ptm_tc.h +@@ -119,6 +119,8 @@ struct ptm_priv { + u32 ep_id; + struct ppe_fw fw; + struct net_device *dev; ++ struct napi_struct napi_tx; ++ struct napi_struct napi_rx; + spinlock_t ptm_lock; + struct rtnl_link_stats64 stats64; + int subif_id; diff --git a/package/kernel/lantiq/vrx518_tc/patches/203-dbg.patch b/package/kernel/lantiq/vrx518_tc/patches/203-dbg.patch new file mode 100644 index 00000000000..687e66f991e --- /dev/null +++ b/package/kernel/lantiq/vrx518_tc/patches/203-dbg.patch @@ -0,0 +1,120 @@ +--- a/dcdp/platform/sw_plat.c ++++ b/dcdp/platform/sw_plat.c +@@ -85,6 +85,7 @@ struct aca_ring { + u32 dnum; + u32 dsize; + int idx; /* SoC RX/TX index */ ++ u64 cnt; + int ep_dev_idx; + }; + +@@ -210,6 +211,8 @@ struct plat_priv { + struct net_device *netdev; + struct napi_struct *napi_tx; + struct napi_struct *napi_rx; ++ u64 napi_tx_stats[NAPI_POLL_WEIGHT+1]; ++ u64 napi_rx_stats[NAPI_POLL_WEIGHT+1]; + DECLARE_HASHTABLE(mem_map, 8); + }; + +@@ -362,6 +365,7 @@ static void txlist_free(struct tx_list * + static inline void ring_idx_inc(struct aca_ring *ring) + { + ring->idx = (ring->idx + 1) % ring->dnum; ++ ring->cnt += 1; + } + + static struct sk_buff *txin_skb_prepare(struct sk_buff *skb) +@@ -619,6 +623,8 @@ static int plat_txout_napi(struct napi_s + + cnt = txout_action(tcpriv, txout, budget); + ++ priv->napi_tx_stats[cnt] += 1; ++ + if (cnt < budget) { + if (napi_complete_done(napi, cnt)) + ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_TX); +@@ -653,6 +659,8 @@ static int plat_rxout_napi(struct napi_s + if (cnt) + rxin_action(tcpriv, rxin, DMA_PACKET_SZ, cnt); + ++ priv->napi_rx_stats[cnt] += 1; ++ + if (cnt < budget) { + if (napi_complete_done(napi, cnt)) + ep_dev->hw_ops->icu_en(ep_dev, ACA_HOSTIF_RX); +@@ -1092,6 +1100,56 @@ static int plat_soc_cfg_get(struct soc_c + return 0; + } + ++static struct proc_dir_entry *g_proc_entry; ++ ++static int proc_show(struct seq_file *m, void *p) ++{ ++ struct aca_ring *txin = &g_plat_priv->soc_rings.txin; ++ struct aca_ring *txout = &g_plat_priv->soc_rings.txout; ++ struct aca_ring *rxin = &g_plat_priv->soc_rings.rxin; ++ struct aca_ring *rxout = &g_plat_priv->soc_rings.rxout; ++ int i; ++ ++ seq_printf(m, "napi_tx_stats: "); ++ for (i = 0; i < sizeof(g_plat_priv->napi_tx_stats) / sizeof(g_plat_priv->napi_tx_stats[0]); i++) { ++ if (i == 0) { ++ seq_printf(m, "%llu", g_plat_priv->napi_tx_stats[i]); ++ } else { ++ seq_printf(m, ", %llu", g_plat_priv->napi_tx_stats[i]); ++ } ++ } ++ seq_printf(m, "\n"); ++ ++ seq_printf(m, "napi_rx_stats: "); ++ for (i = 0; i < sizeof(g_plat_priv->napi_rx_stats) / sizeof(g_plat_priv->napi_rx_stats[0]); i++) { ++ if (i == 0) { ++ seq_printf(m, "%llu", g_plat_priv->napi_rx_stats[i]); ++ } else { ++ seq_printf(m, ", %llu", g_plat_priv->napi_rx_stats[i]); ++ } ++ } ++ seq_printf(m, "\n"); ++ ++ seq_printf(m, "txin: %d/%u, %llu\n", txin->idx, txin->dnum, txin->cnt); ++ seq_printf(m, "txout: %d/%u, %llu\n", txout->idx, txout->dnum, txout->cnt); ++ seq_printf(m, "rxin: %d/%u, %llu\n", rxin->idx, rxin->dnum, rxin->cnt); ++ seq_printf(m, "rxout: %d/%u, %llu\n", rxout->idx, rxout->dnum, rxout->cnt); ++ ++ return 0; ++} ++ ++static int proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, proc_show, NULL); ++} ++ ++static struct proc_ops proc_operations = { ++ .proc_open = proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release ++}; ++ + static int plat_open(struct net_device *pdev, const char *dev_name, + struct napi_struct *napi_tx, struct napi_struct *napi_rx, + int id, int flag) +@@ -1099,6 +1157,8 @@ static int plat_open(struct net_device * + struct tc_priv *priv = g_plat_priv->tc_priv; + int i; + ++ g_proc_entry = proc_create("swplat", 0600, priv->proc_dir, &proc_operations); ++ + for (i = 0; i < EP_MAX_NUM && i < priv->ep_num; i++) { + disable_irq(priv->ep_dev[i].aca_rx_irq); + disable_irq(priv->ep_dev[i].aca_tx_irq); +@@ -1137,6 +1197,8 @@ static void plat_close(struct net_device + enable_irq(priv->ep_dev[i].aca_tx_irq); + } + ++ proc_remove(g_proc_entry); ++ + return; + } + From 2a0aa9eefadb3bad415eae84e023af70c06b020c Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Sat, 18 Dec 2021 11:59:47 +0100 Subject: [PATCH 11/21] ltq-ifxos: enable for ipq40xx This is required for the MEI CPE driver. Signed-off-by: Andre Heider --- package/kernel/lantiq/ltq-ifxos/Makefile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/package/kernel/lantiq/ltq-ifxos/Makefile b/package/kernel/lantiq/ltq-ifxos/Makefile index bc586faaf12..e8f41665dda 100644 --- a/package/kernel/lantiq/ltq-ifxos/Makefile +++ b/package/kernel/lantiq/ltq-ifxos/Makefile @@ -32,7 +32,7 @@ define KernelPackage/ltq-ifxos SUBMENU:=Libraries TITLE:=Lantiq OS abstraction library URL:=http://www.lantiq.com/ - DEPENDS:=@TARGET_lantiq + DEPENDS:=@(TARGET_lantiq||TARGET_ipq40xx) FILES:=$(PKG_BUILD_DIR)/src/drv_ifxos.ko AUTOLOAD:=$(call AutoLoad,10,drv_ifxos) endef @@ -44,13 +44,11 @@ CONFIGURE_ARGS += \ --enable-kernelincl="$(LINUX_DIR)/include" \ --with-kernel-module -ifdef CONFIG_TARGET_lantiq - define Build/InstallDev +define Build/InstallDev $(INSTALL_DIR) $(1)/usr/{lib,include/ifxos} $(CP) $(PKG_BUILD_DIR)/src/include/* $(1)/usr/include/ifxos mkdir -p $(1)/usr/lib $(CP) $(PKG_BUILD_DIR)/src/.libs/libifxos.a $(1)/usr/lib/libifxos.a - endef -endif +endef $(eval $(call KernelPackage,ltq-ifxos)) From bc442076f28937d5d752364be1727e765325cbac Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Wed, 21 Aug 2019 08:44:58 +0200 Subject: [PATCH 12/21] kernel: add new ltq-vdsl-vr11-mei driver This uses version 1.11.1 of the drv_mei_cpe package from the Intel UGW 8.5.2.10 for the VRX518. Signed-off-by: Martin Schiller [updated for kernel 5.10] Signed-off-by: Jan Hoffmann [update to 1.11.1, switch to tag tarball, update patches] Signed-off-by: Andre Heider [update for kernel 5.15] Signed-off-by: Jan Hoffmann Signed-off-by: Andre Heider --- .../kernel/lantiq/ltq-vdsl-vr11-mei/Makefile | 113 ++++++++++++++++++ .../patches/001-fix-compile.patch | 88 ++++++++++++++ .../patches/010-warnings.patch | 20 ++++ .../patches/020-not-leak-cflags.patch | 12 ++ .../patches/100-compat.patch | 10 ++ .../patches/101_no-date-time.patch | 13 ++ ...eset-g_tx_link_rate-on-showtime-exit.patch | 12 ++ .../patches/120-remove-debug-printk.patch | 10 ++ 8 files changed, 278 insertions(+) create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11-mei/Makefile create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/001-fix-compile.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/010-warnings.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/020-not-leak-cflags.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/100-compat.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/101_no-date-time.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/110-reset-g_tx_link_rate-on-showtime-exit.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/120-remove-debug-printk.patch diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/Makefile b/package/kernel/lantiq/ltq-vdsl-vr11-mei/Makefile new file mode 100644 index 00000000000..990471a219a --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/Makefile @@ -0,0 +1,113 @@ +# Copyright (C) 2012 OpenWrt.org +# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG. +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ltq-vdsl-vr11-mei +PKG_VERSION:=1.11.1 +PKG_RELEASE:=$(AUTORELEASE) +PKG_BASE_NAME:=dsl_cpe_mei + +UGW_VERSION=8.5.2.10 +UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION) + +PKG_SOURCE:=$(UGW_BASENAME).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/ +PKG_HASH:=337614473d50ed64de010adaed99a16103e08eea8fc67fe9d6caf155bea33d1d +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(UGW_BASENAME) +PKG_LICENSE:=GPL-2.0 BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE +PKG_EXTMOD_SUBDIRS:=src + +PKG_FIXUP:=autoreconf +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ltq-vdsl-vr11-mei + TITLE:=mei driver for vdsl + SECTION:=sys + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ipq40xx +kmod-ltq-ifxos +kmod-vrx518_tc + FILES:=$(PKG_BUILD_DIR)/src/drv_mei_cpe.ko + AUTOLOAD:=$(call AutoLoad,50,drv_mei_cpe) +endef + +define KernelPackage/ltq-vdsl-vr11-mei/description + Lantiq MEI CPE Kernel Module Driver +endef + + +define Package/ltq-vdsl-vr11-mei-test + SECTION:=net + CATEGORY:=Network + TITLE:=Lantiq mei driver test tool + URL:=http://www.lantiq.com/ + DEPENDS:=@TARGET_ipq40xx +kmod-ltq-vdsl-vr11-mei +endef + +define Package/ltq-vdsl-vr11-mei-test/description + Userland tool to directly control the mei driver, this is only needed + for test and development purposes. +endef + +MAKE_FLAGS += \ + $(KERNEL_MAKE_FLAGS) \ + SHELL="$(BASH)" + +# ltq-vdsl-app uses a header provided by the MEI driver which has some +# conditionals. +# Define the conditionals here to have the same view on both sides. If you +# change them, you need to change them for the ltq-vdsl-app as well +MEI_DRV_CFLAGS = \ + -DMEI_DRV_ATM_PTM_INTERFACE_ENABLE=1 \ + -DMEI_SUPPORT_DEBUG_STREAMS=1 \ + -DMEI_SUPPORT_OPTIMIZED_FW_DL=1 + +#MEI_DRV_CFLAGS+= \ +# -DMEI_SUPPORT_OPTIMIZED_FW_DL=0 \ +# -DIRQ_POLLING_FORCE=99 + +CONFIGURE_ARGS += \ + --enable-debug-logger-support=no +# --enable-debug-stream-support=no + +# This looks weird, but it's necessary to address the right device. +# (pdev->dev.parent instead of pdev->dev) +MEI_DRV_CFLAGS+= \ + -DMEI_TARGET_x86=1 + +CONFIGURE_ARGS += \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --enable-device=vr11 \ + --enable-debug \ + --enable-error_print \ + --enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos/" \ + --enable-ifxos-library="-L$(STAGING_DIR)/usr/lib" \ + --enable-add_drv_cflags="$(MEI_DRV_CFLAGS)" \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-drv_test_appl=yes \ + ARCH=$(LINUX_KARCH) + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/vdsl + $(CP) $(PKG_BUILD_DIR)/src/drv_mei_cpe_api_intern.h $(1)/usr/include/vdsl/ + $(CP) $(PKG_BUILD_DIR)/src/drv_mei_cpe_api_atm_ptm_intern.h $(1)/usr/include/vdsl/ + $(CP) $(PKG_BUILD_DIR)/src/drv_mei_cpe_interface.h $(1)/usr/include/vdsl + $(CP) $(PKG_BUILD_DIR)/src/drv_mei_cpe_config.h $(1)/usr/include/vdsl/ + $(CP) $(PKG_BUILD_DIR)/src/cmv_message_format.h $(1)/usr/include/vdsl/ +endef + +$(eval $(call KernelPackage,ltq-vdsl-vr11-mei)) + +define Package/ltq-vdsl-vr11-mei-test/install + $(INSTALL_DIR) $(1)/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mei_cpe_drv_test $(1)/bin +endef + +$(eval $(call BuildPackage,ltq-vdsl-vr11-mei-test)) diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/001-fix-compile.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/001-fix-compile.patch new file mode 100644 index 00000000000..ff46b1f0886 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/001-fix-compile.patch @@ -0,0 +1,88 @@ +--- a/src/drv_mei_cpe_linux.c ++++ b/src/drv_mei_cpe_linux.c +@@ -1534,7 +1534,7 @@ struct proc_entry { + char name[32]; + proc_rd_callback_t rd; + proc_wr_callback_t wr; +- struct file_operations ops; ++ struct proc_ops ops; + int entity; + }; + +@@ -2068,16 +2068,15 @@ static int mei_proc_single_open(struct i + static void mei_proc_entry_create(struct proc_dir_entry *parent_node, + struct proc_entry *proc_entry) + { +- memset(&proc_entry->ops, 0, sizeof(struct file_operations)); +- proc_entry->ops.owner = THIS_MODULE; ++ memset(&proc_entry->ops, 0, sizeof(struct proc_ops)); + +- proc_entry->ops.open = mei_proc_single_open; +- proc_entry->ops.release = single_release; ++ proc_entry->ops.proc_open = mei_proc_single_open; ++ proc_entry->ops.proc_release = single_release; + +- proc_entry->ops.read = seq_read; +- proc_entry->ops.llseek = seq_lseek; ++ proc_entry->ops.proc_read = seq_read; ++ proc_entry->ops.proc_lseek = seq_lseek; + if (proc_entry->wr) +- proc_entry->ops.write = proc_entry->wr; ++ proc_entry->ops.proc_write = proc_entry->wr; + + proc_create_data(proc_entry->name, + (S_IFREG | S_IRUGO), +--- a/src/drv_mei_cpe_linux.h ++++ b/src/drv_mei_cpe_linux.h +@@ -31,6 +31,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -122,7 +123,7 @@ typedef int (*MEI_RequestIrq_WrapLinux_t + /** + Function typedef for the Linux free_irq() + */ +-typedef void (*MEI_FreeIrq_WrapLinux_t)( unsigned int usedIrq, ++typedef const void *(*MEI_FreeIrq_WrapLinux_t)( unsigned int usedIrq, + void *usedDevId ); + + +--- a/src/drv_mei_cpe_linux_proc_config.c ++++ b/src/drv_mei_cpe_linux_proc_config.c +@@ -1277,13 +1277,12 @@ static int mei_proc_single_open(struct i + return single_open(file, mei_seq_single_show, PDE_DATA(inode)); + } + +-static struct file_operations proc_ops = { +- .owner = THIS_MODULE, +- .open = mei_proc_single_open, +- .release = single_release, +- .read = seq_read, +- .llseek = seq_lseek, +- .write = MEI_ProcWriteConfig ++static struct proc_ops proc_ops = { ++ .proc_open = mei_proc_single_open, ++ .proc_release = single_release, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = MEI_ProcWriteConfig + }; + + /** +--- a/src/mei_cpe_appl_osmap.h ++++ b/src/mei_cpe_appl_osmap.h +@@ -38,10 +38,6 @@ extern "C" + #include + #include + #include +- +-extern int snprintf (char *__restrict __s, size_t __maxlen, +- __const char *__restrict __format, ...) +- __THROW __attribute__ ((__format__ (__printf__, 3, 4))); + #endif + + /* ========================================================================== diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/010-warnings.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/010-warnings.patch new file mode 100644 index 00000000000..f6ee2f7f8bb --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/010-warnings.patch @@ -0,0 +1,20 @@ +--- a/src/drv_mei_cpe_dbg_driver.c ++++ b/src/drv_mei_cpe_dbg_driver.c +@@ -309,7 +309,7 @@ MEI_STATIC IFX_void_t MEI_DbgMsgDumpLogW + IFX_int32_t i; + unsigned short paylSize; + union {IFX_uint8_t d8[2]; IFX_uint16_t d16;} temp16; +- union {IFX_uint8_t d8[4]; IFX_uint16_t d32;} temp32; ++ union {IFX_uint8_t d8[4]; IFX_uint32_t d32;} temp32; + + MEI_DbgMsgDumpLogLabel(pCmvMsg, fctOpCode); + +@@ -368,7 +368,7 @@ MEI_STATIC IFX_void_t MEI_DbgMsgDumpTrcW + IFX_int32_t i; + unsigned short paylSize; + union {IFX_uint8_t d8[2]; IFX_uint16_t d16;} temp16; +- union {IFX_uint8_t d8[4]; IFX_uint16_t d32;} temp32; ++ union {IFX_uint8_t d8[4]; IFX_uint32_t d32;} temp32; + + MEI_DbgMsgDumpTraceLabel(pCmvMsg, fctOpCode); + diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/020-not-leak-cflags.patch new file mode 100644 index 00000000000..f6fb48ed6ea --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/020-not-leak-cflags.patch @@ -0,0 +1,12 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -213,8 +213,7 @@ drv_mei_cpe_common_cflags = $(AM_CFLAGS) + else + + drv_mei_cpe_common_cflags = \ +- $(AM_CFLAGS) -D__KERNEL__ -DLINUX -D__linux__ -DMODULE -DEXPORT_SYMTAB \ +- -pipe -Wall -Wimplicit -Wunused -Wuninitialized -Wstrict-aliasing -Wno-date-time ++ -D__KERNEL__ -DLINUX -D__linux__ -DMODULE -DEXPORT_SYMTAB + + endif + diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/100-compat.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/100-compat.patch new file mode 100644 index 00000000000..a2e42ccb03f --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/100-compat.patch @@ -0,0 +1,10 @@ +--- a/src/drv_mei_cpe_linux.c ++++ b/src/drv_mei_cpe_linux.c +@@ -4530,7 +4530,6 @@ module_exit (MEI_module_exit); + #ifdef MODULE + MODULE_AUTHOR("www.lantiq.com"); + MODULE_DESCRIPTION("MEI CPE Driver - www.lantiq.com"); +-MODULE_SUPPORTED_DEVICE("MEI CPE Interface"); + MODULE_LICENSE ("GPL"); + #endif /* #ifdef MODULE*/ + diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/101_no-date-time.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/101_no-date-time.patch new file mode 100644 index 00000000000..18918b9956c --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/101_no-date-time.patch @@ -0,0 +1,13 @@ +--- a/src/drv_mei_cpe_linux.c ++++ b/src/drv_mei_cpe_linux.c +@@ -1556,8 +1556,8 @@ static void MEI_GetVersionProc(struct se + } + + seq_printf(s, "%s" MEI_DRV_CRLF, &MEI_WHATVERSION[4]); +- seq_printf(s, "Compiled on %s, %s for Linux kernel %s (jiffies: %ld)" MEI_DRV_CRLF, +- __DATE__, __TIME__, UTS_RELEASE, jiffies); ++ seq_printf(s, "Compiled for Linux kernel %s (jiffies: %ld)" MEI_DRV_CRLF, ++ UTS_RELEASE, jiffies); + } + + /** diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/110-reset-g_tx_link_rate-on-showtime-exit.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/110-reset-g_tx_link_rate-on-showtime-exit.patch new file mode 100644 index 00000000000..f57b8f076fb --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/110-reset-g_tx_link_rate-on-showtime-exit.patch @@ -0,0 +1,12 @@ +--- a/src/drv_mei_cpe_api_atm_ptm_intern.c ++++ b/src/drv_mei_cpe_api_atm_ptm_intern.c +@@ -152,6 +152,9 @@ IFX_int32_t MEI_InternalXtmSwhowtimeExit + /* Get line number*/ + dslLineNum = pMeiDynCntrl->pMeiDev->meiDrvCntrl.dslLineNum; + ++ g_tx_link_rate[dslLineNum][0] = 0; ++ g_tx_link_rate[dslLineNum][1] = 0; ++ + #ifdef PPA_SUPPORTS_CALLBACKS + /* get NULL or function pointer */ + mei_showtime_exit = diff --git a/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/120-remove-debug-printk.patch b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/120-remove-debug-printk.patch new file mode 100644 index 00000000000..24db470c4ae --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11-mei/patches/120-remove-debug-printk.patch @@ -0,0 +1,10 @@ +--- a/src/drv_mei_cpe_mei_access_vrx.c ++++ b/src/drv_mei_cpe_mei_access_vrx.c +@@ -1691,7 +1691,6 @@ IFX_int32_t MEI_InterfaceDetect( + { + MEI_REG_ACCESS_ME_VERSION_SET(pMeiDrvCntrl, 0x00000000); + hwVers = MEI_REG_ACCESS_ME_VERSION_GET(pMeiDrvCntrl); +- printk ("hwVers=0x%08X\n", hwVers); + + if (MEI_DEVICE_CFG_IS_PLATFORM(e_MEI_DEV_PLATFORM_CONFIG_VR9)) + { From 1f7ec35077f2288e9512177546d7d275ce15955f Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Wed, 21 Aug 2019 08:55:25 +0200 Subject: [PATCH 13/21] kernel: add new ltq-vdsl-vr11 driver This uses version 4.23.1 of the drv_dsl_cpe_api package from the Intel UGW 8.5.2.10 for the VRX518. Signed-off-by: Martin Schiller [rebased and updated for kernel 5.10] Signed-off-by: Jan Hoffmann [update to 4.23.1, switch to tag tarball, update patches] Signed-off-by: Andre Heider [added fix for elapsed time and upstream MINEFTR] Signed-off-by: Jan Hoffmann Signed-off-by: Andre Heider --- package/kernel/lantiq/ltq-vdsl-vr11/Makefile | 80 ++++++++++++ .../patches/001-fix-compile.patch | 84 ++++++++++++ .../patches/020-not-leak-cflags.patch | 23 ++++ .../ltq-vdsl-vr11/patches/100-compat.patch | 18 +++ .../patches/200-fix-elapsed-time.patch | 122 ++++++++++++++++++ .../patches/210-fix-us-eftrmin.patch | 22 ++++ 6 files changed, 349 insertions(+) create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11/Makefile create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11/patches/001-fix-compile.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11/patches/020-not-leak-cflags.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11/patches/100-compat.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11/patches/200-fix-elapsed-time.patch create mode 100644 package/kernel/lantiq/ltq-vdsl-vr11/patches/210-fix-us-eftrmin.patch diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/Makefile b/package/kernel/lantiq/ltq-vdsl-vr11/Makefile new file mode 100644 index 00000000000..64db4662ee5 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/Makefile @@ -0,0 +1,80 @@ +# Copyright (C) 2012 OpenWrt.org +# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG. +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ltq-vdsl-vr11 +PKG_VERSION:=4.23.1 +PKG_RELEASE:=$(AUTORELEASE) +PKG_BASE_NAME:=dsl_cpe_api + +UGW_VERSION=8.5.2.10 +UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION) + +PKG_SOURCE:=$(UGW_BASENAME).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/ +PKG_HASH:=5e8bbab841d67dc16e329d9b3774f6db4189dd1d01f575d0e921ccf2c426dd9f +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(UGW_BASENAME) +PKG_LICENSE:=GPL-2.0 BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +# TODO this driver depends on the vrx518 dsl firmware, add this dependency if +# that ever gets a compatible license +define KernelPackage/ltq-vdsl-vr11 + TITLE:=vdsl driver + SECTION:=sys + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ipq40xx +kmod-ltq-vdsl-vr11-mei + FILES:=$(PKG_BUILD_DIR)/src/drv_dsl_cpe_api.ko + AUTOLOAD:=$(call AutoLoad,51,drv_dsl_cpe_api) +endef + +define Package/ltq-vdsl-vr11/description + This package contains the Lantiq DSL CPE API driver. + + Supported Devices: + - VRX500 Family +endef + +MAKE_FLAGS += \ + $(KERNEL_MAKE_FLAGS) \ + SHELL="$(BASH)" + +CONFIGURE_ARGS += \ + --enable-add-drv-cflags="" \ + --enable-add_ext_drv_cflags="-DDSL_DRV_ATM_PTM_INTERFACE_ENABLE=1" \ + --enable-debug-logger-support=no + +CONFIGURE_ARGS += --enable-kernel-include="$(LINUX_DIR)/include" \ + --enable-vrx \ + --enable-vrx-device=vr11 \ + --enable-ifxos \ + --enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos" \ + --enable-driver-include="-I$(STAGING_DIR)/usr/include/vdsl" \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-debug-prints=no \ + ARCH=$(LINUX_KARCH) + +CONFIGURE_ARGS += \ + --enable-model=full \ + --enable-dsl-ceoc=no +#CONFIGURE_ARGS += --enable-model=lite +#CONFIGURE_ARGS += --enable-model=footprint +#CONFIGURE_ARGS += --enable-model=typical +#CONFIGURE_ARGS += --enable-model=debug + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/drv_vdsl_cpe_api + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe*.h $(1)/usr/include/drv_vdsl_cpe_api/ +endef + +$(eval $(call KernelPackage,ltq-vdsl-vr11)) diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/001-fix-compile.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/001-fix-compile.patch new file mode 100644 index 00000000000..709c3766ded --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/001-fix-compile.patch @@ -0,0 +1,84 @@ +--- a/src/include/drv_dsl_cpe_os_linux.h ++++ b/src/include/drv_dsl_cpe_os_linux.h +@@ -36,6 +36,7 @@ + #endif + + #include ++#include + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +--- a/configure.in ++++ b/configure.in +@@ -422,7 +422,7 @@ AC_ARG_ENABLE(debug-prints, + AC_SUBST([DSL_DBG_MAX_LEVEL_SET],[no]) + + AC_SUBST([DSL_DBG_MAX_LEVEL_PRE],[n/a]) +- AC_SUBST([INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT],[no]) ++ AC_SUBST([INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT],[yes]) + ;; + no | none ) + AC_DEFINE(DSL_DEBUG_DISABLE,,[Disabled debug prints]) +@@ -433,7 +433,7 @@ AC_ARG_ENABLE(debug-prints, + AC_SUBST([DSL_DBG_MAX_LEVEL_SET],[no]) + + AC_SUBST([DSL_DBG_MAX_LEVEL_PRE],[n/a]) +- AC_SUBST([INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT],[yes]) ++ AC_SUBST([INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT],[no]) + ;; + prn | 0x1 ) + AC_SUBST([DSL_DEBUG_DISABLE],[no]) +--- a/src/common/drv_dsl_cpe_api.c ++++ b/src/common/drv_dsl_cpe_api.c +@@ -88,8 +88,12 @@ static DSL_uint32_t g_VRxPD_IOctlWhiteli + DSL_FIO_BAND_PLAN_STATUS_GET, + DSL_FIO_DBG_MODULE_LEVEL_GET, + DSL_FIO_DBG_MODULE_LEVEL_SET, ++#ifdef INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT ++#ifndef DSL_DEBUG_DISABLE + DSL_FIO_DBG_MODULE_DESTINATION_GET, + DSL_FIO_DBG_MODULE_DESTINATION_SET, ++#endif /* DSL_DEBUG_DISABLE*/ ++#endif /* INCLUDE_DSL_CPE_DEBUG_LOGGER_SUPPORT */ + DSL_FIO_OPERATOR_CONFIG_GET, + DSL_FIO_OPERATOR_CONFIG_SET, + /* Delimeter only. Keep it! */ +--- a/src/common/drv_dsl_cpe_os_linux.c ++++ b/src/common/drv_dsl_cpe_os_linux.c +@@ -625,7 +625,7 @@ DSL_void_t* DSL_DRV_VMalloc( + DSL_DRV_size_t nSize) + { + /* VRX500-BU: Better to use vmalloc or vzmalloc here?! */ +- return __vmalloc((unsigned long)nSize, GFP_KERNEL, PAGE_KERNEL); ++ return __vmalloc((unsigned long)nSize, GFP_KERNEL); + /* return vmalloc(nSize);*/ + } + +--- a/src/include/drv_dsl_cpe_debug.h ++++ b/src/include/drv_dsl_cpe_debug.h +@@ -99,6 +99,7 @@ DSL_void_t DSL_DRV_ErrorSet(DSL_void_t * + /** Terminate execution if assertion fails */ + #define DSL_ASSERT(exp) ((void)0) + ++ #define DSL_DEBUG_LIMIT(level, body) ((void)0) + #else + + #define DSL_DEBUG_SET_ERROR(code) DSL_DRV_ErrorSet(pContext, code); +--- a/src/pm/drv_dsl_cpe_pm_core.c ++++ b/src/pm/drv_dsl_cpe_pm_core.c +@@ -26,6 +26,7 @@ + #define DSL_DBG_BLOCK DSL_DBG_PM + + #ifdef __LINUX__ ++#ifndef DSL_DEBUG_DISABLE + #define DSL_PM_CORE_RATELIMIT_INTERVAL 20 * HZ /* for each 20 seconds */ + #define DSL_PM_CORE_RATELIMIT_BURST 1 /* 1 occurrence */ + /* struct ratelimit_state to be used in DSL_DEBUG_LIMIT */ +@@ -33,6 +34,7 @@ static DEFINE_RATELIMIT_STATE( + DSL_DBG_RATELIMIT_STRUCT_NAME(DSL_DBG_BLOCK), + DSL_PM_CORE_RATELIMIT_INTERVAL, + DSL_PM_CORE_RATELIMIT_BURST); ++#endif + #endif/* __LINUX__ */ + + DSL_boolean_t DSL_DRV_PM_IsPmReady( diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/020-not-leak-cflags.patch new file mode 100644 index 00000000000..21fc0be18e2 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/020-not-leak-cflags.patch @@ -0,0 +1,23 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -283,10 +283,7 @@ else + drv_dsl_cpe_api_common_mod_cflags = + endif + +-drv_dsl_cpe_api_common_cflags = -DLINUX -D__LINUX__ -D__KERNEL__ -DEXPORT_SYMTAB \ +- -pipe -Wall -Wformat -Wimplicit -Wunused -Wswitch -Wcomment -Winline \ +- -Wuninitialized -Wparentheses -Wreturn-type \ +- -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common ++drv_dsl_cpe_api_common_cflags = -DLINUX -D__LINUX__ -D__KERNEL__ -DEXPORT_SYMTAB + + if DSL_DBG_MAX_LEVEL_SET + drv_dsl_cpe_api_common_cflags += -DDSL_DBG_MAX_LEVEL=$(DSL_DBG_MAX_LEVEL_PRE) +@@ -296,7 +293,7 @@ endif + drv_dsl_cpe_api_target_cflags = $(ADD_DRV_CFLAGS) + + # compile cflags +-drv_dsl_cpe_api_compile_cflags = $(EXTRA_DRV_CFLAGS) ++drv_dsl_cpe_api_compile_cflags = + + if !KERNEL_2_6 + # the headerfile of linux kernels 2.6.x contain to much arithmetic diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/100-compat.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/100-compat.patch new file mode 100644 index 00000000000..eeda611d715 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/100-compat.patch @@ -0,0 +1,18 @@ +--- a/src/common/drv_dsl_cpe_os_linux.c ++++ b/src/common/drv_dsl_cpe_os_linux.c +@@ -1051,12 +1051,11 @@ DSL_int32_t DSL_DRV_ThreadShutdown( + + DSL_uint32_t DSL_DRV_SysTimeGet(DSL_uint32_t nOffset) + { +- struct timeval tv; ++ struct timespec64 now; + DSL_uint32_t nTime = 0; + +- memset(&tv, 0, sizeof(tv)); +- do_gettimeofday(&tv); +- nTime = (DSL_uint32_t)tv.tv_sec; ++ ktime_get_real_ts64(&now); ++ nTime = (DSL_uint32_t)now.tv_sec; + + if ( (nOffset == 0) || (nOffset > nTime) ) + { diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/200-fix-elapsed-time.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/200-fix-elapsed-time.patch new file mode 100644 index 00000000000..2734415d15c --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/200-fix-elapsed-time.patch @@ -0,0 +1,122 @@ +--- a/src/include/drv_dsl_cpe_pm_core.h ++++ b/src/include/drv_dsl_cpe_pm_core.h +@@ -1554,9 +1554,9 @@ typedef struct + DSL_boolean_t bShowtimeProcessingStart; + /** Showtime reached flag*/ + DSL_boolean_t bShowtimeInvTrigger; +- /** Current Showtime synchronization time to be used, (msec) */ ++ /** Current Showtime synchronization time to be used, (sec) */ + DSL_uint32_t nCurrShowtimeTime; +- /** Showtime synchronization time to be used, (msec) */ ++ /** Showtime synchronization time to be used, (sec) */ + DSL_uint32_t nElapsedShowtimeTime; + /** Actual Line state*/ + DSL_LineStateValue_t nLineState; +--- a/src/pm/drv_dsl_cpe_api_pm.c ++++ b/src/pm/drv_dsl_cpe_api_pm.c +@@ -1633,7 +1633,7 @@ DSL_Error_t DSL_DRV_PM_ChannelCountersTo + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pChCounters = DSL_DRV_PM_PTR_CHANNEL_COUNTERS_TOTAL(pCounters->nChannel,pCounters->nDirection); + +@@ -1693,7 +1693,7 @@ DSL_Error_t DSL_DRV_PM_ChannelCountersEx + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pChCounters = DSL_DRV_PM_PTR_CHANNEL_COUNTERS_TOTAL_EXT(pCounters->nChannel); + +@@ -2764,7 +2764,7 @@ DSL_Error_t DSL_DRV_PM_DataPathCountersT + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pDpCounters = DSL_DRV_PM_PTR_DATAPATH_COUNTERS_TOTAL(pCounters->nChannel,pCounters->nDirection); + +@@ -3678,7 +3678,7 @@ DSL_Error_t DSL_DRV_PM_DataPathFailureCo + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pDpCounters = DSL_DRV_PM_PTR_DATAPATH_FAILURE_COUNTERS_TOTAL(pCounters->nChannel,pCounters->nDirection); + +@@ -4536,7 +4536,7 @@ DSL_Error_t DSL_DRV_PM_LineSecCountersTo + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pLineCounters = DSL_DRV_PM_PTR_LINE_SEC_COUNTERS_TOTAL(pCounters->nDirection); + +@@ -5273,7 +5273,7 @@ DSL_Error_t DSL_DRV_PM_LineInitCountersT + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pLinitCounters = DSL_DRV_PM_PTR_LINE_INIT_COUNTERS_TOTAL(); + +@@ -5774,7 +5774,7 @@ DSL_Error_t DSL_DRV_PM_LineEventShowtime + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pLfCounters = DSL_DRV_PM_PTR_LINE_EVENT_SHOWTIME_COUNTERS_TOTAL(pCounters->nDirection); + +@@ -6302,7 +6302,7 @@ DSL_Error_t DSL_DRV_PM_ReTxCountersTotal + } + + /* Fill Total Counters elapsed time*/ +- pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime/DSL_PM_MSEC; ++ pCounters->total.nElapsedTime = DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime; + + pReTxCounters = DSL_DRV_PM_PTR_RETX_COUNTERS_TOTAL(pCounters->nDirection); + +--- a/src/pm/drv_dsl_cpe_pm_core.c ++++ b/src/pm/drv_dsl_cpe_pm_core.c +@@ -78,6 +78,7 @@ static DSL_Error_t DSL_DRV_PM_SyncTimeUp + { + DSL_Error_t nErrCode = DSL_SUCCESS; + DSL_uint32_t msecTimeFrame = DSL_PM_COUNTER_POLLING_CYCLE, ++ secTimeFrame = DSL_PM_COUNTER_POLLING_CYCLE/DSL_PM_MSEC, + nCurrMsTime = 0; + #ifdef INCLUDE_DSL_CPE_PM_HISTORY + DSL_uint32_t nCurrSysTime = 0, nPrevElapsedTime = 0; +@@ -117,10 +118,13 @@ static DSL_Error_t DSL_DRV_PM_SyncTimeUp + { + /* Get elapsed time [msec] since the last entry*/ + msecTimeFrame = nCurrMsTime - DSL_DRV_PM_CONTEXT(pContext)->nLastMsTimeCheck; ++ ++ /* Get elapsed time [sec] since the last entry*/ ++ secTimeFrame = (nCurrMsTime/DSL_PM_MSEC) - (DSL_DRV_PM_CONTEXT(pContext)->nLastMsTimeCheck/DSL_PM_MSEC); + } + + /* Get Total Elapsed Time Since the PM module startup*/ +- DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime += msecTimeFrame; ++ DSL_DRV_PM_CONTEXT(pContext)->nPmTotalElapsedTime += secTimeFrame; + + /* Set last time check to the current time*/ + DSL_DRV_PM_CONTEXT(pContext)->nLastMsTimeCheck = nCurrMsTime; +@@ -158,7 +162,7 @@ static DSL_Error_t DSL_DRV_PM_SyncTimeUp + else + { + /* Update current showtime elapsed time*/ +- DSL_DRV_PM_CONTEXT(pContext)->nCurrShowtimeTime += (msecTimeFrame/DSL_PM_MSEC); ++ DSL_DRV_PM_CONTEXT(pContext)->nCurrShowtimeTime += secTimeFrame; + DSL_DRV_PM_CONTEXT(pContext)->nElapsedShowtimeTime = + DSL_DRV_PM_CONTEXT(pContext)->nCurrShowtimeTime; + } diff --git a/package/kernel/lantiq/ltq-vdsl-vr11/patches/210-fix-us-eftrmin.patch b/package/kernel/lantiq/ltq-vdsl-vr11/patches/210-fix-us-eftrmin.patch new file mode 100644 index 00000000000..ad912605b68 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-vr11/patches/210-fix-us-eftrmin.patch @@ -0,0 +1,22 @@ +--- a/src/pm/drv_dsl_cpe_api_pm_vrx.c ++++ b/src/pm/drv_dsl_cpe_api_pm_vrx.c +@@ -1482,9 +1482,16 @@ DSL_Error_t DSL_DRV_PM_DEV_ReTxCountersG + /* ignore zero value*/ + if (nEftrMin) + { +- /* Fw Format: kBit/s */ +- /* API format: bit/s */ +- pCounters->nEftrMin = nEftrMin*1000; ++ if (nDirection == DSL_NEAR_END) ++ { ++ /* Fw Format: kBit/s */ ++ /* API format: bit/s */ ++ pCounters->nEftrMin = nEftrMin*1000; ++ } ++ else ++ { ++ pCounters->nEftrMin = nEftrMin; ++ } + } + } + else From 6361eb47cdcca974a38c00259008d9df7bb7e885 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Sat, 18 Dec 2021 12:01:03 +0100 Subject: [PATCH 14/21] ltq-dsl-base: enable for ipq40xx This is required by the DSL userland tool for hotplug support. Signed-off-by: Andre Heider --- package/network/utils/ltq-dsl-base/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/utils/ltq-dsl-base/Makefile b/package/network/utils/ltq-dsl-base/Makefile index 2ff069ca4dc..b51851f076e 100644 --- a/package/network/utils/ltq-dsl-base/Makefile +++ b/package/network/utils/ltq-dsl-base/Makefile @@ -17,7 +17,7 @@ define Package/ltq-dsl-base CATEGORY:=Network TITLE:=DSL related files for Intel/Lantiq DSL Chipsets URL:=http://openwrt.org/ - DEPENDS:=@TARGET_lantiq +jshn + DEPENDS:=@(TARGET_lantiq||TARGET_ipq40xx) +jshn endef define Package/ltq-dsl-base/description From 6e4c9738bed0ac99d048e71596b716d0819375b2 Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Wed, 21 Aug 2019 09:00:08 +0200 Subject: [PATCH 15/21] ltq-vdsl-vr11-app: add version 4.23.1 for vr11 targets This uses version 4.23.1 of the dsl_cpe_control package from the Intel UGW 8.5.2.10 for the VRX518. Signed-off-by: Martin Schiller [rebased] Signed-off-by: Jan Hoffmann [update to 4.23.1, added Jan's vector mac patch, fix warnings, switch to tag tarball] Signed-off-by: Andre Heider [add missing nLine in autoboot script, fix disconnect on termination, remove unneeded VR9 leftovers in init script] Signed-off-by: Jan Hoffmann Signed-off-by: Andre Heider --- .../network/config/ltq-vdsl-vr11-app/Makefile | 92 ++++++ .../ltq-vdsl-vr11-app/files/dsl_control | 264 ++++++++++++++++++ .../ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh | 18 ++ .../patches/100-compat.patch | 11 + .../patches/101-warnings.patch | 87 ++++++ .../patches/200-autoboot.patch | 85 ++++++ .../ltq-vdsl-vr11-app/patches/300-ubus.patch | 50 ++++ 7 files changed, 607 insertions(+) create mode 100644 package/network/config/ltq-vdsl-vr11-app/Makefile create mode 100644 package/network/config/ltq-vdsl-vr11-app/files/dsl_control create mode 100755 package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh create mode 100644 package/network/config/ltq-vdsl-vr11-app/patches/100-compat.patch create mode 100644 package/network/config/ltq-vdsl-vr11-app/patches/101-warnings.patch create mode 100644 package/network/config/ltq-vdsl-vr11-app/patches/200-autoboot.patch create mode 100644 package/network/config/ltq-vdsl-vr11-app/patches/300-ubus.patch diff --git a/package/network/config/ltq-vdsl-vr11-app/Makefile b/package/network/config/ltq-vdsl-vr11-app/Makefile new file mode 100644 index 00000000000..8639795458f --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/Makefile @@ -0,0 +1,92 @@ +# Copyright (C) 2010 OpenWrt.org +# Copyright (C) 2015-2016 Lantiq Beteiligungs GmbH & Co KG. +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ltq-vdsl-vr11-app +PKG_VERSION:=4.23.1 +PKG_RELEASE:=1 +PKG_BASE_NAME:=dsl_cpe_control + +UGW_VERSION=8.5.2.10 +UGW_BASENAME=$(PKG_BASE_NAME)-ugw_$(UGW_VERSION) + +PKG_SOURCE:=$(UGW_BASENAME).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.com/prpl-foundation/intel/$(PKG_BASE_NAME)/-/archive/ugw_$(UGW_VERSION)/ +PKG_HASH:=d21ec74ca30f7f3893a8aa26d2b74ec319652f6b112832efab6f1274c7e5d1fc +PKG_BUILD_DIR:=$(BUILD_DIR)/$(UGW_BASENAME) +PKG_LICENSE:=BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE + +PKG_BUILD_DEPENDS:=ltq-vdsl-vr11 + +PKG_FLAGS:=nonshared +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/ltq-vdsl-vr11-app + SECTION:=net + CATEGORY:=Network + TITLE:=Lantiq VDSL userland tool + URL:=http://www.lantiq.com/ + DEPENDS:=@TARGET_ipq40xx +libpthread +librt +libubox +libubus +ltq-dsl-base +kmod-ltq-vdsl-vr11 + PROVIDES:=ltq-dsl-app +endef + +define Package/ltq-vdsl-vr11-app/description + Userland tool needed to control Lantiq VDSL CPE +endef + +# ltq-vdsl-vr11-app uses a header provided by the MEI driver which has some +# conditionals. +# +# Define them here with the default values they would get in the MEI driver, +# have the same view on both sides. +# +# If you change them, you need to change them for the ltq-vdsl-vr11-app as well +VDSL_APP_CFLAGS = \ + -DMAX_CLI_PIPES=1 \ + -DMEI_SUPPORT_DEBUG_STREAMS=1 \ + -DMEI_SUPPORT_OPTIMIZED_FW_DL=1 + +CONFIGURE_ARGS += \ + --enable-debug-logger-support=no + +CONFIGURE_ARGS += \ + --enable-vrx \ + --enable-vrx-device=vr11 \ + --enable-driver-include="-I$(STAGING_DIR)/usr/include/drv_vdsl_cpe_api" \ + --enable-device-driver-include="-I$(STAGING_DIR)/usr/include/vdsl/" \ + --enable-ifxos \ + --enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos" \ + --enable-ifxos-library="-I$(STAGING_DIR)/usr/lib" \ + --enable-add-appl-cflags="$(VDSL_APP_CFLAGS)" \ + --enable-debug \ + --disable-dti + +CONFIGURE_ARGS += \ + --enable-model=full \ + --enable-dsl-ceoc=no +#CONFIGURE_ARGS += --enable-model=lite +#CONFIGURE_ARGS += --enable-model=footprint +#CONFIGURE_ARGS += --enable-model=typical +#CONFIGURE_ARGS += --enable-model=debug + +define Build/Prepare + $(call Build/Prepare/Default) + $(CP) ../ltq-vdsl-vr9-app/src/src/dsl_cpe_ubus.c $(PKG_BUILD_DIR)/src/ +endef + +define Package/ltq-vdsl-vr11-app/install + $(INSTALL_DIR) $(1)/etc/init.d $(1)/sbin $(1)/etc/hotplug.d/dsl + $(INSTALL_BIN) ./files/dsl_control $(1)/etc/init.d/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin/vdsl_cpe_control + $(INSTALL_BIN) ./files/dsl_cpe_pipe.sh $(1)/sbin/ +endef + +$(eval $(call BuildPackage,ltq-vdsl-vr11-app)) diff --git a/package/network/config/ltq-vdsl-vr11-app/files/dsl_control b/package/network/config/ltq-vdsl-vr11-app/files/dsl_control new file mode 100644 index 00000000000..d960a772618 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/files/dsl_control @@ -0,0 +1,264 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2012 OpenWrt.org + +START=97 +USE_PROCD=1 + +dslstat() { + ubus call dsl metrics +} + +extra_command "dslstat" "Get DSL status information" + +# +# ITU-T G.997.1 (06/2012) - Section 7.3.1.1.1 (xTU transmission system enabling (XTSE)) +# ITU-T G.997.1 Amendment 2 (04/2013) - Section 2.1 - (Vectoring mode enable (VECTORMODE_ENABLE)) +# +# G.992.1 Annex A +# G.992.2 Annex A +# G.992.3 Annex A / L-US1 / L_US-2 / M +# G.992.5 Annex A / M +# G.993.2 Annex A/B/C +# G.993.5 Annex A/B/C +xtse_xdsl_a="05_01_04_00_4C_01_04_07" + +# G.992.1 Annex B +# G.992.3 Annex B +# G.992.5 Annex B +# G.993.2 Annex A/B/C +# G.993.5 Annex A/B/C +xtse_xdsl_b="10_00_10_00_00_04_00_07" + +# G.992.1 Annex B +# G.992.3 Annex B +# G.992.3 Annex J +# G.992.5 Annex B +# G.992.5 Annex J +# G.993.2 Annex A/B/C +# G.993.5 Annex A/B/C +xtse_xdsl_j="10_00_10_40_00_04_01_07" + +# G.992.1 Annex B +xtse_xdsl_bdmt="10_00_00_00_00_00_00_00" + +# G.992.3 Annex B +xtse_xdsl_b2="00_00_10_00_00_00_00_00" + +# G.992.5 Annex B +xtse_xdsl_b2p="00_00_00_00_00_04_00_00" + +# ANSI T1.413 +xtse_xdsl_at1="01_00_00_00_00_00_00_00" + +# G.992.2 Annex A +xtse_xdsl_alite="00_01_00_00_00_00_00_00" + +# G.992.1 Annex A +xtse_xdsl_admt="04_00_00_00_00_00_00_00" + +# G.992.3 Annex A +xtse_xdsl_a2="00_00_04_00_00_00_00_00" + +# G.992.5 Annex A +xtse_xdsl_a2p="00_00_00_00_00_01_00_00" + +# G.992.3 Annex L +xtse_xdsl_l="00_00_00_00_0C_00_00_00" + +# G.992.3 Annex M +# G.992.5 Annex M +xtse_xdsl_m="00_00_00_00_40_00_04_00" + +# G.992.3 Annex M +xtse_xdsl_m2="00_00_00_00_40_00_00_00" + +# G.992.5 Annex M +xtse_xdsl_m2p="00_00_00_00_00_00_04_00" + +# +# ITU-T G.994.1 (06/2012) - Table 2 (Mandatory carrier sets) +# + +# A43 +tone_adsl_a="0x142" # A43C + J43 + A43 +tone_vdsl_a="0x142" # A43C + J43 + A43 + +# A43 + V43 +tone_adsl_av="0x142" # A43C + J43 + A43 +tone_vdsl_av="0x146" # A43C + J43 + A43 + V43 + +# B43 +tone_adsl_b="0x81" # B43 + B43c +tone_vdsl_b="0x1" # B43 + +# B43 + V43 +tone_adsl_bv="0x81" # B43 + B43c +tone_vdsl_bv="0x5" # B43 + V43 + +# create DSL autoboot script. Used for SNR margin tweak and to set MAC address for vectoring error reports +autoboot_script() { + echo "[WaitForConfiguration]={ +locs nLine=0 0 $1 +dsmmcs nLine=0 $2 +} + +[WaitForLinkActivate]={ +} + +[WaitForRestart]={ +} + +[Common]={ +}" > /tmp/dsl.scr +} + +lowlevel_cfg() { + echo "# VRX Low Level Configuration File +# +# Parameters must be separated by tabs or spaces. +# Empty lines and comments will be ignored. +# + +# nFilter +# +# NA = -1 +# OFF = 0 +# ISDN = 1 +# POTS = 2 +# POTS_2 = 3 +# POTS_3 = 4 +# +# (dec) + -1 + +# nHsToneGroupMode nHsToneGroup_A nHsToneGroup_V nHsToneGroup_AV +# +# NA = -1 NA = -1 see see +# AUTO = 0 VDSL2_B43 = 0x0001 nHsToneGroup_A nHsToneGroup_A +# MANUAL = 1 VDSL2_A43 = 0x0002 +# VDSL2_V43 = 0x0004 +# VDSL1_V43P = 0x0008 +# VDSL1_V43I = 0x0010 +# ADSL1_C43 = 0x0020 +# ADSL2_J43 = 0x0040 +# ADSL2_B43C = 0x0080 +# ADSL2_A43C = 0x0100 +# +# (dec) (hex) (hex) (hex) + 1 $1 $2 0x0 + +# nBaseAddr nIrqNum +# +# (hex) (dec) + 0x1e116000 63 + +# nUtopiaPhyAdr nUtopiaBusWidth nPosPhyParity +# default(16b) = 0 NA = -1 +# 8-bit = 1 ODD = 0 +# 16-bit = 2 +# +# +# (hex) (dec) (dec) + 0xFF 0 0 + +# bNtrEnable +# +# (dec) + 0" > /tmp/lowlevel.cfg +} + +get_macaddr() { + local name + config_get name $1 name + [ "$name" = "dsl0" ] && config_get $2 $1 macaddr +} + +service_triggers() { + procd_add_reload_trigger network +} + +start_service() { + local annex + local firmware + local tone + local tone_adsl + local tone_vdsl + local xtse + local xfer_mode + local line_mode + local tc_layer + local mode + local lowlevel + local snr + local macaddr + + config_load network + config_get tone dsl tone + config_get annex dsl annex + config_get firmware dsl firmware + config_get xfer_mode dsl xfer_mode + config_get line_mode dsl line_mode + config_get snr dsl ds_snr_offset + config_foreach get_macaddr device macaddr + + eval "xtse=\"\${xtse_xdsl_$annex}\"" + + case "${xfer_mode}" in + atm) + tc_layer="-T1:0x1:0x1_1:0x1:0x1" + ;; + ptm) + tc_layer="-T2:0x1:0x1_2:0x1:0x1" + ;; + esac + + case "${line_mode}" in + adsl) + mode="-M1" + + # mask out VDSL bits when ADSL is requested + xtse="${xtse%_*}_00" + ;; + vdsl) + mode="-M2" + + # mask out ADSL bits when VDSL is requested + xtse="00_00_00_00_00_00_00_${xtse##*_}" + ;; + esac + + [ -z "${firmware}" ] && firmware=/lib/firmware/vdsl.bin + [ -f "${firmware}" ] || { + echo failed to find $firmware + return 1 + } + + eval "tone_adsl=\"\${tone_adsl_$tone}\"" + eval "tone_vdsl=\"\${tone_vdsl_$tone}\"" + [ -n "${tone_adsl}" ] && [ -n "${tone_vdsl}" ] && { + lowlevel_cfg "${tone_adsl}" "${tone_vdsl}" + lowlevel="-l /tmp/lowlevel.cfg" + } + + [ -z "${snr}" ] && snr=0 + [ -z "${macaddr}" ] && macaddr="00:00:00:00:00:00" + autoboot_script "$snr" "$macaddr" + autoboot="-a /tmp/dsl.scr -A /tmp/dsl.scr" + + procd_open_instance + procd_set_param command /sbin/vdsl_cpe_control \ + -i$xtse \ + -n /sbin/dsl_notify.sh \ + -f ${firmware} \ + $lowlevel \ + ${mode} \ + ${tc_layer} \ + $autoboot + procd_close_instance +} + +stop_service() { + DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \ + DSL_INTERFACE_STATUS="DOWN" \ + /sbin/dsl_notify.sh +} diff --git a/package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh b/package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh new file mode 100755 index 00000000000..9002b7b3164 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/files/dsl_cpe_pipe.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +pipe_no=0 + +# use specified pipe no +case "$1" in +0|1|2) +pipe_no=$1; shift; ;; +esac + + +#echo "Call dsl_pipe with $*" +lock /var/lock/dsl_pipe +echo $* > /tmp/pipe/dsl_cpe${pipe_no}_cmd +result=$(cat /tmp/pipe/dsl_cpe${pipe_no}_ack) +lock -u /var/lock/dsl_pipe + +echo "$result" diff --git a/package/network/config/ltq-vdsl-vr11-app/patches/100-compat.patch b/package/network/config/ltq-vdsl-vr11-app/patches/100-compat.patch new file mode 100644 index 00000000000..6bc359c3cc9 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/patches/100-compat.patch @@ -0,0 +1,11 @@ +--- a/src/dsl_cpe_init_cfg.c ++++ b/src/dsl_cpe_init_cfg.c +@@ -38,7 +38,7 @@ DSL_InitData_t gInitCfgData = + DSL_DEV_HS_TONE_GROUP_CLEANED, \ + DSL_DEV_HS_TONE_GROUP_CLEANED, \ + DSL_DEV_HS_TONE_GROUP_CLEANED, \ +- 0x1E116000, 0x37, -1), ++ 0x1E116000, 0x3f, -1), + DSL_CPE_SIC_SET(DSL_TC_ATM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII, \ + DSL_TC_EFM, DSL_EMF_TC_CLEANED, DSL_EMF_TC_CLEANED, DSL_SYSTEMIF_MII), + DSL_CPE_MAC_CFG_SET(DSL_EFM_SPEED_100, DSL_EFM_DUPLEX_FULL, DSL_EFM_FLOWCTRL_ON, DSL_EFM_AUTONEG_OFF, \ diff --git a/package/network/config/ltq-vdsl-vr11-app/patches/101-warnings.patch b/package/network/config/ltq-vdsl-vr11-app/patches/101-warnings.patch new file mode 100644 index 00000000000..0c02bb17b75 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/patches/101-warnings.patch @@ -0,0 +1,87 @@ +--- a/src/dsl_cpe_control.h ++++ b/src/dsl_cpe_control.h +@@ -13,6 +13,8 @@ + #ifndef _DSL_CPE_CONTROL_H + #define _DSL_CPE_CONTROL_H + ++#include ++ + /** \defgroup DSL_CPE_CONTROL Lantiq DSL CPE API Control Application + Lists the entire modules to the DSL CPE_API Control Application. + @{ */ +--- a/src/dsl_cpe_safec_wrapper.h ++++ b/src/dsl_cpe_safec_wrapper.h +@@ -23,7 +23,7 @@ + #define cpe_control_vsnprintf_s vsnprintf_s + + /* snprintf_s symbol is not exported in SafeC lib */ +-static int cpe_control_snprintf_s(char *dest, ++static inline int cpe_control_snprintf_s(char *dest, + size_t dmax, + const char *fmt, + ...) +@@ -40,7 +40,7 @@ static int cpe_control_snprintf_s(char * + + #else + +-#warning "Safe C library is not available!" ++//#warning "Safe C library is not available!" + + #include /* size_t */ + #include /* va_list */ +@@ -55,7 +55,7 @@ static __inline__ size_t safec_wrapper_m + #define cpe_control_memset_s(dest, destsz, src, srcsz) memset(dest, src, safec_wrapper_min(destsz,srcsz)) + #define cpe_control_strncpy_s(dest, destsz, src, srcsz) strncpy(dest, src, safec_wrapper_min(destsz,srcsz)) + +-static size_t cpe_control_strnlen_s(const char *str, ++static inline size_t cpe_control_strnlen_s(const char *str, + size_t smax) + { + /* preconditions */ +@@ -74,7 +74,7 @@ static size_t cpe_control_strnlen_s(cons + return size; + } + +-static char *cpe_control_strtok_s(char *dest, ++static inline char *cpe_control_strtok_s(char *dest, + size_t *dmax, + const char *delim, + char **ptr) +@@ -123,7 +123,7 @@ static char *cpe_control_strtok_s(char * + return pTmp; + } + +-static int cpe_control_pipe_strcat_s(char *dest, ++static inline int cpe_control_pipe_strcat_s(char *dest, + size_t destsz, + char *src) + { +@@ -157,7 +157,7 @@ static int cpe_control_pipe_strcat_s(cha + return 0; + } + +-static int cpe_control_snprintf_s(char *dest, ++static inline int cpe_control_snprintf_s(char *dest, + size_t dmax, + const char *fmt, + ...) +@@ -181,7 +181,7 @@ static int cpe_control_snprintf_s(char * + return retVal; + } + +-static int cpe_control_vsnprintf_s(char *dest, ++static inline int cpe_control_vsnprintf_s(char *dest, + size_t dmax, + const char *fmt, + va_list vlist) +--- a/tools/pipe/dsl_cpe_safec_wrapper.h ++++ b/tools/pipe/dsl_cpe_safec_wrapper.h +@@ -27,7 +27,7 @@ + + #else + +-#warning "Safe C library is not available!" ++//#warning "Safe C library is not available!" + + #include /* size_t */ + static __inline__ size_t safec_wrapper_min(size_t a, size_t b) diff --git a/package/network/config/ltq-vdsl-vr11-app/patches/200-autoboot.patch b/package/network/config/ltq-vdsl-vr11-app/patches/200-autoboot.patch new file mode 100644 index 00000000000..c3e9b966204 --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/patches/200-autoboot.patch @@ -0,0 +1,85 @@ +This enables automatic connection after the control daemon is started, +and also changes the way the connection is stopped on termination. + +Using the autoboot restart command is necessary because the stop command +would stop the autoboot thread, and the driver offers no working way to +start it again later, short of unloading and reloading the module. + +--- a/src/dsl_cpe_init_cfg.c ++++ b/src/dsl_cpe_init_cfg.c +@@ -27,7 +27,7 @@ DSL_InitData_t gInitCfgData = + DSL_CPE_FW2_SET(DSL_NULL, 0x0), + DSL_CPE_XTU_SET(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7), + DSL_CPE_LINE_INV_NE_SET(DSL_NULL), +- DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_STOP), ++ DSL_CPE_AUTOBOOT_CTRL_SET(DSL_AUTOBOOT_CTRL_START), + DSL_CPE_AUTOBOOT_CFG_SET(DSL_FALSE, DSL_FALSE, DSL_FALSE), + DSL_CPE_TEST_MODE_CTRL_SET(DSL_TESTMODE_DISABLE), + DSL_CPE_LINE_ACTIVATE_CTRL_SET(DSL_G997_INHIBIT_LDSF, DSL_G997_INHIBIT_ACSF, DSL_G997_NORMAL_STARTUP), +--- a/src/dsl_cpe_control.c ++++ b/src/dsl_cpe_control.c +@@ -7338,6 +7338,7 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi + { + DSL_Error_t nRet = DSL_SUCCESS; + DSL_int_t nDevice = 0; ++ DSL_AutobootConfig_t sAutobootCfg; + DSL_AutobootControl_t sAutobootCtl; + DSL_CPE_Control_Context_t *pCtrlCtx = DSL_NULL; + +@@ -7349,8 +7350,32 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi + + for (nDevice = 0; nDevice < DSL_CPE_DSL_ENTITIES; ++nDevice) + { ++ g_bWaitBeforeConfigWrite[nDevice] = DSL_TRUE; ++ g_bWaitBeforeLinkActivation[nDevice] = DSL_TRUE; ++ g_bWaitBeforeRestart[nDevice] = DSL_TRUE; ++ ++ g_bAutoContinueWaitBeforeConfigWrite[nDevice] = DSL_FALSE; ++ g_bAutoContinueWaitBeforeLinkActivation[nDevice] = DSL_FALSE; ++ g_bAutoContinueWaitBeforeRestart[nDevice] = DSL_FALSE; ++ ++ memset(&sAutobootCfg, 0x0, sizeof(DSL_AutobootConfig_t)); ++ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeConfigWrite = DSL_TRUE; ++ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeLinkActivation = DSL_TRUE; ++ sAutobootCfg.data.nStateMachineOptions.bWaitBeforeRestart = DSL_TRUE; ++ ++ nRet = (DSL_Error_t)DSL_CPE_Ioctl( ++ DSL_CPE_GetGlobalContext()->fd[nDevice], ++ DSL_FIO_AUTOBOOT_CONFIG_SET, (DSL_int_t)&sAutobootCfg); ++ ++ if (nRet < DSL_SUCCESS) ++ { ++ DSL_CCA_DEBUG(DSL_CCA_DBG_ERR, (DSL_CPE_PREFIX ++ "Autoboot configuration for device (%d) failed!, nRet = %d!" ++ DSL_CPE_CRLF, nDevice, sAutobootCtl.accessCtl.nReturn)); ++ } ++ + memset(&sAutobootCtl, 0, sizeof(DSL_AutobootControl_t)); +- sAutobootCtl.data.nCommand = DSL_AUTOBOOT_CTRL_STOP; ++ sAutobootCtl.data.nCommand = DSL_AUTOBOOT_CTRL_RESTART; + + nRet = (DSL_Error_t)DSL_CPE_Ioctl( + DSL_CPE_GetGlobalContext()->fd[nDevice], +@@ -7359,13 +7384,13 @@ DSL_CPE_STATIC DSL_void_t DSL_CPE_Termi + if (nRet < DSL_SUCCESS) + { + DSL_CCA_DEBUG(DSL_CCA_DBG_ERR, (DSL_CPE_PREFIX +- "Autoboot stop for device (%d) failed!, nRet = %d!" ++ "Autoboot restart for device (%d) failed!, nRet = %d!" + DSL_CPE_CRLF, nDevice, sAutobootCtl.accessCtl.nReturn)); + } + } + + DSL_CCA_DEBUG(DSL_CCA_DBG_MSG, (DSL_CPE_PREFIX +- "Autoboot stop executed" DSL_CPE_CRLF)); ++ "Autoboot restart executed" DSL_CPE_CRLF)); + + DSL_CPE_DaemonExit(); + +@@ -8798,4 +8823,4 @@ DSL_CPE_STATIC DSL_Error_t DSL_CPE_Firmw + pDecimal)); + + return nErrCode; +-} +\ No newline at end of file ++} diff --git a/package/network/config/ltq-vdsl-vr11-app/patches/300-ubus.patch b/package/network/config/ltq-vdsl-vr11-app/patches/300-ubus.patch new file mode 100644 index 00000000000..fc0dd70bc1b --- /dev/null +++ b/package/network/config/ltq-vdsl-vr11-app/patches/300-ubus.patch @@ -0,0 +1,50 @@ +--- a/src/dsl_cpe_control.c ++++ b/src/dsl_cpe_control.c +@@ -221,6 +221,9 @@ extern DSL_Error_t DSL_CPE_Pipe_StaticRe + #endif /* INCLUDE_DSL_RESOURCE_STATISTICS*/ + #endif + ++extern void ubus_init(); ++extern void ubus_deinit(); ++ + DSL_char_t *g_sFirmwareName1 = DSL_NULL; + DSL_FirmwareFeatures_t g_nFwFeatures1 = {DSL_FW_XDSLMODE_CLEANED, DSL_FW_XDSLFEATURE_CLEANED, + DSL_FW_XDSLFEATURE_CLEANED}; +@@ -7831,6 +7834,8 @@ DSL_int_t dsl_cpe_daemon ( + #endif /* defined(INCLUDE_DSL_JSON_PARSING) && (INCLUDE_DSL_JSON_PARSING == 1) */ + #endif /* RTEMS*/ + ++ ubus_init(); ++ + /* Open DSL_CPE_MAX_DSL_ENTITIES devices*/ + for (nDevice = 0; nDevice < DSL_CPE_DSL_ENTITIES; nDevice++) + { +@@ -8367,6 +8372,7 @@ DSL_int_t dsl_cpe_daemon ( + #endif /* INCLUDE_DSL_CPE_CLI_SUPPORT */ + + DSL_CPE_CONTROL_EXIT: ++ ubus_deinit(); + + if (INCLUDE_DSL_BONDING) + { +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -17,7 +17,7 @@ else + dsl_cpe_control_common_ldflags = + endif + +-dsl_cpe_control_LDADD = -lpthread -lrt ++dsl_cpe_control_LDADD = -lpthread -lrt -lubox -lubus + + if INCLUDE_DSL_CPE_DTI_SUPPORT + dsl_cpe_control_LDADD += -ldti_agent +@@ -118,7 +118,8 @@ dsl_cpe_control_SOURCES = \ + dsl_cpe_control.c \ + dsl_cpe_init_cfg.c \ + dsl_cpe_linux.c \ +- dsl_cpe_debug.c ++ dsl_cpe_debug.c \ ++ dsl_cpe_ubus.c + + dsl_cpe_control_SOURCES += \ + $(dsl_cpe_control_dti_sources) From bc205a34a48d2455a011cd65fbad7430a02ff8e4 Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Wed, 21 Aug 2019 08:39:30 +0200 Subject: [PATCH 16/21] ipq40xx: fritzbox-7530.dts: increase dma coherent pool size This is needed by the mei driver to be able to download the firmware. Signed-off-by: Martin Schiller Signed-off-by: Andre Heider --- .../files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts index a0ceb299b49..71166231a90 100644 --- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts +++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts @@ -9,6 +9,10 @@ model = "AVM FRITZ!Box 7530"; compatible = "avm,fritzbox-7530"; + chosen { + bootargs-append = " coherent_pool=4M"; + }; + aliases { led-boot = &power_green; led-failsafe = &info_red; From 539b52068a079801fe0955f7cf5f39e536a08803 Mon Sep 17 00:00:00 2001 From: Martin Schiller Date: Wed, 21 Aug 2019 09:10:46 +0200 Subject: [PATCH 17/21] ipq40xx: add DSL support for FritzBox 7530 Set up MAC, LED, settings and default packages for DSL usage, similar to the lantiq target. Due to licensing uncertainty, we do not include the firmware files for the DSL drivers. To have a working DSL setup, follow the instructions below. Download the firmware files locally: mkdir -p files/lib/firmware/09a9 wget -P files/lib/firmware/09a9 https://gitlab.com/prpl-foundation/intel/vrx518_aca_fw/-/raw/ugw-8.5.2/platform/xrx500/aca_fw.bin wget -P files/lib/firmware https://gitlab.com/prpl-foundation/intel/vrx518_ppe_fw/-/raw/ugw_8.5.2.10/platform/xrx500/ppe_fw.bin wget -P files/lib/firmware https://gitlab.com/prpl-foundation/intel/dsl_vr11_firmware_xdsl/-/raw/ugw-8.5.2/xcpe_8D1507_8D0901.bin ln -s xcpe_8D1507_8D0901.bin files/lib/firmware/vdsl.bin For people building their own images: Run the above commands in the root of your local OpenWrt clone, and the firmware files will be part of the resulting images. For people downloading images: Copy the firmware files onto the router once it's booted up: scp -O -r files/lib/firmware root@fritz:/lib Reboot the device afterwards. Signed-off-by: Martin Schiller [cleaned up] Signed-off-by: Andre Heider [set up LED] Signed-off-by: Jan Hoffmann Signed-off-by: Andre Heider --- .../ipq40xx/base-files/etc/board.d/01_leds | 9 ++++--- .../ipq40xx/base-files/etc/board.d/02_network | 25 +++++++++++++++++++ .../boot/dts/qcom-ipq4019-fritzbox-7530.dts | 4 +-- target/linux/ipq40xx/image/generic.mk | 2 +- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/target/linux/ipq40xx/base-files/etc/board.d/01_leds b/target/linux/ipq40xx/base-files/etc/board.d/01_leds index 2bcbd954824..3ba130cc909 100644 --- a/target/linux/ipq40xx/base-files/etc/board.d/01_leds +++ b/target/linux/ipq40xx/base-files/etc/board.d/01_leds @@ -28,9 +28,8 @@ avm,fritzbox-4040) ucidef_set_led_netdev "wan" "WAN" "green:wan" "wan" ucidef_set_led_switch "lan" "LAN" "green:lan" "switch0" "0x1e" ;; -avm,fritzbox-7530 |\ -glinet,gl-b1300 |\ -mikrotik,lhgg-60ad) +avm,fritzbox-7530) + ucidef_set_led_netdev "dsl" "DSL" "green:info" "dsl0" ucidef_set_led_wlan "wlan" "WLAN" "green:wlan" "phy0tpt" ;; edgecore,oap100) @@ -56,6 +55,10 @@ engenius,ens620ext) glinet,gl-ap1300) ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth1" ;; +glinet,gl-b1300 |\ +mikrotik,lhgg-60ad) + ucidef_set_led_wlan "wlan" "WLAN" "green:wlan" "phy0tpt" + ;; mikrotik,cap-ac) ucidef_set_led_default "power" "POWER" "blue:power" "1" ucidef_set_led_default "user" "USER" "green:user" "0" diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network index ced26b9dd3f..7d4806b6053 100644 --- a/target/linux/ipq40xx/base-files/etc/board.d/02_network +++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network @@ -98,6 +98,26 @@ ipq40xx_setup_interfaces() esac } +ipq40xx_setup_dsl() +{ + local board="$1" + local annex="j" + local tone="b" + local xfer_mode="" + + case "$board" in + avm,fritzbox-7530) + ;; + *) + return 0 + ;; + esac + + ucidef_add_atm_bridge "1" "32" "llc" "bridged" "dsl" + ucidef_add_vdsl_modem "$annex" "$tone" "$xfer_mode" + ucidef_set_interface_wan "dsl0" "pppoe" +} + ipq40xx_setup_macs() { local board="$1" @@ -117,6 +137,10 @@ ipq40xx_setup_macs() lan_mac=$(mtd_get_mac_binary_ubi Factory 0x5006) label_mac=$wan_mac ;; + avm,fritzbox-7530) + local tffsdev=$(find_mtd_chardev "nand-tffs") + wan_mac=$(/usr/bin/fritz_tffs_nand -b -d $tffsdev -n macdsl) + ;; cilab,meshpoint-one) label_mac=$(mtd_get_mac_binary "ART" 0x1006) ;; @@ -185,6 +209,7 @@ ipq40xx_setup_macs() board_config_update board=$(board_name) ipq40xx_setup_interfaces $board +ipq40xx_setup_dsl $board ipq40xx_setup_macs $board board_config_flush diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts index 71166231a90..336da52f272 100644 --- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts +++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts @@ -17,7 +17,7 @@ led-boot = &power_green; led-failsafe = &info_red; led-running = &power_green; - led-upgrade = &info_green; + led-upgrade = &info_red; }; soc { @@ -96,7 +96,7 @@ gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; }; - info_green: info { + info { label = "green:info"; gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; }; diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk index dcf0cb20aa2..deec544f658 100644 --- a/target/linux/ipq40xx/image/generic.mk +++ b/target/linux/ipq40xx/image/generic.mk @@ -274,7 +274,7 @@ define Device/avm_fritzbox-7530 DEVICE_ALT0_VENDOR := AVM DEVICE_ALT0_MODEL := FRITZ!Box 7520 SOC := qcom-ipq4019 - DEVICE_PACKAGES := fritz-caldata fritz-tffs-nand + DEVICE_PACKAGES := fritz-caldata fritz-tffs-nand ltq-vdsl-vr11-app endef TARGET_DEVICES += avm_fritzbox-7530 From 8b12966d20bf10316752b3678d3999f83e564c60 Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Mon, 28 Nov 2022 16:01:26 -0800 Subject: [PATCH 18/21] tools/lz4: add `lz4` binaries same as `packages/liblz4` modified to be a HOST/tools type build with unified liblz4 (this is also the dev package for liblz4) the image initramfs generator offers the LZ4 option but there was no executable to support it actually working Signed-off-by: Tony Butler --- tools/Makefile | 4 ++ tools/lz4/Makefile | 49 +++++++++++++ ...01-add-make-ENABLE_DOCS-configurable.patch | 60 ++++++++++++++++ ...makefile-install-links-from-same-dir.patch | 71 +++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100644 tools/lz4/Makefile create mode 100644 tools/lz4/patches/001-add-make-ENABLE_DOCS-configurable.patch create mode 100644 tools/lz4/patches/002-makefile-install-links-from-same-dir.patch diff --git a/tools/Makefile b/tools/Makefile index c7c7d007563..46283e8d814 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -20,6 +20,9 @@ endif ifneq ($(CONFIG_SDK)$(CONFIG_PACKAGE_kmod-b43)$(CONFIG_BRCMSMAC_USE_FW_FROM_WL),) BUILD_B43_TOOLS = y endif +ifneq ($(CONFIG_SDK)$(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),) + BUILD_LZ4_TOOLS = y +endif tools-y += autoconf tools-y += autoconf-archive @@ -61,6 +64,7 @@ tools-y += zlib tools-y += zstd tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_B43_TOOLS),y) += b43-tools tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_ISL),y) += isl +tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_LZ4_TOOLS),y) += lz4 tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_TOOLCHAIN),y) += gmp mpc mpfr tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(CONFIG_TARGET_apm821xx)$(CONFIG_TARGET_gemini),y) += genext2fs tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(CONFIG_TARGET_ath79),y) += lzma-old squashfs diff --git a/tools/lz4/Makefile b/tools/lz4/Makefile new file mode 100644 index 00000000000..c5d4f6f16b2 --- /dev/null +++ b/tools/lz4/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2022 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lz4 +PKG_VERSION:=1.9.4 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/lz4/lz4/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=0b0e3aa07c8c063ddf40b082bdf7e37a1562bda40a0ff5272957f3e987e0e54b + +PKG_LICENSE:=BSD-2-Clause +PKG_LICENSE_FILES:=LICENSE lib/LICENSE + +HOST_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/host-build.mk + +# Always optimize for speed +HOST_CFLAGS := $(filter-out -O%,$(HOST_CFLAGS)) -O3 + +HOST_MAKE_FLAGS+=PREFIX=$(HOST_BUILD_PREFIX) \ + ENABLE_DOCS=1 + +define Host/Configure +endef + +define Host/Compile + $(call Host/Compile/Default,default) +endef + +define Host/Install + $(call Host/Compile/Default,install) +endef + +define Host/Uninstall + $(call Host/Compile/Default,uninstall) + $(call Host/Compile/Default,clean) +endef + +define Host/Clean +endef + +$(eval $(call HostBuild)) diff --git a/tools/lz4/patches/001-add-make-ENABLE_DOCS-configurable.patch b/tools/lz4/patches/001-add-make-ENABLE_DOCS-configurable.patch new file mode 100644 index 00000000000..5d6dca33f31 --- /dev/null +++ b/tools/lz4/patches/001-add-make-ENABLE_DOCS-configurable.patch @@ -0,0 +1,60 @@ ++++ a/programs/Makefile 2022-08-15 15:45:31.000000000 -0700 +--- b/programs/Makefile 2022-11-28 16:34:21.315593784 -0800 +@@ -66,6 +66,7 @@ + MD2ROFF = ronn + MD2ROFF_FLAGS = --roff --warnings --manual="User Commands" --organization="lz4 $(LZ4_VERSION)" + ++ENABLE_DOCS ?= 1 + + default: lz4-release + +@@ -120,6 +121,7 @@ + lz4c32 : $(SRCFILES) + $(CC) $(FLAGS) $^ -o $@$(EXT) + ++ifeq ($(ENABLE_DOCS),1) + lz4.1: lz4.1.md $(LIBVER_SRC) + cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | $(SED) -n '/^\.\\\".*/!p' > $@ + +@@ -130,6 +132,7 @@ + + preview-man: clean-man man + man ./lz4.1 ++endif + + clean: + ifeq ($(WINBASED),yes) +@@ -172,16 +175,19 @@ + + install: lz4 + @echo Installing binaries in $(DESTDIR)$(bindir) +- $(INSTALL_DIR) $(DESTDIR)$(bindir)/ $(DESTDIR)$(man1dir)/ ++ $(INSTALL_DIR) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) lz4$(EXT) $(DESTDIR)$(bindir)/lz4$(EXT) + $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4c$(EXT) + $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4cat$(EXT) + $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/unlz4$(EXT) ++ifeq ($(ENABLE_DOCS),1) + @echo Installing man pages in $(DESTDIR)$(man1dir) ++ $(INSTALL_DIR) $(DESTDIR)$(man1dir)/ + $(INSTALL_DATA) lz4.1 $(DESTDIR)$(man1dir)/lz4.1 + $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4c.1 + $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4cat.1 + $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/unlz4.1 ++endif + @echo lz4 installation completed + + uninstall: +@@ -189,10 +195,12 @@ + $(RM) $(DESTDIR)$(bindir)/unlz4$(EXT) + $(RM) $(DESTDIR)$(bindir)/lz4$(EXT) + $(RM) $(DESTDIR)$(bindir)/lz4c$(EXT) ++ifeq ($(ENABLE_DOCS),1) + $(RM) $(DESTDIR)$(man1dir)/lz4.1 + $(RM) $(DESTDIR)$(man1dir)/lz4c.1 + $(RM) $(DESTDIR)$(man1dir)/lz4cat.1 + $(RM) $(DESTDIR)$(man1dir)/unlz4.1 ++endif + @echo lz4 programs successfully uninstalled + + endif diff --git a/tools/lz4/patches/002-makefile-install-links-from-same-dir.patch b/tools/lz4/patches/002-makefile-install-links-from-same-dir.patch new file mode 100644 index 00000000000..159dc67f1af --- /dev/null +++ b/tools/lz4/patches/002-makefile-install-links-from-same-dir.patch @@ -0,0 +1,71 @@ +diff -ur a/lib/Makefile b/lib/Makefile +--- a/lib/Makefile 2022-12-04 23:49:06.336839263 -0800 ++++ b/lib/Makefile 2022-12-05 00:00:59.172307488 -0800 +@@ -195,8 +195,8 @@ + $(INSTALL_PROGRAM) dll/$(LIBLZ4_EXP) $(DESTDIR)$(libdir) + else + $(INSTALL_PROGRAM) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir) +- $(LN_SF) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT_MAJOR) +- $(LN_SF) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT) ++ (cd $(DESTDIR)$(libdir) && $(LN_SF) liblz4.$(SHARED_EXT_VER) liblz4.$(SHARED_EXT_MAJOR)) ++ (cd $(DESTDIR)$(libdir) && $(LN_SF) liblz4.$(SHARED_EXT_MAJOR) liblz4.$(SHARED_EXT)) + endif + endif + @echo Installing headers in $(DESTDIR)$(includedir) +diff -ur a/Makefile b/Makefile +--- a/Makefile 2022-12-04 23:49:06.336839263 -0800 ++++ b/Makefile 2022-12-04 23:42:09.693836654 -0800 +@@ -77,12 +77,12 @@ + + .PHONY: clean + clean: +- $(MAKE) -C $(LZ4DIR) $@ > $(VOID) +- $(MAKE) -C $(PRGDIR) $@ > $(VOID) +- $(MAKE) -C $(TESTDIR) $@ > $(VOID) +- $(MAKE) -C $(EXDIR) $@ > $(VOID) +- $(MAKE) -C $(FUZZDIR) $@ > $(VOID) +- $(MAKE) -C contrib/gen_manual $@ > $(VOID) ++ $(MAKE) -C $(LZ4DIR) $@ ++ $(MAKE) -C $(PRGDIR) $@ ++ $(MAKE) -C $(TESTDIR) $@ ++ $(MAKE) -C $(EXDIR) $@ ++ $(MAKE) -C $(FUZZDIR) $@ ++ $(MAKE) -C contrib/gen_manual $@ + $(RM) lz4$(EXT) + $(RM) -r $(CMAKE_BUILD_DIR) + @echo Cleaning completed +diff -ur a/programs/Makefile b/programs/Makefile +--- a/programs/Makefile 2022-12-04 23:49:06.336839263 -0800 ++++ b/programs/Makefile 2022-12-04 23:42:30.849582910 -0800 +@@ -138,7 +138,7 @@ + ifeq ($(WINBASED),yes) + $(RM) *.rc + endif +- $(MAKE) -C $(LZ4DIR) $@ > $(VOID) ++ $(MAKE) -C $(LZ4DIR) $@ + $(RM) core *.o *.test tmp* \ + lz4$(EXT) lz4c$(EXT) lz4c32$(EXT) lz4-wlib$(EXT) \ + unlz4$(EXT) lz4cat$(EXT) +@@ -177,16 +177,16 @@ + @echo Installing binaries in $(DESTDIR)$(bindir) + $(INSTALL_DIR) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) lz4$(EXT) $(DESTDIR)$(bindir)/lz4$(EXT) +- $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4c$(EXT) +- $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/lz4cat$(EXT) +- $(LN_SF) lz4$(EXT) $(DESTDIR)$(bindir)/unlz4$(EXT) ++ (cd $(DESTDIR)$(bindir) && $(LN_SF) lz4$(EXT) lz4c$(EXT)) ++ (cd $(DESTDIR)$(bindir) && $(LN_SF) lz4$(EXT) lz4cat$(EXT)) ++ (cd $(DESTDIR)$(bindir) && $(LN_SF) lz4$(EXT) unlz4$(EXT)) + ifeq ($(ENABLE_DOCS),1) + @echo Installing man pages in $(DESTDIR)$(man1dir) + $(INSTALL_DIR) $(DESTDIR)$(man1dir)/ + $(INSTALL_DATA) lz4.1 $(DESTDIR)$(man1dir)/lz4.1 +- $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4c.1 +- $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4cat.1 +- $(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/unlz4.1 ++ (cd $(DESTDIR)$(man1dir) && $(LN_SF) lz4.1 lz4c.1) ++ (cd $(DESTDIR)$(man1dir) && $(LN_SF) lz4.1 lz4cat.1) ++ (cd $(DESTDIR)$(man1dir) && $(LN_SF) lz4.1 unlz4.1) + endif + @echo lz4 installation completed + From 9a8509c2c572a29aec28b6b10da12c5d7a1efba8 Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Mon, 28 Nov 2022 17:06:46 -0800 Subject: [PATCH 19/21] tools/liblzo: add `liblzo` library prerequisite of upcoming `tools/lzop` addition, and subsequent initramfs and squashfs cleanups same as `packages/lzo` modified to be a HOST/tools type build, and should always be the same version and sources when either one is bumped because this (and `packages/lzo`) only provide liblzo and no executables, use the clearer name `tools/liblzo` Signed-off-by: Tony Butler --- tools/Makefile | 2 + tools/liblzo/Makefile | 42 ++++++++++++ .../001-add-cmake-ENABLE-configurables.patch | 68 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 tools/liblzo/Makefile create mode 100644 tools/liblzo/patches/001-add-cmake-ENABLE-configurables.patch diff --git a/tools/Makefile b/tools/Makefile index 46283e8d814..67b09f3a803 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -62,6 +62,7 @@ tools-y += sstrip tools-y += zip tools-y += zlib tools-y += zstd +tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS),y) += liblzo tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_B43_TOOLS),y) += b43-tools tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_ISL),y) += isl tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_LZ4_TOOLS),y) += lz4 @@ -94,6 +95,7 @@ $(curdir)/gengetopt/compile := $(curdir)/libtool/compile $(curdir)/gmp/compile := $(curdir)/libtool/compile $(curdir)/isl/compile := $(curdir)/gmp/compile $(curdir)/libdeflate/compile := $(curdir)/cmake/compile +$(curdir)/liblzo/compile := $(curdir)/cmake/compile $(curdir)/libressl/compile := $(curdir)/pkgconf/compile $(curdir)/libtool/compile := $(curdir)/automake/compile $(curdir)/missing-macros/compile $(curdir)/lzma-old/compile := $(curdir)/zlib/compile diff --git a/tools/liblzo/Makefile b/tools/liblzo/Makefile new file mode 100644 index 00000000000..4ebda0c3336 --- /dev/null +++ b/tools/liblzo/Makefile @@ -0,0 +1,42 @@ +# +# Copyright (C) 2022 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lzo +PKG_VERSION:=2.10 +PKG_RELEASE:=4 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.oberhumer.com/opensource/lzo/download/ +PKG_HASH:=c0f892943208266f9b6543b3ae308fab6284c5c90e627931446fb49b4221a072 + +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +CMAKE_BINARY_SUBDIR:=openwrt-build + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/cmake.mk + +CMAKE_HOST_OPTIONS += \ + -DENABLE_SHARED=ON \ + -DENABLE_TESTS=OFF \ + -DENABLE_EXAMPLES=OFF \ + -DENABLE_DOCS=ON \ + -DBUILD_TESTING=OFF + +define Host/Uninstall + rm -rf $(HOST_BUILD_PREFIX)/include/lzo + rm -f $(HOST_BUILD_PREFIX)/lib/liblzo2.a + rm -f $(HOST_BUILD_PREFIX)/lib/liblzo2.so.2.0.0 + rm -f $(HOST_BUILD_PREFIX)/lib/liblzo2.so.2 + rm -f $(HOST_BUILD_PREFIX)/lib/liblzo2.so + rm -f $(HOST_BUILD_PREFIX)/lib/pkgconfig/lzo2.pc +endef + +$(eval $(call HostBuild)) diff --git a/tools/liblzo/patches/001-add-cmake-ENABLE-configurables.patch b/tools/liblzo/patches/001-add-cmake-ENABLE-configurables.patch new file mode 100644 index 00000000000..9ab27fc924a --- /dev/null +++ b/tools/liblzo/patches/001-add-cmake-ENABLE-configurables.patch @@ -0,0 +1,68 @@ +--- a/CMakeLists.txt 2022-11-28 06:34:39.171209779 -0800 ++++ b/CMakeLists.txt 2022-11-28 06:33:13.368239757 -0800 +@@ -51,8 +51,11 @@ + project(lzo VERSION 2.10 LANGUAGES C) + + # configuration options +-option(ENABLE_STATIC "Build static LZO library." ON) +-option(ENABLE_SHARED "Build shared LZO library." OFF) ++option(ENABLE_STATIC "Build static LZO library." ON) ++option(ENABLE_SHARED "Build shared LZO library." OFF) ++option(ENABLE_TESTS "Build tests." ON) ++option(ENABLE_EXAMPLES "Build examples." ON) ++option(ENABLE_DOCS "Install documentation." ON) + if(NOT ENABLE_STATIC AND NOT ENABLE_SHARED) + set(ENABLE_STATIC ON) + endif() +@@ -127,14 +130,20 @@ + endif() + endmacro() + # main test driver ++if(ENABLE_TESTS OR ENABLE_EXAMPLES) + lzo_add_executable(lzotest lzotest/lzotest.c) ++endif() + # examples ++if(ENABLE_EXAMPLES) + lzo_add_executable(dict examples/dict.c) + lzo_add_executable(lzopack examples/lzopack.c) + lzo_add_executable(overlap examples/overlap.c) + lzo_add_executable(precomp examples/precomp.c) + lzo_add_executable(precomp2 examples/precomp2.c) ++endif() ++if(ENABLE_TESTS OR ENABLE_EXAMPLES) + lzo_add_executable(simple examples/simple.c) ++endif() + # some boring internal test programs + if(0) + lzo_add_executable(align tests/align.c) +@@ -144,7 +153,7 @@ + endif() + + # miniLZO +-if(1) ++if(ENABLE_TESTS) + add_executable(testmini minilzo/testmini.c minilzo/minilzo.c) + target_include_directories(testmini PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/lzo") # needed for "lzoconf.h" + endif() +@@ -263,8 +272,10 @@ + + if(DEFINED CMAKE_INSTALL_FULL_LIBDIR) + +-set(f AUTHORS COPYING NEWS THANKS doc/LZO.FAQ doc/LZO.TXT doc/LZOAPI.TXT) +-install(FILES ${f} DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}") ++if(ENABLE_DOCS) ++ set(f AUTHORS COPYING NEWS THANKS doc/LZO.FAQ doc/LZO.TXT doc/LZOAPI.TXT) ++ install(FILES ${f} DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}") ++endif() + + set(f include/lzo/lzo1.h include/lzo/lzo1a.h include/lzo/lzo1b.h + include/lzo/lzo1c.h include/lzo/lzo1f.h include/lzo/lzo1x.h +@@ -285,7 +296,7 @@ + ) + endif() + +-if(1) ++if(ENABLE_EXAMPLES) + set(f lzopack lzotest simple testmini) # examples + install(TARGETS ${f} DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/lzo/examples") + endif() From 32e99ed06972e4295cec7ae57b2c55eb63566461 Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Mon, 28 Nov 2022 17:32:11 -0800 Subject: [PATCH 20/21] tools/lzop: add `lzop` binaries Depends: `tools/liblzo` `lzop` is the standard executable for LZO compression the initramfs generator offers the LZO option but there was no executable to support it actually working Signed-off-by: Tony Butler --- tools/Makefile | 5 +++ tools/lzop/Makefile | 33 +++++++++++++++++++ ...1-add-cmake-ENABLE_DOCS-configurable.patch | 24 ++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 tools/lzop/Makefile create mode 100644 tools/lzop/patches/001-add-cmake-ENABLE_DOCS-configurable.patch diff --git a/tools/Makefile b/tools/Makefile index 67b09f3a803..a8044dcf1fe 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -23,6 +23,9 @@ endif ifneq ($(CONFIG_SDK)$(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),) BUILD_LZ4_TOOLS = y endif +ifneq ($(CONFIG_SDK)$(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),) + BUILD_LZO_TOOLS = y +endif tools-y += autoconf tools-y += autoconf-archive @@ -66,6 +69,7 @@ tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS),y) += liblzo tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_B43_TOOLS),y) += b43-tools tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_ISL),y) += isl tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_LZ4_TOOLS),y) += lz4 +tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_LZO_TOOLS),y) += lzop tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(BUILD_TOOLCHAIN),y) += gmp mpc mpfr tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(CONFIG_TARGET_apm821xx)$(CONFIG_TARGET_gemini),y) += genext2fs tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(CONFIG_TARGET_ath79),y) += lzma-old squashfs @@ -99,6 +103,7 @@ $(curdir)/liblzo/compile := $(curdir)/cmake/compile $(curdir)/libressl/compile := $(curdir)/pkgconf/compile $(curdir)/libtool/compile := $(curdir)/automake/compile $(curdir)/missing-macros/compile $(curdir)/lzma-old/compile := $(curdir)/zlib/compile +$(curdir)/lzop/compile := $(curdir)/cmake/compile $(curdir)/liblzo/compile $(curdir)/llvm-bpf/compile := $(curdir)/cmake/compile $(curdir)/make-ext4fs/compile := $(curdir)/zlib/compile $(curdir)/meson/compile := $(curdir)/ninja/compile diff --git a/tools/lzop/Makefile b/tools/lzop/Makefile new file mode 100644 index 00000000000..65bd7fe67c1 --- /dev/null +++ b/tools/lzop/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (C) 2022 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lzop +PKG_VERSION:=1.04 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.lzop.org/download/ +PKG_HASH:=7e72b62a8a60aff5200a047eea0773a8fb205caf7acbe1774d95147f305a2f41 + +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +CMAKE_BINARY_SUBDIR:=openwrt-build + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/cmake.mk + +CMAKE_HOST_OPTIONS += \ + -DENABLE_DOCS=ON \ + -DBUILD_TESTING=OFF + +define Host/Uninstall + rm -f $(STAGING_DIR_HOST)/bin/lzop +endef + +$(eval $(call HostBuild)) diff --git a/tools/lzop/patches/001-add-cmake-ENABLE_DOCS-configurable.patch b/tools/lzop/patches/001-add-cmake-ENABLE_DOCS-configurable.patch new file mode 100644 index 00000000000..01ebd33a399 --- /dev/null +++ b/tools/lzop/patches/001-add-cmake-ENABLE_DOCS-configurable.patch @@ -0,0 +1,24 @@ +--- a/CMakeLists.txt 2017-08-10 04:19:45.000000000 -0700 ++++ b/CMakeLists.txt 2022-11-28 17:21:03.453548350 -0800 +@@ -50,6 +50,9 @@ + + project(lzop VERSION 1.04 LANGUAGES C) + ++# configuration options ++option(ENABLE_DOCS "Install documentation." ON) ++ + # install directories + if(NOT CMAKE_INSTALL_PREFIX) + message(FATAL_ERROR "ERROR: CMAKE_INSTALL_PREFIX is not defined.") +@@ -186,9 +189,11 @@ + + install(TARGETS lzop DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") + ++if(ENABLE_DOCS) + set(f AUTHORS COPYING NEWS README THANKS doc/lzop.html doc/lzop.man doc/lzop.pod doc/lzop.ps doc/lzop.tex doc/lzop.txt) + install(FILES ${f} DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}") + install(FILES doc/lzop.1 DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man1") ++endif() # ENABLE_DOCS + + endif() # CMAKE_INSTALL_FULL_LIBDIR + From 4a444e576fd26764ed11aed8c3bdf2281bba3cc6 Mon Sep 17 00:00:00 2001 From: Tony Butler Date: Mon, 28 Nov 2022 17:37:20 -0800 Subject: [PATCH 21/21] build: fix incomplete initramfs compression options Requires: tools/lz4, tools/lzop complete the wiring so that these options work: * `CONFIG_KERNEL_INITRAMFS_COMPRESSION_LZO` * `CONFIG_KERNEL_INITRAMFS_COMPRESSION_LZ4` Signed-off-by: Tony Butler [remove blocking dependencies for separate ramdisk, fix lzop options] Signed-off-by: Daniel Golle --- config/Config-images.in | 2 -- include/image-commands.mk | 2 ++ include/kernel-defaults.mk | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/Config-images.in b/config/Config-images.in index 5615141b750..6e43793ef53 100644 --- a/config/Config-images.in +++ b/config/Config-images.in @@ -37,11 +37,9 @@ menu "Target Images" bool "lzma" config TARGET_INITRAMFS_COMPRESSION_LZO - depends on !TARGET_ROOTFS_INITRAMFS_SEPARATE bool "lzo" config TARGET_INITRAMFS_COMPRESSION_LZ4 - depends on !TARGET_ROOTFS_INITRAMFS_SEPARATE bool "lz4" config TARGET_INITRAMFS_COMPRESSION_XZ diff --git a/include/image-commands.mk b/include/image-commands.mk index ff8acf96c4f..70055cc5764 100644 --- a/include/image-commands.mk +++ b/include/image-commands.mk @@ -277,7 +277,9 @@ endef define Build/initrd_compression $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_BZIP2),.bzip2) \ $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_GZIP),.gzip) \ + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),.lz4) \ $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZMA),.lzma) \ + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),.lzo) \ $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_XZ),.xz) \ $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_ZSTD),.zstd) endef diff --git a/include/kernel-defaults.mk b/include/kernel-defaults.mk index dcba319a0f2..127fa8563af 100644 --- a/include/kernel-defaults.mk +++ b/include/kernel-defaults.mk @@ -179,10 +179,10 @@ endif $(if $(SOURCE_DATE_EPOCH),touch -hcd "@$(SOURCE_DATE_EPOCH)" $(KERNEL_BUILD_DIR)/initrd.cpio) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_BZIP2),bzip2 -9 -c < $(KERNEL_BUILD_DIR)/initrd.cpio > $(KERNEL_BUILD_DIR)/initrd.cpio.bzip2) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_GZIP),gzip -n -f -S .gzip -9n $(KERNEL_BUILD_DIR)/initrd.cpio) + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),$(STAGING_DIR_HOST)/bin/lz4c -l -c1 -fz --favor-decSpeed $(KERNEL_BUILD_DIR)/initrd.cpio) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZMA),$(STAGING_DIR_HOST)/bin/lzma e -lc1 -lp2 -pb2 $(KERNEL_BUILD_DIR)/initrd.cpio $(KERNEL_BUILD_DIR)/initrd.cpio.lzma) -# ? $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),) + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),$(STAGING_DIR_HOST)/bin/lzop -9 -f $(KERNEL_BUILD_DIR)/initrd.cpio) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_XZ),$(STAGING_DIR_HOST)/bin/xz -T$(if $(filter 1,$(NPROC)),2,0) -9 -fz --check=crc32 $(KERNEL_BUILD_DIR)/initrd.cpio) -# ? $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),) $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_ZSTD),$(STAGING_DIR_HOST)/bin/zstd -T0 -f -o $(KERNEL_BUILD_DIR)/initrd.cpio.zstd $(KERNEL_BUILD_DIR)/initrd.cpio) endif +$(KERNEL_MAKE) $(KERNEL_MAKEOPTS_IMAGE) $(if $(KERNELNAME),$(KERNELNAME),all) modules