- Add pfe driver to NXP LS1012A FRWY board.
- Add grub-efi based boot on NXP ls1012a FRWY Board.
Change-Id: I3877e25afc9b67cabe6f7a22f075a31ecad50e80
Signed-off-by: srinidhira0 <srinidhir@vmware.com>
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/6498
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Alexey Makhalov <amakhalov@vmware.com>
| ... | ... |
@@ -1496,7 +1496,7 @@ CONFIG_NET_MPLS_GSO=m |
| 1496 | 1496 |
# CONFIG_MPLS_ROUTING is not set |
| 1497 | 1497 |
CONFIG_NET_NSH=m |
| 1498 | 1498 |
# CONFIG_HSR is not set |
| 1499 |
-# CONFIG_NET_SWITCHDEV is not set |
|
| 1499 |
+CONFIG_NET_SWITCHDEV=y |
|
| 1500 | 1500 |
CONFIG_NET_L3_MASTER_DEV=y |
| 1501 | 1501 |
# CONFIG_QRTR is not set |
| 1502 | 1502 |
# CONFIG_NET_NCSI is not set |
| ... | ... |
@@ -2210,10 +2210,11 @@ CONFIG_BE2NET_HWMON=y |
| 2210 | 2210 |
CONFIG_NET_VENDOR_EZCHIP=y |
| 2211 | 2211 |
# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set |
| 2212 | 2212 |
CONFIG_NET_VENDOR_FREESCALE=y |
| 2213 |
-# CONFIG_FSL_FMAN is not set |
|
| 2213 |
+CONFIG_FSL_FMAN=m |
|
| 2214 | 2214 |
# CONFIG_FSL_PQ_MDIO is not set |
| 2215 |
-# CONFIG_FSL_XGMAC_MDIO is not set |
|
| 2215 |
+CONFIG_FSL_XGMAC_MDIO=m |
|
| 2216 | 2216 |
# CONFIG_GIANFAR is not set |
| 2217 |
+CONFIG_FSL_DPAA_ETH=m |
|
| 2217 | 2218 |
CONFIG_NET_VENDOR_HISILICON=y |
| 2218 | 2219 |
# CONFIG_HIX5HD2_GMAC is not set |
| 2219 | 2220 |
# CONFIG_HISI_FEMAC is not set |
| ... | ... |
@@ -2270,6 +2271,7 @@ CONFIG_NET_VENDOR_MICROCHIP=y |
| 2270 | 2270 |
# CONFIG_ENCX24J600 is not set |
| 2271 | 2271 |
CONFIG_LAN743X=m |
| 2272 | 2272 |
CONFIG_NET_VENDOR_MICROSEMI=y |
| 2273 |
+# CONFIG_MSCC_OCELOT_SWITCH is not set |
|
| 2273 | 2274 |
CONFIG_NET_VENDOR_MYRI=y |
| 2274 | 2275 |
CONFIG_MYRI10GE=m |
| 2275 | 2276 |
# CONFIG_FEALNX is not set |
| ... | ... |
@@ -2303,6 +2305,7 @@ CONFIG_8139TOO_8129=y |
| 2303 | 2303 |
CONFIG_R8169=m |
| 2304 | 2304 |
CONFIG_NET_VENDOR_RENESAS=y |
| 2305 | 2305 |
CONFIG_NET_VENDOR_ROCKER=y |
| 2306 |
+# CONFIG_ROCKER is not set |
|
| 2306 | 2307 |
CONFIG_NET_VENDOR_SAMSUNG=y |
| 2307 | 2308 |
# CONFIG_SXGBE_ETH is not set |
| 2308 | 2309 |
# CONFIG_NET_VENDOR_SEEQ is not set |
| ... | ... |
@@ -2902,6 +2905,7 @@ CONFIG_PPS=y |
| 2902 | 2902 |
# |
| 2903 | 2903 |
CONFIG_PTP_1588_CLOCK=y |
| 2904 | 2904 |
CONFIG_PTP_1588_CLOCK_DTE=y |
| 2905 |
+CONFIG_PTP_1588_CLOCK_QORIQ=m |
|
| 2905 | 2906 |
# CONFIG_DP83640_PHY is not set |
| 2906 | 2907 |
CONFIG_PINCTRL=y |
| 2907 | 2908 |
CONFIG_PINMUX=y |
| ... | ... |
@@ -4942,6 +4946,8 @@ CONFIG_VIDEO_BCM2835=m |
| 4942 | 4942 |
# CONFIG_STAGING_GASKET_FRAMEWORK is not set |
| 4943 | 4943 |
# CONFIG_XIL_AXIS_FIFO is not set |
| 4944 | 4944 |
# CONFIG_EROFS_FS is not set |
| 4945 |
+CONFIG_FSL_PPFE=m |
|
| 4946 |
+CONFIG_FSL_PPFE_UTIL_DISABLED=y |
|
| 4945 | 4947 |
# CONFIG_GOLDFISH is not set |
| 4946 | 4948 |
# CONFIG_CHROME_PLATFORMS is not set |
| 4947 | 4949 |
CONFIG_CLKDEV_LOOKUP=y |
| ... | ... |
@@ -4964,7 +4970,7 @@ CONFIG_CLK_VEXPRESS_OSC=y |
| 4964 | 4964 |
# CONFIG_COMMON_CLK_CDCE706 is not set |
| 4965 | 4965 |
# CONFIG_COMMON_CLK_CDCE925 is not set |
| 4966 | 4966 |
# CONFIG_COMMON_CLK_CS2000_CP is not set |
| 4967 |
-# CONFIG_CLK_QORIQ is not set |
|
| 4967 |
+CONFIG_CLK_QORIQ=y |
|
| 4968 | 4968 |
CONFIG_COMMON_CLK_XGENE=y |
| 4969 | 4969 |
# CONFIG_COMMON_CLK_PWM is not set |
| 4970 | 4970 |
# CONFIG_COMMON_CLK_VC5 is not set |
| ... | ... |
@@ -5098,7 +5104,11 @@ CONFIG_RASPBERRYPI_POWER=y |
| 5098 | 5098 |
# |
| 5099 | 5099 |
# NXP/Freescale QorIQ SoC drivers |
| 5100 | 5100 |
# |
| 5101 |
-# CONFIG_FSL_DPAA is not set |
|
| 5101 |
+CONFIG_FSL_DPAA=y |
|
| 5102 |
+# CONFIG_FSL_DPAA_CHECKING is not set |
|
| 5103 |
+# CONFIG_FSL_BMAN_TEST is not set |
|
| 5104 |
+# CONFIG_FSL_QMAN_TEST is not set |
|
| 5105 |
+CONFIG_FSL_GUTS=y |
|
| 5102 | 5106 |
|
| 5103 | 5107 |
# |
| 5104 | 5108 |
# i.MX SoC drivers |
| ... | ... |
@@ -2,7 +2,7 @@ |
| 2 | 2 |
Summary: Kernel |
| 3 | 3 |
Name: linux |
| 4 | 4 |
Version: 4.19.6 |
| 5 |
-Release: 6%{?kat_build:.%kat_build}%{?dist}
|
|
| 5 |
+Release: 7%{?kat_build:.%kat_build}%{?dist}
|
|
| 6 | 6 |
License: GPLv2 |
| 7 | 7 |
URL: http://www.kernel.org/ |
| 8 | 8 |
Group: System Environment/Kernel |
| ... | ... |
@@ -43,7 +43,32 @@ Patch29: 4.17-0001-apparmor-patch-to-provide-compatibility-with-v2.x-ne.p |
| 43 | 43 |
Patch30: 4.17-0002-apparmor-af_unix-mediation.patch |
| 44 | 44 |
Patch31: 4.17-0003-apparmor-fix-use-after-free-in-sk_peer_label.patch |
| 45 | 45 |
Patch32: 4.18-0001-hwrng-rdrand-Add-RNG-driver-based-on-x86-rdrand-inst.patch |
| 46 |
- |
|
| 46 |
+%ifarch aarch64 |
|
| 47 |
+# NXP LS1012a FRWY patches |
|
| 48 |
+Patch51: 0001-staging-fsl_ppfe-eth-header-files-for-pfe-driver.patch |
|
| 49 |
+Patch52: 0002-staging-fsl_ppfe-eth-introduce-pfe-driver.patch |
|
| 50 |
+Patch53: 0003-staging-fsl_ppfe-eth-fix-RGMII-tx-delay-issue.patch |
|
| 51 |
+Patch54: 0004-staging-fsl_ppfe-eth-remove-unused-functions.patch |
|
| 52 |
+Patch55: 0005-staging-fsl_ppfe-eth-fix-read-write-ack-idx-issue.patch |
|
| 53 |
+Patch56: 0006-staging-fsl_ppfe-eth-Make-phy_ethtool_ksettings_get-.patch |
|
| 54 |
+Patch57: 0007-staging-fsl_ppfe-eth-add-function-to-update-tmu-cred.patch |
|
| 55 |
+Patch58: 0008-staging-fsl_ppfe-eth-Avoid-packet-drop-at-TMU-queues.patch |
|
| 56 |
+Patch59: 0009-staging-fsl_ppfe-eth-Enable-PFE-in-clause-45-mode.patch |
|
| 57 |
+Patch60: 0010-staging-fsl_ppfe-eth-Disable-autonegotiation-for-2.5.patch |
|
| 58 |
+Patch61: 0011-staging-fsl_ppfe-eth-add-missing-included-header-fil.patch |
|
| 59 |
+Patch62: 0012-staging-fsl_ppfe-eth-clean-up-iounmap-pfe-ddr_basead.patch |
|
| 60 |
+Patch63: 0013-staging-fsl_ppfe-eth-calculate-PFE_PKT_SIZE-with-SKB.patch |
|
| 61 |
+Patch64: 0014-staging-fsl_ppfe-eth-support-for-userspace-networkin.patch |
|
| 62 |
+Patch65: 0015-staging-fsl_ppfe-eth-unregister-netdev-after-pfe_phy.patch |
|
| 63 |
+Patch66: 0016-staging-fsl_ppfe-eth-HW-parse-results-for-DPDK.patch |
|
| 64 |
+Patch67: 0017-staging-fsl_ppfe-eth-reorganize-pfe_netdev_ops.patch |
|
| 65 |
+Patch68: 0018-staging-fsl_ppfe-eth-use-mask-for-rx-max-frame-len.patch |
|
| 66 |
+Patch69: 0019-staging-fsl_ppfe-eth-define-pfe-ndo_change_mtu-funct.patch |
|
| 67 |
+Patch70: 0020-staging-fsl_ppfe-eth-remove-jumbo-frame-enable-from-.patch |
|
| 68 |
+Patch71: 0021-staging-fsl_ppfe-eth-disable-CRC-removal.patch |
|
| 69 |
+Patch72: 0022-staging-fsl_ppfe-eth-handle-ls1012a-errata_a010897.patch |
|
| 70 |
+Patch73: 0023-staging-fsl_ppfe-eth-Modify-Kconfig-to-enable-pfe-dr.patch |
|
| 71 |
+%endif |
|
| 47 | 72 |
|
| 48 | 73 |
%if 0%{?kat_build:1}
|
| 49 | 74 |
Patch1000: %{kat_build}.patch
|
| ... | ... |
@@ -155,6 +180,32 @@ Kernel Device Tree Blob files for NXP ls1012a FRWY board |
| 155 | 155 |
%patch31 -p1 |
| 156 | 156 |
%patch32 -p1 |
| 157 | 157 |
|
| 158 |
+%ifarch aarch64 |
|
| 159 |
+# NXP FSL_PPFE Driver patches |
|
| 160 |
+%patch51 -p1 |
|
| 161 |
+%patch52 -p1 |
|
| 162 |
+%patch53 -p1 |
|
| 163 |
+%patch54 -p1 |
|
| 164 |
+%patch55 -p1 |
|
| 165 |
+%patch56 -p1 |
|
| 166 |
+%patch57 -p1 |
|
| 167 |
+%patch58 -p1 |
|
| 168 |
+%patch59 -p1 |
|
| 169 |
+%patch60 -p1 |
|
| 170 |
+%patch61 -p1 |
|
| 171 |
+%patch62 -p1 |
|
| 172 |
+%patch63 -p1 |
|
| 173 |
+%patch64 -p1 |
|
| 174 |
+%patch65 -p1 |
|
| 175 |
+%patch66 -p1 |
|
| 176 |
+%patch67 -p1 |
|
| 177 |
+%patch68 -p1 |
|
| 178 |
+%patch69 -p1 |
|
| 179 |
+%patch70 -p1 |
|
| 180 |
+%patch71 -p1 |
|
| 181 |
+%patch72 -p1 |
|
| 182 |
+%patch73 -p1 |
|
| 183 |
+%endif |
|
| 158 | 184 |
%if 0%{?kat_build:1}
|
| 159 | 185 |
%patch1000 -p1 |
| 160 | 186 |
%endif |
| ... | ... |
@@ -249,7 +300,7 @@ install -vm 644 arch/arm64/boot/Image %{buildroot}/boot/vmlinuz-%{uname_r}
|
| 249 | 249 |
# Install DTB files |
| 250 | 250 |
install -vdm 755 %{buildroot}/boot/dtb
|
| 251 | 251 |
install -vm 640 arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dtb %{buildroot}/boot/dtb/
|
| 252 |
-install -vm 640 arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dtb %{buildroot}/boot/dtb/
|
|
| 252 |
+install -vm 640 arch/arm64/boot/dts/freescale/fsl-ls1012a-frwy.dtb %{buildroot}/boot/dtb/
|
|
| 253 | 253 |
%endif |
| 254 | 254 |
|
| 255 | 255 |
# Restrict the permission on System.map-X file |
| ... | ... |
@@ -381,11 +432,13 @@ ln -sf %{name}-%{uname_r}.cfg /boot/photon.cfg
|
| 381 | 381 |
|
| 382 | 382 |
%files dtb-ls1012afrwy |
| 383 | 383 |
%defattr(-,root,root) |
| 384 |
-/boot/dtb/fsl-ls1012a-frdm.dtb |
|
| 384 |
+/boot/dtb/fsl-ls1012a-frwy.dtb |
|
| 385 | 385 |
|
| 386 | 386 |
%endif |
| 387 | 387 |
|
| 388 | 388 |
%changelog |
| 389 |
+* Fri Jan 11 2019 Srinidhi Rao <srinidhir@vmware.com> 4.19.6-7 |
|
| 390 |
+- Add Network support for NXP LS1012A board. |
|
| 389 | 391 |
* Wed Jan 09 2019 Ankit Jain <ankitja@vmware.com> 4.19.6-6 |
| 390 | 392 |
- Enable following for x86_64 and aarch64: |
| 391 | 393 |
- Enable Kernel Address Space Layout Randomization. |
| 392 | 394 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,2692 @@ |
| 0 |
+From 77d2c2e907a9921aaed61cb33230a866500d5512 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Sat, 16 Sep 2017 14:21:37 +0530 |
|
| 3 |
+Subject: [PATCH 01/22] staging: fsl_ppfe/eth: header files for pfe driver |
|
| 4 |
+ |
|
| 5 |
+This patch has all pfe header files. |
|
| 6 |
+ |
|
| 7 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 8 |
+Signed-off-by: Anjaneyulu Jagarlmudi <anji.jagarlmudi@nxp.com> |
|
| 9 |
+ |
|
| 10 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 11 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 12 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 13 |
+] |
|
| 14 |
+ |
|
| 15 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 16 |
+--- |
|
| 17 |
+ drivers/staging/fsl_ppfe/include/pfe/cbus.h | 78 +++++ |
|
| 18 |
+ drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h | 55 +++ |
|
| 19 |
+ .../staging/fsl_ppfe/include/pfe/cbus/class_csr.h | 289 ++++++++++++++++ |
|
| 20 |
+ .../staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h | 242 ++++++++++++++ |
|
| 21 |
+ drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h | 86 +++++ |
|
| 22 |
+ drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h | 100 ++++++ |
|
| 23 |
+ .../staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h | 50 +++ |
|
| 24 |
+ .../staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h | 168 ++++++++++ |
|
| 25 |
+ .../staging/fsl_ppfe/include/pfe/cbus/util_csr.h | 61 ++++ |
|
| 26 |
+ drivers/staging/fsl_ppfe/include/pfe/pfe.h | 372 +++++++++++++++++++++ |
|
| 27 |
+ drivers/staging/fsl_ppfe/pfe_ctrl.h | 112 +++++++ |
|
| 28 |
+ drivers/staging/fsl_ppfe/pfe_debugfs.h | 25 ++ |
|
| 29 |
+ drivers/staging/fsl_ppfe/pfe_eth.h | 184 ++++++++++ |
|
| 30 |
+ drivers/staging/fsl_ppfe/pfe_firmware.h | 32 ++ |
|
| 31 |
+ drivers/staging/fsl_ppfe/pfe_hif.h | 211 ++++++++++++ |
|
| 32 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.h | 239 +++++++++++++ |
|
| 33 |
+ drivers/staging/fsl_ppfe/pfe_hw.h | 27 ++ |
|
| 34 |
+ drivers/staging/fsl_ppfe/pfe_mod.h | 112 +++++++ |
|
| 35 |
+ drivers/staging/fsl_ppfe/pfe_perfmon.h | 38 +++ |
|
| 36 |
+ drivers/staging/fsl_ppfe/pfe_sysfs.h | 29 ++ |
|
| 37 |
+ 20 files changed, 2510 insertions(+) |
|
| 38 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus.h |
|
| 39 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h |
|
| 40 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/class_csr.h |
|
| 41 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h |
|
| 42 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h |
|
| 43 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h |
|
| 44 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h |
|
| 45 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h |
|
| 46 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/util_csr.h |
|
| 47 |
+ create mode 100644 drivers/staging/fsl_ppfe/include/pfe/pfe.h |
|
| 48 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_ctrl.h |
|
| 49 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_debugfs.h |
|
| 50 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_eth.h |
|
| 51 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_firmware.h |
|
| 52 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_hif.h |
|
| 53 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_hif_lib.h |
|
| 54 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_hw.h |
|
| 55 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_mod.h |
|
| 56 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_perfmon.h |
|
| 57 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_sysfs.h |
|
| 58 |
+ |
|
| 59 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus.h b/drivers/staging/fsl_ppfe/include/pfe/cbus.h |
|
| 60 |
+new file mode 100644 |
|
| 61 |
+index 000000000000..04503d28c982 |
|
| 62 |
+--- /dev/null |
|
| 63 |
+@@ -0,0 +1,78 @@ |
|
| 64 |
++/* |
|
| 65 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 66 |
++ * Copyright 2017 NXP |
|
| 67 |
++ * |
|
| 68 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 69 |
++ * it under the terms of the GNU General Public License as published by |
|
| 70 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 71 |
++ * (at your option) any later version. |
|
| 72 |
++ * |
|
| 73 |
++ * This program is distributed in the hope that it will be useful, |
|
| 74 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 75 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 76 |
++ * GNU General Public License for more details. |
|
| 77 |
++ * |
|
| 78 |
++ * You should have received a copy of the GNU General Public License |
|
| 79 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 80 |
++ */ |
|
| 81 |
++ |
|
| 82 |
++#ifndef _CBUS_H_ |
|
| 83 |
++#define _CBUS_H_ |
|
| 84 |
++ |
|
| 85 |
++#define EMAC1_BASE_ADDR (CBUS_BASE_ADDR + 0x200000) |
|
| 86 |
++#define EGPI1_BASE_ADDR (CBUS_BASE_ADDR + 0x210000) |
|
| 87 |
++#define EMAC2_BASE_ADDR (CBUS_BASE_ADDR + 0x220000) |
|
| 88 |
++#define EGPI2_BASE_ADDR (CBUS_BASE_ADDR + 0x230000) |
|
| 89 |
++#define BMU1_BASE_ADDR (CBUS_BASE_ADDR + 0x240000) |
|
| 90 |
++#define BMU2_BASE_ADDR (CBUS_BASE_ADDR + 0x250000) |
|
| 91 |
++#define ARB_BASE_ADDR (CBUS_BASE_ADDR + 0x260000) |
|
| 92 |
++#define DDR_CONFIG_BASE_ADDR (CBUS_BASE_ADDR + 0x270000) |
|
| 93 |
++#define HIF_BASE_ADDR (CBUS_BASE_ADDR + 0x280000) |
|
| 94 |
++#define HGPI_BASE_ADDR (CBUS_BASE_ADDR + 0x290000) |
|
| 95 |
++#define LMEM_BASE_ADDR (CBUS_BASE_ADDR + 0x300000) |
|
| 96 |
++#define LMEM_SIZE 0x10000 |
|
| 97 |
++#define LMEM_END (LMEM_BASE_ADDR + LMEM_SIZE) |
|
| 98 |
++#define TMU_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x310000) |
|
| 99 |
++#define CLASS_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x320000) |
|
| 100 |
++#define HIF_NOCPY_BASE_ADDR (CBUS_BASE_ADDR + 0x350000) |
|
| 101 |
++#define UTIL_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x360000) |
|
| 102 |
++#define CBUS_GPT_BASE_ADDR (CBUS_BASE_ADDR + 0x370000) |
|
| 103 |
++ |
|
| 104 |
++/* |
|
| 105 |
++ * defgroup XXX_MEM_ACCESS_ADDR PE memory access through CSR |
|
| 106 |
++ * XXX_MEM_ACCESS_ADDR register bit definitions. |
|
| 107 |
++ */ |
|
| 108 |
++#define PE_MEM_ACCESS_WRITE BIT(31) /* Internal Memory Write. */ |
|
| 109 |
++#define PE_MEM_ACCESS_IMEM BIT(15) |
|
| 110 |
++#define PE_MEM_ACCESS_DMEM BIT(16) |
|
| 111 |
++ |
|
| 112 |
++/* Byte Enables of the Internal memory access. These are interpred in BE */ |
|
| 113 |
++#define PE_MEM_ACCESS_BYTE_ENABLE(offset, size) \ |
|
| 114 |
++ ({ typeof(size) size_ = (size); \
|
|
| 115 |
++ (((BIT(size_) - 1) << (4 - (offset) - (size_))) & 0xf) << 24; }) |
|
| 116 |
++ |
|
| 117 |
++#include "cbus/emac_mtip.h" |
|
| 118 |
++#include "cbus/gpi.h" |
|
| 119 |
++#include "cbus/bmu.h" |
|
| 120 |
++#include "cbus/hif.h" |
|
| 121 |
++#include "cbus/tmu_csr.h" |
|
| 122 |
++#include "cbus/class_csr.h" |
|
| 123 |
++#include "cbus/hif_nocpy.h" |
|
| 124 |
++#include "cbus/util_csr.h" |
|
| 125 |
++ |
|
| 126 |
++/* PFE cores states */ |
|
| 127 |
++#define CORE_DISABLE 0x00000000 |
|
| 128 |
++#define CORE_ENABLE 0x00000001 |
|
| 129 |
++#define CORE_SW_RESET 0x00000002 |
|
| 130 |
++ |
|
| 131 |
++/* LMEM defines */ |
|
| 132 |
++#define LMEM_HDR_SIZE 0x0010 |
|
| 133 |
++#define LMEM_BUF_SIZE_LN2 0x7 |
|
| 134 |
++#define LMEM_BUF_SIZE BIT(LMEM_BUF_SIZE_LN2) |
|
| 135 |
++ |
|
| 136 |
++/* DDR defines */ |
|
| 137 |
++#define DDR_HDR_SIZE 0x0100 |
|
| 138 |
++#define DDR_BUF_SIZE_LN2 0xb |
|
| 139 |
++#define DDR_BUF_SIZE BIT(DDR_BUF_SIZE_LN2) |
|
| 140 |
++ |
|
| 141 |
++#endif /* _CBUS_H_ */ |
|
| 142 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h b/drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h |
|
| 143 |
+new file mode 100644 |
|
| 144 |
+index 000000000000..87738ca3cfbb |
|
| 145 |
+--- /dev/null |
|
| 146 |
+@@ -0,0 +1,55 @@ |
|
| 147 |
++/* |
|
| 148 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 149 |
++ * Copyright 2017 NXP |
|
| 150 |
++ * |
|
| 151 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 152 |
++ * it under the terms of the GNU General Public License as published by |
|
| 153 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 154 |
++ * (at your option) any later version. |
|
| 155 |
++ * |
|
| 156 |
++ * This program is distributed in the hope that it will be useful, |
|
| 157 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 158 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 159 |
++ * GNU General Public License for more details. |
|
| 160 |
++ * |
|
| 161 |
++ * You should have received a copy of the GNU General Public License |
|
| 162 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 163 |
++ */ |
|
| 164 |
++ |
|
| 165 |
++#ifndef _BMU_H_ |
|
| 166 |
++#define _BMU_H_ |
|
| 167 |
++ |
|
| 168 |
++#define BMU_VERSION 0x000 |
|
| 169 |
++#define BMU_CTRL 0x004 |
|
| 170 |
++#define BMU_UCAST_CONFIG 0x008 |
|
| 171 |
++#define BMU_UCAST_BASE_ADDR 0x00c |
|
| 172 |
++#define BMU_BUF_SIZE 0x010 |
|
| 173 |
++#define BMU_BUF_CNT 0x014 |
|
| 174 |
++#define BMU_THRES 0x018 |
|
| 175 |
++#define BMU_INT_SRC 0x020 |
|
| 176 |
++#define BMU_INT_ENABLE 0x024 |
|
| 177 |
++#define BMU_ALLOC_CTRL 0x030 |
|
| 178 |
++#define BMU_FREE_CTRL 0x034 |
|
| 179 |
++#define BMU_FREE_ERR_ADDR 0x038 |
|
| 180 |
++#define BMU_CURR_BUF_CNT 0x03c |
|
| 181 |
++#define BMU_MCAST_CNT 0x040 |
|
| 182 |
++#define BMU_MCAST_ALLOC_CTRL 0x044 |
|
| 183 |
++#define BMU_REM_BUF_CNT 0x048 |
|
| 184 |
++#define BMU_LOW_WATERMARK 0x050 |
|
| 185 |
++#define BMU_HIGH_WATERMARK 0x054 |
|
| 186 |
++#define BMU_INT_MEM_ACCESS 0x100 |
|
| 187 |
++ |
|
| 188 |
++struct BMU_CFG {
|
|
| 189 |
++ unsigned long baseaddr; |
|
| 190 |
++ u32 count; |
|
| 191 |
++ u32 size; |
|
| 192 |
++ u32 low_watermark; |
|
| 193 |
++ u32 high_watermark; |
|
| 194 |
++}; |
|
| 195 |
++ |
|
| 196 |
++#define BMU1_BUF_SIZE LMEM_BUF_SIZE_LN2 |
|
| 197 |
++#define BMU2_BUF_SIZE DDR_BUF_SIZE_LN2 |
|
| 198 |
++ |
|
| 199 |
++#define BMU2_MCAST_ALLOC_CTRL (BMU2_BASE_ADDR + BMU_MCAST_ALLOC_CTRL) |
|
| 200 |
++ |
|
| 201 |
++#endif /* _BMU_H_ */ |
|
| 202 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus/class_csr.h b/drivers/staging/fsl_ppfe/include/pfe/cbus/class_csr.h |
|
| 203 |
+new file mode 100644 |
|
| 204 |
+index 000000000000..e4dadff58768 |
|
| 205 |
+--- /dev/null |
|
| 206 |
+@@ -0,0 +1,289 @@ |
|
| 207 |
++/* |
|
| 208 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 209 |
++ * Copyright 2017 NXP |
|
| 210 |
++ * |
|
| 211 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 212 |
++ * it under the terms of the GNU General Public License as published by |
|
| 213 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 214 |
++ * (at your option) any later version. |
|
| 215 |
++ * |
|
| 216 |
++ * This program is distributed in the hope that it will be useful, |
|
| 217 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 218 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 219 |
++ * GNU General Public License for more details. |
|
| 220 |
++ * |
|
| 221 |
++ * You should have received a copy of the GNU General Public License |
|
| 222 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 223 |
++ */ |
|
| 224 |
++ |
|
| 225 |
++#ifndef _CLASS_CSR_H_ |
|
| 226 |
++#define _CLASS_CSR_H_ |
|
| 227 |
++ |
|
| 228 |
++/* @file class_csr.h. |
|
| 229 |
++ * class_csr - block containing all the classifier control and status register. |
|
| 230 |
++ * Mapped on CBUS and accessible from all PE's and ARM. |
|
| 231 |
++ */ |
|
| 232 |
++#define CLASS_VERSION (CLASS_CSR_BASE_ADDR + 0x000) |
|
| 233 |
++#define CLASS_TX_CTRL (CLASS_CSR_BASE_ADDR + 0x004) |
|
| 234 |
++#define CLASS_INQ_PKTPTR (CLASS_CSR_BASE_ADDR + 0x010) |
|
| 235 |
++ |
|
| 236 |
++/* (ddr_hdr_size[24:16], lmem_hdr_size[5:0]) */ |
|
| 237 |
++#define CLASS_HDR_SIZE (CLASS_CSR_BASE_ADDR + 0x014) |
|
| 238 |
++ |
|
| 239 |
++/* LMEM header size for the Classifier block.\ Data in the LMEM |
|
| 240 |
++ * is written from this offset. |
|
| 241 |
++ */ |
|
| 242 |
++#define CLASS_HDR_SIZE_LMEM(off) ((off) & 0x3f) |
|
| 243 |
++ |
|
| 244 |
++/* DDR header size for the Classifier block.\ Data in the DDR |
|
| 245 |
++ * is written from this offset. |
|
| 246 |
++ */ |
|
| 247 |
++#define CLASS_HDR_SIZE_DDR(off) (((off) & 0x1ff) << 16) |
|
| 248 |
++ |
|
| 249 |
++#define CLASS_PE0_QB_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x020) |
|
| 250 |
++ |
|
| 251 |
++/* DMEM address of first [15:0] and second [31:16] buffers on QB side. */ |
|
| 252 |
++#define CLASS_PE0_QB_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x024) |
|
| 253 |
++ |
|
| 254 |
++/* DMEM address of third [15:0] and fourth [31:16] buffers on QB side. */ |
|
| 255 |
++#define CLASS_PE0_RO_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x060) |
|
| 256 |
++ |
|
| 257 |
++/* DMEM address of first [15:0] and second [31:16] buffers on RO side. */ |
|
| 258 |
++#define CLASS_PE0_RO_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x064) |
|
| 259 |
++ |
|
| 260 |
++/* DMEM address of third [15:0] and fourth [31:16] buffers on RO side. */ |
|
| 261 |
++ |
|
| 262 |
++/* @name Class PE memory access. Allows external PE's and HOST to |
|
| 263 |
++ * read/write PMEM/DMEM memory ranges for each classifier PE. |
|
| 264 |
++ */ |
|
| 265 |
++/* {sr_pe_mem_cmd[31], csr_pe_mem_wren[27:24], csr_pe_mem_addr[23:0]},
|
|
| 266 |
++ * See \ref XXX_MEM_ACCESS_ADDR for details. |
|
| 267 |
++ */ |
|
| 268 |
++#define CLASS_MEM_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x100) |
|
| 269 |
++ |
|
| 270 |
++/* Internal Memory Access Write Data [31:0] */ |
|
| 271 |
++#define CLASS_MEM_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x104) |
|
| 272 |
++ |
|
| 273 |
++/* Internal Memory Access Read Data [31:0] */ |
|
| 274 |
++#define CLASS_MEM_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x108) |
|
| 275 |
++#define CLASS_TM_INQ_ADDR (CLASS_CSR_BASE_ADDR + 0x114) |
|
| 276 |
++#define CLASS_PE_STATUS (CLASS_CSR_BASE_ADDR + 0x118) |
|
| 277 |
++ |
|
| 278 |
++#define CLASS_PHY1_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x11c) |
|
| 279 |
++#define CLASS_PHY1_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x120) |
|
| 280 |
++#define CLASS_PHY1_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x124) |
|
| 281 |
++#define CLASS_PHY1_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x128) |
|
| 282 |
++#define CLASS_PHY1_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x12c) |
|
| 283 |
++#define CLASS_PHY1_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x130) |
|
| 284 |
++#define CLASS_PHY1_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x134) |
|
| 285 |
++#define CLASS_PHY1_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x138) |
|
| 286 |
++#define CLASS_PHY1_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x13c) |
|
| 287 |
++#define CLASS_PHY1_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x140) |
|
| 288 |
++#define CLASS_PHY2_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x144) |
|
| 289 |
++#define CLASS_PHY2_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x148) |
|
| 290 |
++#define CLASS_PHY2_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x14c) |
|
| 291 |
++#define CLASS_PHY2_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x150) |
|
| 292 |
++#define CLASS_PHY2_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x154) |
|
| 293 |
++#define CLASS_PHY2_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x158) |
|
| 294 |
++#define CLASS_PHY2_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x15c) |
|
| 295 |
++#define CLASS_PHY2_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x160) |
|
| 296 |
++#define CLASS_PHY2_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x164) |
|
| 297 |
++#define CLASS_PHY2_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x168) |
|
| 298 |
++#define CLASS_PHY3_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x16c) |
|
| 299 |
++#define CLASS_PHY3_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x170) |
|
| 300 |
++#define CLASS_PHY3_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x174) |
|
| 301 |
++#define CLASS_PHY3_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x178) |
|
| 302 |
++#define CLASS_PHY3_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x17c) |
|
| 303 |
++#define CLASS_PHY3_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x180) |
|
| 304 |
++#define CLASS_PHY3_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x184) |
|
| 305 |
++#define CLASS_PHY3_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x188) |
|
| 306 |
++#define CLASS_PHY3_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x18c) |
|
| 307 |
++#define CLASS_PHY3_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x190) |
|
| 308 |
++#define CLASS_PHY1_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x194) |
|
| 309 |
++#define CLASS_PHY1_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x198) |
|
| 310 |
++#define CLASS_PHY1_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x19c) |
|
| 311 |
++#define CLASS_PHY1_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a0) |
|
| 312 |
++#define CLASS_PHY2_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a4) |
|
| 313 |
++#define CLASS_PHY2_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a8) |
|
| 314 |
++#define CLASS_PHY2_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1ac) |
|
| 315 |
++#define CLASS_PHY2_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b0) |
|
| 316 |
++#define CLASS_PHY3_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b4) |
|
| 317 |
++#define CLASS_PHY3_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b8) |
|
| 318 |
++#define CLASS_PHY3_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1bc) |
|
| 319 |
++#define CLASS_PHY3_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c0) |
|
| 320 |
++#define CLASS_PHY4_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c4) |
|
| 321 |
++#define CLASS_PHY4_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c8) |
|
| 322 |
++#define CLASS_PHY4_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1cc) |
|
| 323 |
++#define CLASS_PHY4_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1d0) |
|
| 324 |
++#define CLASS_PHY4_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x1d4) |
|
| 325 |
++#define CLASS_PHY4_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x1d8) |
|
| 326 |
++#define CLASS_PHY4_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1dc) |
|
| 327 |
++#define CLASS_PHY4_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1e0) |
|
| 328 |
++#define CLASS_PHY4_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x1e4) |
|
| 329 |
++#define CLASS_PHY4_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1e8) |
|
| 330 |
++#define CLASS_PHY4_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x1ec) |
|
| 331 |
++#define CLASS_PHY4_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x1f0) |
|
| 332 |
++#define CLASS_PHY4_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x1f4) |
|
| 333 |
++#define CLASS_PHY4_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x1f8) |
|
| 334 |
++ |
|
| 335 |
++#define CLASS_PE_SYS_CLK_RATIO (CLASS_CSR_BASE_ADDR + 0x200) |
|
| 336 |
++#define CLASS_AFULL_THRES (CLASS_CSR_BASE_ADDR + 0x204) |
|
| 337 |
++#define CLASS_GAP_BETWEEN_READS (CLASS_CSR_BASE_ADDR + 0x208) |
|
| 338 |
++#define CLASS_MAX_BUF_CNT (CLASS_CSR_BASE_ADDR + 0x20c) |
|
| 339 |
++#define CLASS_TSQ_FIFO_THRES (CLASS_CSR_BASE_ADDR + 0x210) |
|
| 340 |
++#define CLASS_TSQ_MAX_CNT (CLASS_CSR_BASE_ADDR + 0x214) |
|
| 341 |
++#define CLASS_IRAM_DATA_0 (CLASS_CSR_BASE_ADDR + 0x218) |
|
| 342 |
++#define CLASS_IRAM_DATA_1 (CLASS_CSR_BASE_ADDR + 0x21c) |
|
| 343 |
++#define CLASS_IRAM_DATA_2 (CLASS_CSR_BASE_ADDR + 0x220) |
|
| 344 |
++#define CLASS_IRAM_DATA_3 (CLASS_CSR_BASE_ADDR + 0x224) |
|
| 345 |
++ |
|
| 346 |
++#define CLASS_BUS_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x228) |
|
| 347 |
++ |
|
| 348 |
++#define CLASS_BUS_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x22c) |
|
| 349 |
++#define CLASS_BUS_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x230) |
|
| 350 |
++ |
|
| 351 |
++/* (route_entry_size[9:0], route_hash_size[23:16] |
|
| 352 |
++ * (this is actually ln2(size))) |
|
| 353 |
++ */ |
|
| 354 |
++#define CLASS_ROUTE_HASH_ENTRY_SIZE (CLASS_CSR_BASE_ADDR + 0x234) |
|
| 355 |
++ |
|
| 356 |
++#define CLASS_ROUTE_ENTRY_SIZE(size) ((size) & 0x1ff) |
|
| 357 |
++#define CLASS_ROUTE_HASH_SIZE(hash_bits) (((hash_bits) & 0xff) << 16) |
|
| 358 |
++ |
|
| 359 |
++#define CLASS_ROUTE_TABLE_BASE (CLASS_CSR_BASE_ADDR + 0x238) |
|
| 360 |
++ |
|
| 361 |
++#define CLASS_ROUTE_MULTI (CLASS_CSR_BASE_ADDR + 0x23c) |
|
| 362 |
++#define CLASS_SMEM_OFFSET (CLASS_CSR_BASE_ADDR + 0x240) |
|
| 363 |
++#define CLASS_LMEM_BUF_SIZE (CLASS_CSR_BASE_ADDR + 0x244) |
|
| 364 |
++#define CLASS_VLAN_ID (CLASS_CSR_BASE_ADDR + 0x248) |
|
| 365 |
++#define CLASS_BMU1_BUF_FREE (CLASS_CSR_BASE_ADDR + 0x24c) |
|
| 366 |
++#define CLASS_USE_TMU_INQ (CLASS_CSR_BASE_ADDR + 0x250) |
|
| 367 |
++#define CLASS_VLAN_ID1 (CLASS_CSR_BASE_ADDR + 0x254) |
|
| 368 |
++ |
|
| 369 |
++#define CLASS_BUS_ACCESS_BASE (CLASS_CSR_BASE_ADDR + 0x258) |
|
| 370 |
++#define CLASS_BUS_ACCESS_BASE_MASK (0xFF000000) |
|
| 371 |
++/* bit 31:24 of PE peripheral address are stored in CLASS_BUS_ACCESS_BASE */ |
|
| 372 |
++ |
|
| 373 |
++#define CLASS_HIF_PARSE (CLASS_CSR_BASE_ADDR + 0x25c) |
|
| 374 |
++ |
|
| 375 |
++#define CLASS_HOST_PE0_GP (CLASS_CSR_BASE_ADDR + 0x260) |
|
| 376 |
++#define CLASS_PE0_GP (CLASS_CSR_BASE_ADDR + 0x264) |
|
| 377 |
++#define CLASS_HOST_PE1_GP (CLASS_CSR_BASE_ADDR + 0x268) |
|
| 378 |
++#define CLASS_PE1_GP (CLASS_CSR_BASE_ADDR + 0x26c) |
|
| 379 |
++#define CLASS_HOST_PE2_GP (CLASS_CSR_BASE_ADDR + 0x270) |
|
| 380 |
++#define CLASS_PE2_GP (CLASS_CSR_BASE_ADDR + 0x274) |
|
| 381 |
++#define CLASS_HOST_PE3_GP (CLASS_CSR_BASE_ADDR + 0x278) |
|
| 382 |
++#define CLASS_PE3_GP (CLASS_CSR_BASE_ADDR + 0x27c) |
|
| 383 |
++#define CLASS_HOST_PE4_GP (CLASS_CSR_BASE_ADDR + 0x280) |
|
| 384 |
++#define CLASS_PE4_GP (CLASS_CSR_BASE_ADDR + 0x284) |
|
| 385 |
++#define CLASS_HOST_PE5_GP (CLASS_CSR_BASE_ADDR + 0x288) |
|
| 386 |
++#define CLASS_PE5_GP (CLASS_CSR_BASE_ADDR + 0x28c) |
|
| 387 |
++ |
|
| 388 |
++#define CLASS_PE_INT_SRC (CLASS_CSR_BASE_ADDR + 0x290) |
|
| 389 |
++#define CLASS_PE_INT_ENABLE (CLASS_CSR_BASE_ADDR + 0x294) |
|
| 390 |
++ |
|
| 391 |
++#define CLASS_TPID0_TPID1 (CLASS_CSR_BASE_ADDR + 0x298) |
|
| 392 |
++#define CLASS_TPID2 (CLASS_CSR_BASE_ADDR + 0x29c) |
|
| 393 |
++ |
|
| 394 |
++#define CLASS_L4_CHKSUM_ADDR (CLASS_CSR_BASE_ADDR + 0x2a0) |
|
| 395 |
++ |
|
| 396 |
++#define CLASS_PE0_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a4) |
|
| 397 |
++#define CLASS_PE1_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a8) |
|
| 398 |
++#define CLASS_PE2_DEBUG (CLASS_CSR_BASE_ADDR + 0x2ac) |
|
| 399 |
++#define CLASS_PE3_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b0) |
|
| 400 |
++#define CLASS_PE4_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b4) |
|
| 401 |
++#define CLASS_PE5_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b8) |
|
| 402 |
++ |
|
| 403 |
++#define CLASS_STATE (CLASS_CSR_BASE_ADDR + 0x2bc) |
|
| 404 |
++ |
|
| 405 |
++/* CLASS defines */ |
|
| 406 |
++#define CLASS_PBUF_SIZE 0x100 /* Fixed by hardware */ |
|
| 407 |
++#define CLASS_PBUF_HEADER_OFFSET 0x80 /* Can be configured */ |
|
| 408 |
++ |
|
| 409 |
++/* Can be configured */ |
|
| 410 |
++#define CLASS_PBUF0_BASE_ADDR 0x000 |
|
| 411 |
++/* Can be configured */ |
|
| 412 |
++#define CLASS_PBUF1_BASE_ADDR (CLASS_PBUF0_BASE_ADDR + CLASS_PBUF_SIZE) |
|
| 413 |
++/* Can be configured */ |
|
| 414 |
++#define CLASS_PBUF2_BASE_ADDR (CLASS_PBUF1_BASE_ADDR + CLASS_PBUF_SIZE) |
|
| 415 |
++/* Can be configured */ |
|
| 416 |
++#define CLASS_PBUF3_BASE_ADDR (CLASS_PBUF2_BASE_ADDR + CLASS_PBUF_SIZE) |
|
| 417 |
++ |
|
| 418 |
++#define CLASS_PBUF0_HEADER_BASE_ADDR (CLASS_PBUF0_BASE_ADDR + \ |
|
| 419 |
++ CLASS_PBUF_HEADER_OFFSET) |
|
| 420 |
++#define CLASS_PBUF1_HEADER_BASE_ADDR (CLASS_PBUF1_BASE_ADDR + \ |
|
| 421 |
++ CLASS_PBUF_HEADER_OFFSET) |
|
| 422 |
++#define CLASS_PBUF2_HEADER_BASE_ADDR (CLASS_PBUF2_BASE_ADDR + \ |
|
| 423 |
++ CLASS_PBUF_HEADER_OFFSET) |
|
| 424 |
++#define CLASS_PBUF3_HEADER_BASE_ADDR (CLASS_PBUF3_BASE_ADDR + \ |
|
| 425 |
++ CLASS_PBUF_HEADER_OFFSET) |
|
| 426 |
++ |
|
| 427 |
++#define CLASS_PE0_RO_DM_ADDR0_VAL ((CLASS_PBUF1_BASE_ADDR << 16) | \ |
|
| 428 |
++ CLASS_PBUF0_BASE_ADDR) |
|
| 429 |
++#define CLASS_PE0_RO_DM_ADDR1_VAL ((CLASS_PBUF3_BASE_ADDR << 16) | \ |
|
| 430 |
++ CLASS_PBUF2_BASE_ADDR) |
|
| 431 |
++ |
|
| 432 |
++#define CLASS_PE0_QB_DM_ADDR0_VAL ((CLASS_PBUF1_HEADER_BASE_ADDR << 16) |\ |
|
| 433 |
++ CLASS_PBUF0_HEADER_BASE_ADDR) |
|
| 434 |
++#define CLASS_PE0_QB_DM_ADDR1_VAL ((CLASS_PBUF3_HEADER_BASE_ADDR << 16) |\ |
|
| 435 |
++ CLASS_PBUF2_HEADER_BASE_ADDR) |
|
| 436 |
++ |
|
| 437 |
++#define CLASS_ROUTE_SIZE 128 |
|
| 438 |
++#define CLASS_MAX_ROUTE_SIZE 256 |
|
| 439 |
++#define CLASS_ROUTE_HASH_BITS 20 |
|
| 440 |
++#define CLASS_ROUTE_HASH_MASK (BIT(CLASS_ROUTE_HASH_BITS) - 1) |
|
| 441 |
++ |
|
| 442 |
++/* Can be configured */ |
|
| 443 |
++#define CLASS_ROUTE0_BASE_ADDR 0x400 |
|
| 444 |
++/* Can be configured */ |
|
| 445 |
++#define CLASS_ROUTE1_BASE_ADDR (CLASS_ROUTE0_BASE_ADDR + CLASS_ROUTE_SIZE) |
|
| 446 |
++/* Can be configured */ |
|
| 447 |
++#define CLASS_ROUTE2_BASE_ADDR (CLASS_ROUTE1_BASE_ADDR + CLASS_ROUTE_SIZE) |
|
| 448 |
++/* Can be configured */ |
|
| 449 |
++#define CLASS_ROUTE3_BASE_ADDR (CLASS_ROUTE2_BASE_ADDR + CLASS_ROUTE_SIZE) |
|
| 450 |
++ |
|
| 451 |
++#define CLASS_SA_SIZE 128 |
|
| 452 |
++#define CLASS_IPSEC_SA0_BASE_ADDR 0x600 |
|
| 453 |
++/* not used */ |
|
| 454 |
++#define CLASS_IPSEC_SA1_BASE_ADDR (CLASS_IPSEC_SA0_BASE_ADDR + CLASS_SA_SIZE) |
|
| 455 |
++/* not used */ |
|
| 456 |
++#define CLASS_IPSEC_SA2_BASE_ADDR (CLASS_IPSEC_SA1_BASE_ADDR + CLASS_SA_SIZE) |
|
| 457 |
++/* not used */ |
|
| 458 |
++#define CLASS_IPSEC_SA3_BASE_ADDR (CLASS_IPSEC_SA2_BASE_ADDR + CLASS_SA_SIZE) |
|
| 459 |
++ |
|
| 460 |
++/* generic purpose free dmem buffer, last portion of 2K dmem pbuf */ |
|
| 461 |
++#define CLASS_GP_DMEM_BUF_SIZE (2048 - (CLASS_PBUF_SIZE * 4) - \ |
|
| 462 |
++ (CLASS_ROUTE_SIZE * 4) - (CLASS_SA_SIZE)) |
|
| 463 |
++#define CLASS_GP_DMEM_BUF ((void *)(CLASS_IPSEC_SA0_BASE_ADDR + \ |
|
| 464 |
++ CLASS_SA_SIZE)) |
|
| 465 |
++ |
|
| 466 |
++#define TWO_LEVEL_ROUTE BIT(0) |
|
| 467 |
++#define PHYNO_IN_HASH BIT(1) |
|
| 468 |
++#define HW_ROUTE_FETCH BIT(3) |
|
| 469 |
++#define HW_BRIDGE_FETCH BIT(5) |
|
| 470 |
++#define IP_ALIGNED BIT(6) |
|
| 471 |
++#define ARC_HIT_CHECK_EN BIT(7) |
|
| 472 |
++#define CLASS_TOE BIT(11) |
|
| 473 |
++#define HASH_NORMAL (0 << 12) |
|
| 474 |
++#define HASH_CRC_PORT BIT(12) |
|
| 475 |
++#define HASH_CRC_IP (2 << 12) |
|
| 476 |
++#define HASH_CRC_PORT_IP (3 << 12) |
|
| 477 |
++#define QB2BUS_LE BIT(15) |
|
| 478 |
++ |
|
| 479 |
++#define TCP_CHKSUM_DROP BIT(0) |
|
| 480 |
++#define UDP_CHKSUM_DROP BIT(1) |
|
| 481 |
++#define IPV4_CHKSUM_DROP BIT(9) |
|
| 482 |
++ |
|
| 483 |
++/*CLASS_HIF_PARSE bits*/ |
|
| 484 |
++#define HIF_PKT_CLASS_EN BIT(0) |
|
| 485 |
++#define HIF_PKT_OFFSET(ofst) (((ofst) & 0xF) << 1) |
|
| 486 |
++ |
|
| 487 |
++struct class_cfg {
|
|
| 488 |
++ u32 toe_mode; |
|
| 489 |
++ unsigned long route_table_baseaddr; |
|
| 490 |
++ u32 route_table_hash_bits; |
|
| 491 |
++ u32 pe_sys_clk_ratio; |
|
| 492 |
++ u32 resume; |
|
| 493 |
++}; |
|
| 494 |
++ |
|
| 495 |
++#endif /* _CLASS_CSR_H_ */ |
|
| 496 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h b/drivers/staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h |
|
| 497 |
+new file mode 100644 |
|
| 498 |
+index 000000000000..9c5d7919455d |
|
| 499 |
+--- /dev/null |
|
| 500 |
+@@ -0,0 +1,242 @@ |
|
| 501 |
++/* |
|
| 502 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 503 |
++ * Copyright 2017 NXP |
|
| 504 |
++ * |
|
| 505 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 506 |
++ * it under the terms of the GNU General Public License as published by |
|
| 507 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 508 |
++ * (at your option) any later version. |
|
| 509 |
++ * |
|
| 510 |
++ * This program is distributed in the hope that it will be useful, |
|
| 511 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 512 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 513 |
++ * GNU General Public License for more details. |
|
| 514 |
++ * |
|
| 515 |
++ * You should have received a copy of the GNU General Public License |
|
| 516 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 517 |
++ */ |
|
| 518 |
++ |
|
| 519 |
++#ifndef _EMAC_H_ |
|
| 520 |
++#define _EMAC_H_ |
|
| 521 |
++ |
|
| 522 |
++#include <linux/ethtool.h> |
|
| 523 |
++ |
|
| 524 |
++#define EMAC_IEVENT_REG 0x004 |
|
| 525 |
++#define EMAC_IMASK_REG 0x008 |
|
| 526 |
++#define EMAC_R_DES_ACTIVE_REG 0x010 |
|
| 527 |
++#define EMAC_X_DES_ACTIVE_REG 0x014 |
|
| 528 |
++#define EMAC_ECNTRL_REG 0x024 |
|
| 529 |
++#define EMAC_MII_DATA_REG 0x040 |
|
| 530 |
++#define EMAC_MII_CTRL_REG 0x044 |
|
| 531 |
++#define EMAC_MIB_CTRL_STS_REG 0x064 |
|
| 532 |
++#define EMAC_RCNTRL_REG 0x084 |
|
| 533 |
++#define EMAC_TCNTRL_REG 0x0C4 |
|
| 534 |
++#define EMAC_PHY_ADDR_LOW 0x0E4 |
|
| 535 |
++#define EMAC_PHY_ADDR_HIGH 0x0E8 |
|
| 536 |
++#define EMAC_GAUR 0x120 |
|
| 537 |
++#define EMAC_GALR 0x124 |
|
| 538 |
++#define EMAC_TFWR_STR_FWD 0x144 |
|
| 539 |
++#define EMAC_RX_SECTION_FULL 0x190 |
|
| 540 |
++#define EMAC_RX_SECTION_EMPTY 0x194 |
|
| 541 |
++#define EMAC_TX_SECTION_EMPTY 0x1A0 |
|
| 542 |
++#define EMAC_TRUNC_FL 0x1B0 |
|
| 543 |
++ |
|
| 544 |
++#define RMON_T_DROP 0x200 /* Count of frames not cntd correctly */ |
|
| 545 |
++#define RMON_T_PACKETS 0x204 /* RMON TX packet count */ |
|
| 546 |
++#define RMON_T_BC_PKT 0x208 /* RMON TX broadcast pkts */ |
|
| 547 |
++#define RMON_T_MC_PKT 0x20c /* RMON TX multicast pkts */ |
|
| 548 |
++#define RMON_T_CRC_ALIGN 0x210 /* RMON TX pkts with CRC align err */ |
|
| 549 |
++#define RMON_T_UNDERSIZE 0x214 /* RMON TX pkts < 64 bytes, good CRC */ |
|
| 550 |
++#define RMON_T_OVERSIZE 0x218 /* RMON TX pkts > MAX_FL bytes good CRC */ |
|
| 551 |
++#define RMON_T_FRAG 0x21c /* RMON TX pkts < 64 bytes, bad CRC */ |
|
| 552 |
++#define RMON_T_JAB 0x220 /* RMON TX pkts > MAX_FL bytes, bad CRC */ |
|
| 553 |
++#define RMON_T_COL 0x224 /* RMON TX collision count */ |
|
| 554 |
++#define RMON_T_P64 0x228 /* RMON TX 64 byte pkts */ |
|
| 555 |
++#define RMON_T_P65TO127 0x22c /* RMON TX 65 to 127 byte pkts */ |
|
| 556 |
++#define RMON_T_P128TO255 0x230 /* RMON TX 128 to 255 byte pkts */ |
|
| 557 |
++#define RMON_T_P256TO511 0x234 /* RMON TX 256 to 511 byte pkts */ |
|
| 558 |
++#define RMON_T_P512TO1023 0x238 /* RMON TX 512 to 1023 byte pkts */ |
|
| 559 |
++#define RMON_T_P1024TO2047 0x23c /* RMON TX 1024 to 2047 byte pkts */ |
|
| 560 |
++#define RMON_T_P_GTE2048 0x240 /* RMON TX pkts > 2048 bytes */ |
|
| 561 |
++#define RMON_T_OCTETS 0x244 /* RMON TX octets */ |
|
| 562 |
++#define IEEE_T_DROP 0x248 /* Count of frames not counted crtly */ |
|
| 563 |
++#define IEEE_T_FRAME_OK 0x24c /* Frames tx'd OK */ |
|
| 564 |
++#define IEEE_T_1COL 0x250 /* Frames tx'd with single collision */ |
|
| 565 |
++#define IEEE_T_MCOL 0x254 /* Frames tx'd with multiple collision */ |
|
| 566 |
++#define IEEE_T_DEF 0x258 /* Frames tx'd after deferral delay */ |
|
| 567 |
++#define IEEE_T_LCOL 0x25c /* Frames tx'd with late collision */ |
|
| 568 |
++#define IEEE_T_EXCOL 0x260 /* Frames tx'd with excesv collisions */ |
|
| 569 |
++#define IEEE_T_MACERR 0x264 /* Frames tx'd with TX FIFO underrun */ |
|
| 570 |
++#define IEEE_T_CSERR 0x268 /* Frames tx'd with carrier sense err */ |
|
| 571 |
++#define IEEE_T_SQE 0x26c /* Frames tx'd with SQE err */ |
|
| 572 |
++#define IEEE_T_FDXFC 0x270 /* Flow control pause frames tx'd */ |
|
| 573 |
++#define IEEE_T_OCTETS_OK 0x274 /* Octet count for frames tx'd w/o err */ |
|
| 574 |
++#define RMON_R_PACKETS 0x284 /* RMON RX packet count */ |
|
| 575 |
++#define RMON_R_BC_PKT 0x288 /* RMON RX broadcast pkts */ |
|
| 576 |
++#define RMON_R_MC_PKT 0x28c /* RMON RX multicast pkts */ |
|
| 577 |
++#define RMON_R_CRC_ALIGN 0x290 /* RMON RX pkts with CRC alignment err */ |
|
| 578 |
++#define RMON_R_UNDERSIZE 0x294 /* RMON RX pkts < 64 bytes, good CRC */ |
|
| 579 |
++#define RMON_R_OVERSIZE 0x298 /* RMON RX pkts > MAX_FL bytes good CRC */ |
|
| 580 |
++#define RMON_R_FRAG 0x29c /* RMON RX pkts < 64 bytes, bad CRC */ |
|
| 581 |
++#define RMON_R_JAB 0x2a0 /* RMON RX pkts > MAX_FL bytes, bad CRC */ |
|
| 582 |
++#define RMON_R_RESVD_O 0x2a4 /* Reserved */ |
|
| 583 |
++#define RMON_R_P64 0x2a8 /* RMON RX 64 byte pkts */ |
|
| 584 |
++#define RMON_R_P65TO127 0x2ac /* RMON RX 65 to 127 byte pkts */ |
|
| 585 |
++#define RMON_R_P128TO255 0x2b0 /* RMON RX 128 to 255 byte pkts */ |
|
| 586 |
++#define RMON_R_P256TO511 0x2b4 /* RMON RX 256 to 511 byte pkts */ |
|
| 587 |
++#define RMON_R_P512TO1023 0x2b8 /* RMON RX 512 to 1023 byte pkts */ |
|
| 588 |
++#define RMON_R_P1024TO2047 0x2bc /* RMON RX 1024 to 2047 byte pkts */ |
|
| 589 |
++#define RMON_R_P_GTE2048 0x2c0 /* RMON RX pkts > 2048 bytes */ |
|
| 590 |
++#define RMON_R_OCTETS 0x2c4 /* RMON RX octets */ |
|
| 591 |
++#define IEEE_R_DROP 0x2c8 /* Count frames not counted correctly */ |
|
| 592 |
++#define IEEE_R_FRAME_OK 0x2cc /* Frames rx'd OK */ |
|
| 593 |
++#define IEEE_R_CRC 0x2d0 /* Frames rx'd with CRC err */ |
|
| 594 |
++#define IEEE_R_ALIGN 0x2d4 /* Frames rx'd with alignment err */ |
|
| 595 |
++#define IEEE_R_MACERR 0x2d8 /* Receive FIFO overflow count */ |
|
| 596 |
++#define IEEE_R_FDXFC 0x2dc /* Flow control pause frames rx'd */ |
|
| 597 |
++#define IEEE_R_OCTETS_OK 0x2e0 /* Octet cnt for frames rx'd w/o err */ |
|
| 598 |
++ |
|
| 599 |
++#define EMAC_SMAC_0_0 0x500 /*Supplemental MAC Address 0 (RW).*/ |
|
| 600 |
++#define EMAC_SMAC_0_1 0x504 /*Supplemental MAC Address 0 (RW).*/ |
|
| 601 |
++ |
|
| 602 |
++/* GEMAC definitions and settings */ |
|
| 603 |
++ |
|
| 604 |
++#define EMAC_PORT_0 0 |
|
| 605 |
++#define EMAC_PORT_1 1 |
|
| 606 |
++ |
|
| 607 |
++/* GEMAC Bit definitions */ |
|
| 608 |
++#define EMAC_IEVENT_HBERR 0x80000000 |
|
| 609 |
++#define EMAC_IEVENT_BABR 0x40000000 |
|
| 610 |
++#define EMAC_IEVENT_BABT 0x20000000 |
|
| 611 |
++#define EMAC_IEVENT_GRA 0x10000000 |
|
| 612 |
++#define EMAC_IEVENT_TXF 0x08000000 |
|
| 613 |
++#define EMAC_IEVENT_TXB 0x04000000 |
|
| 614 |
++#define EMAC_IEVENT_RXF 0x02000000 |
|
| 615 |
++#define EMAC_IEVENT_RXB 0x01000000 |
|
| 616 |
++#define EMAC_IEVENT_MII 0x00800000 |
|
| 617 |
++#define EMAC_IEVENT_EBERR 0x00400000 |
|
| 618 |
++#define EMAC_IEVENT_LC 0x00200000 |
|
| 619 |
++#define EMAC_IEVENT_RL 0x00100000 |
|
| 620 |
++#define EMAC_IEVENT_UN 0x00080000 |
|
| 621 |
++ |
|
| 622 |
++#define EMAC_IMASK_HBERR 0x80000000 |
|
| 623 |
++#define EMAC_IMASK_BABR 0x40000000 |
|
| 624 |
++#define EMAC_IMASKT_BABT 0x20000000 |
|
| 625 |
++#define EMAC_IMASK_GRA 0x10000000 |
|
| 626 |
++#define EMAC_IMASKT_TXF 0x08000000 |
|
| 627 |
++#define EMAC_IMASK_TXB 0x04000000 |
|
| 628 |
++#define EMAC_IMASKT_RXF 0x02000000 |
|
| 629 |
++#define EMAC_IMASK_RXB 0x01000000 |
|
| 630 |
++#define EMAC_IMASK_MII 0x00800000 |
|
| 631 |
++#define EMAC_IMASK_EBERR 0x00400000 |
|
| 632 |
++#define EMAC_IMASK_LC 0x00200000 |
|
| 633 |
++#define EMAC_IMASKT_RL 0x00100000 |
|
| 634 |
++#define EMAC_IMASK_UN 0x00080000 |
|
| 635 |
++ |
|
| 636 |
++#define EMAC_RCNTRL_MAX_FL_SHIFT 16 |
|
| 637 |
++#define EMAC_RCNTRL_LOOP 0x00000001 |
|
| 638 |
++#define EMAC_RCNTRL_DRT 0x00000002 |
|
| 639 |
++#define EMAC_RCNTRL_MII_MODE 0x00000004 |
|
| 640 |
++#define EMAC_RCNTRL_PROM 0x00000008 |
|
| 641 |
++#define EMAC_RCNTRL_BC_REJ 0x00000010 |
|
| 642 |
++#define EMAC_RCNTRL_FCE 0x00000020 |
|
| 643 |
++#define EMAC_RCNTRL_RGMII 0x00000040 |
|
| 644 |
++#define EMAC_RCNTRL_SGMII 0x00000080 |
|
| 645 |
++#define EMAC_RCNTRL_RMII 0x00000100 |
|
| 646 |
++#define EMAC_RCNTRL_RMII_10T 0x00000200 |
|
| 647 |
++#define EMAC_RCNTRL_CRC_FWD 0x00004000 |
|
| 648 |
++ |
|
| 649 |
++#define EMAC_TCNTRL_GTS 0x00000001 |
|
| 650 |
++#define EMAC_TCNTRL_HBC 0x00000002 |
|
| 651 |
++#define EMAC_TCNTRL_FDEN 0x00000004 |
|
| 652 |
++#define EMAC_TCNTRL_TFC_PAUSE 0x00000008 |
|
| 653 |
++#define EMAC_TCNTRL_RFC_PAUSE 0x00000010 |
|
| 654 |
++ |
|
| 655 |
++#define EMAC_ECNTRL_RESET 0x00000001 /* reset the EMAC */ |
|
| 656 |
++#define EMAC_ECNTRL_ETHER_EN 0x00000002 /* enable the EMAC */ |
|
| 657 |
++#define EMAC_ECNTRL_MAGIC_ENA 0x00000004 |
|
| 658 |
++#define EMAC_ECNTRL_SLEEP 0x00000008 |
|
| 659 |
++#define EMAC_ECNTRL_SPEED 0x00000020 |
|
| 660 |
++#define EMAC_ECNTRL_DBSWAP 0x00000100 |
|
| 661 |
++ |
|
| 662 |
++#define EMAC_X_WMRK_STRFWD 0x00000100 |
|
| 663 |
++ |
|
| 664 |
++#define EMAC_X_DES_ACTIVE_TDAR 0x01000000 |
|
| 665 |
++#define EMAC_R_DES_ACTIVE_RDAR 0x01000000 |
|
| 666 |
++ |
|
| 667 |
++#define EMAC_RX_SECTION_EMPTY_V 0x00010006 |
|
| 668 |
++/* |
|
| 669 |
++ * The possible operating speeds of the MAC, currently supporting 10, 100 and |
|
| 670 |
++ * 1000Mb modes. |
|
| 671 |
++ */ |
|
| 672 |
++enum mac_speed {SPEED_10M, SPEED_100M, SPEED_1000M, SPEED_1000M_PCS};
|
|
| 673 |
++ |
|
| 674 |
++/* MII-related definitios */ |
|
| 675 |
++#define EMAC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */ |
|
| 676 |
++#define EMAC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */ |
|
| 677 |
++#define EMAC_MII_DATA_OP_CL45_RD 0x30000000 /* Perform a read operation */ |
|
| 678 |
++#define EMAC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */ |
|
| 679 |
++#define EMAC_MII_DATA_OP_CL45_WR 0x10000000 /* Perform a write operation */ |
|
| 680 |
++#define EMAC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */ |
|
| 681 |
++#define EMAC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */ |
|
| 682 |
++#define EMAC_MII_DATA_TA 0x00020000 /* Turnaround */ |
|
| 683 |
++#define EMAC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */ |
|
| 684 |
++ |
|
| 685 |
++#define EMAC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */ |
|
| 686 |
++#define EMAC_MII_DATA_RA_MASK 0x1F /* MII Register address mask */ |
|
| 687 |
++#define EMAC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */ |
|
| 688 |
++#define EMAC_MII_DATA_PA_MASK 0x1F /* MII PHY address mask */ |
|
| 689 |
++ |
|
| 690 |
++#define EMAC_MII_DATA_RA(v) (((v) & EMAC_MII_DATA_RA_MASK) << \ |
|
| 691 |
++ EMAC_MII_DATA_RA_SHIFT) |
|
| 692 |
++#define EMAC_MII_DATA_PA(v) (((v) & EMAC_MII_DATA_RA_MASK) << \ |
|
| 693 |
++ EMAC_MII_DATA_PA_SHIFT) |
|
| 694 |
++#define EMAC_MII_DATA(v) ((v) & 0xffff) |
|
| 695 |
++ |
|
| 696 |
++#define EMAC_MII_SPEED_SHIFT 1 |
|
| 697 |
++#define EMAC_HOLDTIME_SHIFT 8 |
|
| 698 |
++#define EMAC_HOLDTIME_MASK 0x7 |
|
| 699 |
++#define EMAC_HOLDTIME(v) (((v) & EMAC_HOLDTIME_MASK) << \ |
|
| 700 |
++ EMAC_HOLDTIME_SHIFT) |
|
| 701 |
++ |
|
| 702 |
++/* |
|
| 703 |
++ * The Address organisation for the MAC device. All addresses are split into |
|
| 704 |
++ * two 32-bit register fields. The first one (bottom) is the lower 32-bits of |
|
| 705 |
++ * the address and the other field are the high order bits - this may be 16-bits |
|
| 706 |
++ * in the case of MAC addresses, or 32-bits for the hash address. |
|
| 707 |
++ * In terms of memory storage, the first item (bottom) is assumed to be at a |
|
| 708 |
++ * lower address location than 'top'. i.e. top should be at address location of |
|
| 709 |
++ * 'bottom' + 4 bytes. |
|
| 710 |
++ */ |
|
| 711 |
++struct pfe_mac_addr {
|
|
| 712 |
++ u32 bottom; /* Lower 32-bits of address. */ |
|
| 713 |
++ u32 top; /* Upper 32-bits of address. */ |
|
| 714 |
++}; |
|
| 715 |
++ |
|
| 716 |
++/* |
|
| 717 |
++ * The following is the organisation of the address filters section of the MAC |
|
| 718 |
++ * registers. The Cadence MAC contains four possible specific address match |
|
| 719 |
++ * addresses, if an incoming frame corresponds to any one of these four |
|
| 720 |
++ * addresses then the frame will be copied to memory. |
|
| 721 |
++ * It is not necessary for all four of the address match registers to be |
|
| 722 |
++ * programmed, this is application dependent. |
|
| 723 |
++ */ |
|
| 724 |
++struct spec_addr {
|
|
| 725 |
++ struct pfe_mac_addr one; /* Specific address register 1. */ |
|
| 726 |
++ struct pfe_mac_addr two; /* Specific address register 2. */ |
|
| 727 |
++ struct pfe_mac_addr three; /* Specific address register 3. */ |
|
| 728 |
++ struct pfe_mac_addr four; /* Specific address register 4. */ |
|
| 729 |
++}; |
|
| 730 |
++ |
|
| 731 |
++struct gemac_cfg {
|
|
| 732 |
++ u32 mode; |
|
| 733 |
++ u32 speed; |
|
| 734 |
++ u32 duplex; |
|
| 735 |
++}; |
|
| 736 |
++ |
|
| 737 |
++/* EMAC Hash size */ |
|
| 738 |
++#define EMAC_HASH_REG_BITS 64 |
|
| 739 |
++ |
|
| 740 |
++#define EMAC_SPEC_ADDR_MAX 4 |
|
| 741 |
++ |
|
| 742 |
++#endif /* _EMAC_H_ */ |
|
| 743 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h b/drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h |
|
| 744 |
+new file mode 100644 |
|
| 745 |
+index 000000000000..7b295830f50b |
|
| 746 |
+--- /dev/null |
|
| 747 |
+@@ -0,0 +1,86 @@ |
|
| 748 |
++/* |
|
| 749 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 750 |
++ * Copyright 2017 NXP |
|
| 751 |
++ * |
|
| 752 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 753 |
++ * it under the terms of the GNU General Public License as published by |
|
| 754 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 755 |
++ * (at your option) any later version. |
|
| 756 |
++ * |
|
| 757 |
++ * This program is distributed in the hope that it will be useful, |
|
| 758 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 759 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 760 |
++ * GNU General Public License for more details. |
|
| 761 |
++ * |
|
| 762 |
++ * You should have received a copy of the GNU General Public License |
|
| 763 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 764 |
++ */ |
|
| 765 |
++ |
|
| 766 |
++#ifndef _GPI_H_ |
|
| 767 |
++#define _GPI_H_ |
|
| 768 |
++ |
|
| 769 |
++#define GPI_VERSION 0x00 |
|
| 770 |
++#define GPI_CTRL 0x04 |
|
| 771 |
++#define GPI_RX_CONFIG 0x08 |
|
| 772 |
++#define GPI_HDR_SIZE 0x0c |
|
| 773 |
++#define GPI_BUF_SIZE 0x10 |
|
| 774 |
++#define GPI_LMEM_ALLOC_ADDR 0x14 |
|
| 775 |
++#define GPI_LMEM_FREE_ADDR 0x18 |
|
| 776 |
++#define GPI_DDR_ALLOC_ADDR 0x1c |
|
| 777 |
++#define GPI_DDR_FREE_ADDR 0x20 |
|
| 778 |
++#define GPI_CLASS_ADDR 0x24 |
|
| 779 |
++#define GPI_DRX_FIFO 0x28 |
|
| 780 |
++#define GPI_TRX_FIFO 0x2c |
|
| 781 |
++#define GPI_INQ_PKTPTR 0x30 |
|
| 782 |
++#define GPI_DDR_DATA_OFFSET 0x34 |
|
| 783 |
++#define GPI_LMEM_DATA_OFFSET 0x38 |
|
| 784 |
++#define GPI_TMLF_TX 0x4c |
|
| 785 |
++#define GPI_DTX_ASEQ 0x50 |
|
| 786 |
++#define GPI_FIFO_STATUS 0x54 |
|
| 787 |
++#define GPI_FIFO_DEBUG 0x58 |
|
| 788 |
++#define GPI_TX_PAUSE_TIME 0x5c |
|
| 789 |
++#define GPI_LMEM_SEC_BUF_DATA_OFFSET 0x60 |
|
| 790 |
++#define GPI_DDR_SEC_BUF_DATA_OFFSET 0x64 |
|
| 791 |
++#define GPI_TOE_CHKSUM_EN 0x68 |
|
| 792 |
++#define GPI_OVERRUN_DROPCNT 0x6c |
|
| 793 |
++#define GPI_CSR_MTIP_PAUSE_REG 0x74 |
|
| 794 |
++#define GPI_CSR_MTIP_PAUSE_QUANTUM 0x78 |
|
| 795 |
++#define GPI_CSR_RX_CNT 0x7c |
|
| 796 |
++#define GPI_CSR_TX_CNT 0x80 |
|
| 797 |
++#define GPI_CSR_DEBUG1 0x84 |
|
| 798 |
++#define GPI_CSR_DEBUG2 0x88 |
|
| 799 |
++ |
|
| 800 |
++struct gpi_cfg {
|
|
| 801 |
++ u32 lmem_rtry_cnt; |
|
| 802 |
++ u32 tmlf_txthres; |
|
| 803 |
++ u32 aseq_len; |
|
| 804 |
++ u32 mtip_pause_reg; |
|
| 805 |
++}; |
|
| 806 |
++ |
|
| 807 |
++/* GPI commons defines */ |
|
| 808 |
++#define GPI_LMEM_BUF_EN 0x1 |
|
| 809 |
++#define GPI_DDR_BUF_EN 0x1 |
|
| 810 |
++ |
|
| 811 |
++/* EGPI 1 defines */ |
|
| 812 |
++#define EGPI1_LMEM_RTRY_CNT 0x40 |
|
| 813 |
++#define EGPI1_TMLF_TXTHRES 0xBC |
|
| 814 |
++#define EGPI1_ASEQ_LEN 0x50 |
|
| 815 |
++ |
|
| 816 |
++/* EGPI 2 defines */ |
|
| 817 |
++#define EGPI2_LMEM_RTRY_CNT 0x40 |
|
| 818 |
++#define EGPI2_TMLF_TXTHRES 0xBC |
|
| 819 |
++#define EGPI2_ASEQ_LEN 0x40 |
|
| 820 |
++ |
|
| 821 |
++/* EGPI 3 defines */ |
|
| 822 |
++#define EGPI3_LMEM_RTRY_CNT 0x40 |
|
| 823 |
++#define EGPI3_TMLF_TXTHRES 0xBC |
|
| 824 |
++#define EGPI3_ASEQ_LEN 0x40 |
|
| 825 |
++ |
|
| 826 |
++/* HGPI defines */ |
|
| 827 |
++#define HGPI_LMEM_RTRY_CNT 0x40 |
|
| 828 |
++#define HGPI_TMLF_TXTHRES 0xBC |
|
| 829 |
++#define HGPI_ASEQ_LEN 0x40 |
|
| 830 |
++ |
|
| 831 |
++#define EGPI_PAUSE_TIME 0x000007D0 |
|
| 832 |
++#define EGPI_PAUSE_ENABLE 0x40000000 |
|
| 833 |
++#endif /* _GPI_H_ */ |
|
| 834 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h b/drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h |
|
| 835 |
+new file mode 100644 |
|
| 836 |
+index 000000000000..71cf81a7910c |
|
| 837 |
+--- /dev/null |
|
| 838 |
+@@ -0,0 +1,100 @@ |
|
| 839 |
++/* |
|
| 840 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 841 |
++ * Copyright 2017 NXP |
|
| 842 |
++ * |
|
| 843 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 844 |
++ * it under the terms of the GNU General Public License as published by |
|
| 845 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 846 |
++ * (at your option) any later version. |
|
| 847 |
++ * |
|
| 848 |
++ * This program is distributed in the hope that it will be useful, |
|
| 849 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 850 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 851 |
++ * GNU General Public License for more details. |
|
| 852 |
++ * |
|
| 853 |
++ * You should have received a copy of the GNU General Public License |
|
| 854 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 855 |
++ */ |
|
| 856 |
++ |
|
| 857 |
++#ifndef _HIF_H_ |
|
| 858 |
++#define _HIF_H_ |
|
| 859 |
++ |
|
| 860 |
++/* @file hif.h. |
|
| 861 |
++ * hif - PFE hif block control and status register. |
|
| 862 |
++ * Mapped on CBUS and accessible from all PE's and ARM. |
|
| 863 |
++ */ |
|
| 864 |
++#define HIF_VERSION (HIF_BASE_ADDR + 0x00) |
|
| 865 |
++#define HIF_TX_CTRL (HIF_BASE_ADDR + 0x04) |
|
| 866 |
++#define HIF_TX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x08) |
|
| 867 |
++#define HIF_TX_ALLOC (HIF_BASE_ADDR + 0x0c) |
|
| 868 |
++#define HIF_TX_BDP_ADDR (HIF_BASE_ADDR + 0x10) |
|
| 869 |
++#define HIF_TX_STATUS (HIF_BASE_ADDR + 0x14) |
|
| 870 |
++#define HIF_RX_CTRL (HIF_BASE_ADDR + 0x20) |
|
| 871 |
++#define HIF_RX_BDP_ADDR (HIF_BASE_ADDR + 0x24) |
|
| 872 |
++#define HIF_RX_STATUS (HIF_BASE_ADDR + 0x30) |
|
| 873 |
++#define HIF_INT_SRC (HIF_BASE_ADDR + 0x34) |
|
| 874 |
++#define HIF_INT_ENABLE (HIF_BASE_ADDR + 0x38) |
|
| 875 |
++#define HIF_POLL_CTRL (HIF_BASE_ADDR + 0x3c) |
|
| 876 |
++#define HIF_RX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x40) |
|
| 877 |
++#define HIF_RX_ALLOC (HIF_BASE_ADDR + 0x44) |
|
| 878 |
++#define HIF_TX_DMA_STATUS (HIF_BASE_ADDR + 0x48) |
|
| 879 |
++#define HIF_RX_DMA_STATUS (HIF_BASE_ADDR + 0x4c) |
|
| 880 |
++#define HIF_INT_COAL (HIF_BASE_ADDR + 0x50) |
|
| 881 |
++ |
|
| 882 |
++/* HIF_INT_SRC/ HIF_INT_ENABLE control bits */ |
|
| 883 |
++#define HIF_INT BIT(0) |
|
| 884 |
++#define HIF_RXBD_INT BIT(1) |
|
| 885 |
++#define HIF_RXPKT_INT BIT(2) |
|
| 886 |
++#define HIF_TXBD_INT BIT(3) |
|
| 887 |
++#define HIF_TXPKT_INT BIT(4) |
|
| 888 |
++ |
|
| 889 |
++/* HIF_TX_CTRL bits */ |
|
| 890 |
++#define HIF_CTRL_DMA_EN BIT(0) |
|
| 891 |
++#define HIF_CTRL_BDP_POLL_CTRL_EN BIT(1) |
|
| 892 |
++#define HIF_CTRL_BDP_CH_START_WSTB BIT(2) |
|
| 893 |
++ |
|
| 894 |
++/* HIF_RX_STATUS bits */ |
|
| 895 |
++#define BDP_CSR_RX_DMA_ACTV BIT(16) |
|
| 896 |
++ |
|
| 897 |
++/* HIF_INT_ENABLE bits */ |
|
| 898 |
++#define HIF_INT_EN BIT(0) |
|
| 899 |
++#define HIF_RXBD_INT_EN BIT(1) |
|
| 900 |
++#define HIF_RXPKT_INT_EN BIT(2) |
|
| 901 |
++#define HIF_TXBD_INT_EN BIT(3) |
|
| 902 |
++#define HIF_TXPKT_INT_EN BIT(4) |
|
| 903 |
++ |
|
| 904 |
++/* HIF_POLL_CTRL bits*/ |
|
| 905 |
++#define HIF_RX_POLL_CTRL_CYCLE 0x0400 |
|
| 906 |
++#define HIF_TX_POLL_CTRL_CYCLE 0x0400 |
|
| 907 |
++ |
|
| 908 |
++/* HIF_INT_COAL bits*/ |
|
| 909 |
++#define HIF_INT_COAL_ENABLE BIT(31) |
|
| 910 |
++ |
|
| 911 |
++/* Buffer descriptor control bits */ |
|
| 912 |
++#define BD_CTRL_BUFLEN_MASK 0x3fff |
|
| 913 |
++#define BD_BUF_LEN(x) ((x) & BD_CTRL_BUFLEN_MASK) |
|
| 914 |
++#define BD_CTRL_CBD_INT_EN BIT(16) |
|
| 915 |
++#define BD_CTRL_PKT_INT_EN BIT(17) |
|
| 916 |
++#define BD_CTRL_LIFM BIT(18) |
|
| 917 |
++#define BD_CTRL_LAST_BD BIT(19) |
|
| 918 |
++#define BD_CTRL_DIR BIT(20) |
|
| 919 |
++#define BD_CTRL_LMEM_CPY BIT(21) /* Valid only for HIF_NOCPY */ |
|
| 920 |
++#define BD_CTRL_PKT_XFER BIT(24) |
|
| 921 |
++#define BD_CTRL_DESC_EN BIT(31) |
|
| 922 |
++#define BD_CTRL_PARSE_DISABLE BIT(25) |
|
| 923 |
++#define BD_CTRL_BRFETCH_DISABLE BIT(26) |
|
| 924 |
++#define BD_CTRL_RTFETCH_DISABLE BIT(27) |
|
| 925 |
++ |
|
| 926 |
++/* Buffer descriptor status bits*/ |
|
| 927 |
++#define BD_STATUS_CONN_ID(x) ((x) & 0xffff) |
|
| 928 |
++#define BD_STATUS_DIR_PROC_ID BIT(16) |
|
| 929 |
++#define BD_STATUS_CONN_ID_EN BIT(17) |
|
| 930 |
++#define BD_STATUS_PE2PROC_ID(x) (((x) & 7) << 18) |
|
| 931 |
++#define BD_STATUS_LE_DATA BIT(21) |
|
| 932 |
++#define BD_STATUS_CHKSUM_EN BIT(22) |
|
| 933 |
++ |
|
| 934 |
++/* HIF Buffer descriptor status bits */ |
|
| 935 |
++#define DIR_PROC_ID BIT(16) |
|
| 936 |
++#define PROC_ID(id) ((id) << 18) |
|
| 937 |
++ |
|
| 938 |
++#endif /* _HIF_H_ */ |
|
| 939 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h b/drivers/staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h |
|
| 940 |
+new file mode 100644 |
|
| 941 |
+index 000000000000..3d4d43ce9fe2 |
|
| 942 |
+--- /dev/null |
|
| 943 |
+@@ -0,0 +1,50 @@ |
|
| 944 |
++/* |
|
| 945 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 946 |
++ * Copyright 2017 NXP |
|
| 947 |
++ * |
|
| 948 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 949 |
++ * it under the terms of the GNU General Public License as published by |
|
| 950 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 951 |
++ * (at your option) any later version. |
|
| 952 |
++ * |
|
| 953 |
++ * This program is distributed in the hope that it will be useful, |
|
| 954 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 955 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 956 |
++ * GNU General Public License for more details. |
|
| 957 |
++ * |
|
| 958 |
++ * You should have received a copy of the GNU General Public License |
|
| 959 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 960 |
++ */ |
|
| 961 |
++ |
|
| 962 |
++#ifndef _HIF_NOCPY_H_ |
|
| 963 |
++#define _HIF_NOCPY_H_ |
|
| 964 |
++ |
|
| 965 |
++#define HIF_NOCPY_VERSION (HIF_NOCPY_BASE_ADDR + 0x00) |
|
| 966 |
++#define HIF_NOCPY_TX_CTRL (HIF_NOCPY_BASE_ADDR + 0x04) |
|
| 967 |
++#define HIF_NOCPY_TX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x08) |
|
| 968 |
++#define HIF_NOCPY_TX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x0c) |
|
| 969 |
++#define HIF_NOCPY_TX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x10) |
|
| 970 |
++#define HIF_NOCPY_TX_STATUS (HIF_NOCPY_BASE_ADDR + 0x14) |
|
| 971 |
++#define HIF_NOCPY_RX_CTRL (HIF_NOCPY_BASE_ADDR + 0x20) |
|
| 972 |
++#define HIF_NOCPY_RX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x24) |
|
| 973 |
++#define HIF_NOCPY_RX_STATUS (HIF_NOCPY_BASE_ADDR + 0x30) |
|
| 974 |
++#define HIF_NOCPY_INT_SRC (HIF_NOCPY_BASE_ADDR + 0x34) |
|
| 975 |
++#define HIF_NOCPY_INT_ENABLE (HIF_NOCPY_BASE_ADDR + 0x38) |
|
| 976 |
++#define HIF_NOCPY_POLL_CTRL (HIF_NOCPY_BASE_ADDR + 0x3c) |
|
| 977 |
++#define HIF_NOCPY_RX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x40) |
|
| 978 |
++#define HIF_NOCPY_RX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x44) |
|
| 979 |
++#define HIF_NOCPY_TX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x48) |
|
| 980 |
++#define HIF_NOCPY_RX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x4c) |
|
| 981 |
++#define HIF_NOCPY_RX_INQ0_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x50) |
|
| 982 |
++#define HIF_NOCPY_RX_INQ1_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x54) |
|
| 983 |
++#define HIF_NOCPY_TX_PORT_NO (HIF_NOCPY_BASE_ADDR + 0x60) |
|
| 984 |
++#define HIF_NOCPY_LMEM_ALLOC_ADDR (HIF_NOCPY_BASE_ADDR + 0x64) |
|
| 985 |
++#define HIF_NOCPY_CLASS_ADDR (HIF_NOCPY_BASE_ADDR + 0x68) |
|
| 986 |
++#define HIF_NOCPY_TMU_PORT0_ADDR (HIF_NOCPY_BASE_ADDR + 0x70) |
|
| 987 |
++#define HIF_NOCPY_TMU_PORT1_ADDR (HIF_NOCPY_BASE_ADDR + 0x74) |
|
| 988 |
++#define HIF_NOCPY_TMU_PORT2_ADDR (HIF_NOCPY_BASE_ADDR + 0x7c) |
|
| 989 |
++#define HIF_NOCPY_TMU_PORT3_ADDR (HIF_NOCPY_BASE_ADDR + 0x80) |
|
| 990 |
++#define HIF_NOCPY_TMU_PORT4_ADDR (HIF_NOCPY_BASE_ADDR + 0x84) |
|
| 991 |
++#define HIF_NOCPY_INT_COAL (HIF_NOCPY_BASE_ADDR + 0x90) |
|
| 992 |
++ |
|
| 993 |
++#endif /* _HIF_NOCPY_H_ */ |
|
| 994 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h b/drivers/staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h |
|
| 995 |
+new file mode 100644 |
|
| 996 |
+index 000000000000..05f3d681d1a4 |
|
| 997 |
+--- /dev/null |
|
| 998 |
+@@ -0,0 +1,168 @@ |
|
| 999 |
++/* |
|
| 1000 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 1001 |
++ * Copyright 2017 NXP |
|
| 1002 |
++ * |
|
| 1003 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 1004 |
++ * it under the terms of the GNU General Public License as published by |
|
| 1005 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 1006 |
++ * (at your option) any later version. |
|
| 1007 |
++ * |
|
| 1008 |
++ * This program is distributed in the hope that it will be useful, |
|
| 1009 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 1010 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 1011 |
++ * GNU General Public License for more details. |
|
| 1012 |
++ * |
|
| 1013 |
++ * You should have received a copy of the GNU General Public License |
|
| 1014 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 1015 |
++ */ |
|
| 1016 |
++ |
|
| 1017 |
++#ifndef _TMU_CSR_H_ |
|
| 1018 |
++#define _TMU_CSR_H_ |
|
| 1019 |
++ |
|
| 1020 |
++#define TMU_VERSION (TMU_CSR_BASE_ADDR + 0x000) |
|
| 1021 |
++#define TMU_INQ_WATERMARK (TMU_CSR_BASE_ADDR + 0x004) |
|
| 1022 |
++#define TMU_PHY_INQ_PKTPTR (TMU_CSR_BASE_ADDR + 0x008) |
|
| 1023 |
++#define TMU_PHY_INQ_PKTINFO (TMU_CSR_BASE_ADDR + 0x00c) |
|
| 1024 |
++#define TMU_PHY_INQ_FIFO_CNT (TMU_CSR_BASE_ADDR + 0x010) |
|
| 1025 |
++#define TMU_SYS_GENERIC_CONTROL (TMU_CSR_BASE_ADDR + 0x014) |
|
| 1026 |
++#define TMU_SYS_GENERIC_STATUS (TMU_CSR_BASE_ADDR + 0x018) |
|
| 1027 |
++#define TMU_SYS_GEN_CON0 (TMU_CSR_BASE_ADDR + 0x01c) |
|
| 1028 |
++#define TMU_SYS_GEN_CON1 (TMU_CSR_BASE_ADDR + 0x020) |
|
| 1029 |
++#define TMU_SYS_GEN_CON2 (TMU_CSR_BASE_ADDR + 0x024) |
|
| 1030 |
++#define TMU_SYS_GEN_CON3 (TMU_CSR_BASE_ADDR + 0x028) |
|
| 1031 |
++#define TMU_SYS_GEN_CON4 (TMU_CSR_BASE_ADDR + 0x02c) |
|
| 1032 |
++#define TMU_TEQ_DISABLE_DROPCHK (TMU_CSR_BASE_ADDR + 0x030) |
|
| 1033 |
++#define TMU_TEQ_CTRL (TMU_CSR_BASE_ADDR + 0x034) |
|
| 1034 |
++#define TMU_TEQ_QCFG (TMU_CSR_BASE_ADDR + 0x038) |
|
| 1035 |
++#define TMU_TEQ_DROP_STAT (TMU_CSR_BASE_ADDR + 0x03c) |
|
| 1036 |
++#define TMU_TEQ_QAVG (TMU_CSR_BASE_ADDR + 0x040) |
|
| 1037 |
++#define TMU_TEQ_WREG_PROB (TMU_CSR_BASE_ADDR + 0x044) |
|
| 1038 |
++#define TMU_TEQ_TRANS_STAT (TMU_CSR_BASE_ADDR + 0x048) |
|
| 1039 |
++#define TMU_TEQ_HW_PROB_CFG0 (TMU_CSR_BASE_ADDR + 0x04c) |
|
| 1040 |
++#define TMU_TEQ_HW_PROB_CFG1 (TMU_CSR_BASE_ADDR + 0x050) |
|
| 1041 |
++#define TMU_TEQ_HW_PROB_CFG2 (TMU_CSR_BASE_ADDR + 0x054) |
|
| 1042 |
++#define TMU_TEQ_HW_PROB_CFG3 (TMU_CSR_BASE_ADDR + 0x058) |
|
| 1043 |
++#define TMU_TEQ_HW_PROB_CFG4 (TMU_CSR_BASE_ADDR + 0x05c) |
|
| 1044 |
++#define TMU_TEQ_HW_PROB_CFG5 (TMU_CSR_BASE_ADDR + 0x060) |
|
| 1045 |
++#define TMU_TEQ_HW_PROB_CFG6 (TMU_CSR_BASE_ADDR + 0x064) |
|
| 1046 |
++#define TMU_TEQ_HW_PROB_CFG7 (TMU_CSR_BASE_ADDR + 0x068) |
|
| 1047 |
++#define TMU_TEQ_HW_PROB_CFG8 (TMU_CSR_BASE_ADDR + 0x06c) |
|
| 1048 |
++#define TMU_TEQ_HW_PROB_CFG9 (TMU_CSR_BASE_ADDR + 0x070) |
|
| 1049 |
++#define TMU_TEQ_HW_PROB_CFG10 (TMU_CSR_BASE_ADDR + 0x074) |
|
| 1050 |
++#define TMU_TEQ_HW_PROB_CFG11 (TMU_CSR_BASE_ADDR + 0x078) |
|
| 1051 |
++#define TMU_TEQ_HW_PROB_CFG12 (TMU_CSR_BASE_ADDR + 0x07c) |
|
| 1052 |
++#define TMU_TEQ_HW_PROB_CFG13 (TMU_CSR_BASE_ADDR + 0x080) |
|
| 1053 |
++#define TMU_TEQ_HW_PROB_CFG14 (TMU_CSR_BASE_ADDR + 0x084) |
|
| 1054 |
++#define TMU_TEQ_HW_PROB_CFG15 (TMU_CSR_BASE_ADDR + 0x088) |
|
| 1055 |
++#define TMU_TEQ_HW_PROB_CFG16 (TMU_CSR_BASE_ADDR + 0x08c) |
|
| 1056 |
++#define TMU_TEQ_HW_PROB_CFG17 (TMU_CSR_BASE_ADDR + 0x090) |
|
| 1057 |
++#define TMU_TEQ_HW_PROB_CFG18 (TMU_CSR_BASE_ADDR + 0x094) |
|
| 1058 |
++#define TMU_TEQ_HW_PROB_CFG19 (TMU_CSR_BASE_ADDR + 0x098) |
|
| 1059 |
++#define TMU_TEQ_HW_PROB_CFG20 (TMU_CSR_BASE_ADDR + 0x09c) |
|
| 1060 |
++#define TMU_TEQ_HW_PROB_CFG21 (TMU_CSR_BASE_ADDR + 0x0a0) |
|
| 1061 |
++#define TMU_TEQ_HW_PROB_CFG22 (TMU_CSR_BASE_ADDR + 0x0a4) |
|
| 1062 |
++#define TMU_TEQ_HW_PROB_CFG23 (TMU_CSR_BASE_ADDR + 0x0a8) |
|
| 1063 |
++#define TMU_TEQ_HW_PROB_CFG24 (TMU_CSR_BASE_ADDR + 0x0ac) |
|
| 1064 |
++#define TMU_TEQ_HW_PROB_CFG25 (TMU_CSR_BASE_ADDR + 0x0b0) |
|
| 1065 |
++#define TMU_TDQ_IIFG_CFG (TMU_CSR_BASE_ADDR + 0x0b4) |
|
| 1066 |
++/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. |
|
| 1067 |
++ * This is a global Enable for all schedulers in PHY0 |
|
| 1068 |
++ */ |
|
| 1069 |
++#define TMU_TDQ0_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x0b8) |
|
| 1070 |
++ |
|
| 1071 |
++#define TMU_LLM_CTRL (TMU_CSR_BASE_ADDR + 0x0bc) |
|
| 1072 |
++#define TMU_LLM_BASE_ADDR (TMU_CSR_BASE_ADDR + 0x0c0) |
|
| 1073 |
++#define TMU_LLM_QUE_LEN (TMU_CSR_BASE_ADDR + 0x0c4) |
|
| 1074 |
++#define TMU_LLM_QUE_HEADPTR (TMU_CSR_BASE_ADDR + 0x0c8) |
|
| 1075 |
++#define TMU_LLM_QUE_TAILPTR (TMU_CSR_BASE_ADDR + 0x0cc) |
|
| 1076 |
++#define TMU_LLM_QUE_DROPCNT (TMU_CSR_BASE_ADDR + 0x0d0) |
|
| 1077 |
++#define TMU_INT_EN (TMU_CSR_BASE_ADDR + 0x0d4) |
|
| 1078 |
++#define TMU_INT_SRC (TMU_CSR_BASE_ADDR + 0x0d8) |
|
| 1079 |
++#define TMU_INQ_STAT (TMU_CSR_BASE_ADDR + 0x0dc) |
|
| 1080 |
++#define TMU_CTRL (TMU_CSR_BASE_ADDR + 0x0e0) |
|
| 1081 |
++ |
|
| 1082 |
++/* [31] Mem Access Command. 0 = Internal Memory Read, 1 = Internal memory |
|
| 1083 |
++ * Write [27:24] Byte Enables of the Internal memory access [23:0] Address of |
|
| 1084 |
++ * the internal memory. This address is used to access both the PM and DM of |
|
| 1085 |
++ * all the PE's |
|
| 1086 |
++ */ |
|
| 1087 |
++#define TMU_MEM_ACCESS_ADDR (TMU_CSR_BASE_ADDR + 0x0e4) |
|
| 1088 |
++ |
|
| 1089 |
++/* Internal Memory Access Write Data */ |
|
| 1090 |
++#define TMU_MEM_ACCESS_WDATA (TMU_CSR_BASE_ADDR + 0x0e8) |
|
| 1091 |
++/* Internal Memory Access Read Data. The commands are blocked |
|
| 1092 |
++ * at the mem_access only |
|
| 1093 |
++ */ |
|
| 1094 |
++#define TMU_MEM_ACCESS_RDATA (TMU_CSR_BASE_ADDR + 0x0ec) |
|
| 1095 |
++ |
|
| 1096 |
++/* [31:0] PHY0 in queue address (must be initialized with one of the |
|
| 1097 |
++ * xxx_INQ_PKTPTR cbus addresses) |
|
| 1098 |
++ */ |
|
| 1099 |
++#define TMU_PHY0_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f0) |
|
| 1100 |
++/* [31:0] PHY1 in queue address (must be initialized with one of the |
|
| 1101 |
++ * xxx_INQ_PKTPTR cbus addresses) |
|
| 1102 |
++ */ |
|
| 1103 |
++#define TMU_PHY1_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f4) |
|
| 1104 |
++/* [31:0] PHY2 in queue address (must be initialized with one of the |
|
| 1105 |
++ * xxx_INQ_PKTPTR cbus addresses) |
|
| 1106 |
++ */ |
|
| 1107 |
++#define TMU_PHY2_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f8) |
|
| 1108 |
++/* [31:0] PHY3 in queue address (must be initialized with one of the |
|
| 1109 |
++ * xxx_INQ_PKTPTR cbus addresses) |
|
| 1110 |
++ */ |
|
| 1111 |
++#define TMU_PHY3_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0fc) |
|
| 1112 |
++#define TMU_BMU_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x100) |
|
| 1113 |
++#define TMU_TX_CTRL (TMU_CSR_BASE_ADDR + 0x104) |
|
| 1114 |
++ |
|
| 1115 |
++#define TMU_BUS_ACCESS_WDATA (TMU_CSR_BASE_ADDR + 0x108) |
|
| 1116 |
++#define TMU_BUS_ACCESS (TMU_CSR_BASE_ADDR + 0x10c) |
|
| 1117 |
++#define TMU_BUS_ACCESS_RDATA (TMU_CSR_BASE_ADDR + 0x110) |
|
| 1118 |
++ |
|
| 1119 |
++#define TMU_PE_SYS_CLK_RATIO (TMU_CSR_BASE_ADDR + 0x114) |
|
| 1120 |
++#define TMU_PE_STATUS (TMU_CSR_BASE_ADDR + 0x118) |
|
| 1121 |
++#define TMU_TEQ_MAX_THRESHOLD (TMU_CSR_BASE_ADDR + 0x11c) |
|
| 1122 |
++/* [31:0] PHY4 in queue address (must be initialized with one of the |
|
| 1123 |
++ * xxx_INQ_PKTPTR cbus addresses) |
|
| 1124 |
++ */ |
|
| 1125 |
++#define TMU_PHY4_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x134) |
|
| 1126 |
++/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. |
|
| 1127 |
++ * This is a global Enable for all schedulers in PHY1 |
|
| 1128 |
++ */ |
|
| 1129 |
++#define TMU_TDQ1_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x138) |
|
| 1130 |
++/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. |
|
| 1131 |
++ * This is a global Enable for all schedulers in PHY2 |
|
| 1132 |
++ */ |
|
| 1133 |
++#define TMU_TDQ2_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x13c) |
|
| 1134 |
++/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. |
|
| 1135 |
++ * This is a global Enable for all schedulers in PHY3 |
|
| 1136 |
++ */ |
|
| 1137 |
++#define TMU_TDQ3_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x140) |
|
| 1138 |
++#define TMU_BMU_BUF_SIZE (TMU_CSR_BASE_ADDR + 0x144) |
|
| 1139 |
++/* [31:0] PHY5 in queue address (must be initialized with one of the |
|
| 1140 |
++ * xxx_INQ_PKTPTR cbus addresses) |
|
| 1141 |
++ */ |
|
| 1142 |
++#define TMU_PHY5_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x148) |
|
| 1143 |
++ |
|
| 1144 |
++#define SW_RESET BIT(0) /* Global software reset */ |
|
| 1145 |
++#define INQ_RESET BIT(2) |
|
| 1146 |
++#define TEQ_RESET BIT(3) |
|
| 1147 |
++#define TDQ_RESET BIT(4) |
|
| 1148 |
++#define PE_RESET BIT(5) |
|
| 1149 |
++#define MEM_INIT BIT(6) |
|
| 1150 |
++#define MEM_INIT_DONE BIT(7) |
|
| 1151 |
++#define LLM_INIT BIT(8) |
|
| 1152 |
++#define LLM_INIT_DONE BIT(9) |
|
| 1153 |
++#define ECC_MEM_INIT_DONE BIT(10) |
|
| 1154 |
++ |
|
| 1155 |
++struct tmu_cfg {
|
|
| 1156 |
++ u32 pe_sys_clk_ratio; |
|
| 1157 |
++ unsigned long llm_base_addr; |
|
| 1158 |
++ u32 llm_queue_len; |
|
| 1159 |
++}; |
|
| 1160 |
++ |
|
| 1161 |
++/* Not HW related for pfe_ctrl / pfe common defines */ |
|
| 1162 |
++#define DEFAULT_MAX_QDEPTH 80 |
|
| 1163 |
++#define DEFAULT_Q0_QDEPTH 511 /*We keep one large queue for host tx qos */ |
|
| 1164 |
++#define DEFAULT_TMU3_QDEPTH 127 |
|
| 1165 |
++ |
|
| 1166 |
++#endif /* _TMU_CSR_H_ */ |
|
| 1167 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/cbus/util_csr.h b/drivers/staging/fsl_ppfe/include/pfe/cbus/util_csr.h |
|
| 1168 |
+new file mode 100644 |
|
| 1169 |
+index 000000000000..ae623cdafe7b |
|
| 1170 |
+--- /dev/null |
|
| 1171 |
+@@ -0,0 +1,61 @@ |
|
| 1172 |
++/* |
|
| 1173 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 1174 |
++ * Copyright 2017 NXP |
|
| 1175 |
++ * |
|
| 1176 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 1177 |
++ * it under the terms of the GNU General Public License as published by |
|
| 1178 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 1179 |
++ * (at your option) any later version. |
|
| 1180 |
++ * |
|
| 1181 |
++ * This program is distributed in the hope that it will be useful, |
|
| 1182 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 1183 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 1184 |
++ * GNU General Public License for more details. |
|
| 1185 |
++ * |
|
| 1186 |
++ * You should have received a copy of the GNU General Public License |
|
| 1187 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 1188 |
++ */ |
|
| 1189 |
++ |
|
| 1190 |
++#ifndef _UTIL_CSR_H_ |
|
| 1191 |
++#define _UTIL_CSR_H_ |
|
| 1192 |
++ |
|
| 1193 |
++#define UTIL_VERSION (UTIL_CSR_BASE_ADDR + 0x000) |
|
| 1194 |
++#define UTIL_TX_CTRL (UTIL_CSR_BASE_ADDR + 0x004) |
|
| 1195 |
++#define UTIL_INQ_PKTPTR (UTIL_CSR_BASE_ADDR + 0x010) |
|
| 1196 |
++ |
|
| 1197 |
++#define UTIL_HDR_SIZE (UTIL_CSR_BASE_ADDR + 0x014) |
|
| 1198 |
++ |
|
| 1199 |
++#define UTIL_PE0_QB_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x020) |
|
| 1200 |
++#define UTIL_PE0_QB_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x024) |
|
| 1201 |
++#define UTIL_PE0_RO_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x060) |
|
| 1202 |
++#define UTIL_PE0_RO_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x064) |
|
| 1203 |
++ |
|
| 1204 |
++#define UTIL_MEM_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x100) |
|
| 1205 |
++#define UTIL_MEM_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x104) |
|
| 1206 |
++#define UTIL_MEM_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x108) |
|
| 1207 |
++ |
|
| 1208 |
++#define UTIL_TM_INQ_ADDR (UTIL_CSR_BASE_ADDR + 0x114) |
|
| 1209 |
++#define UTIL_PE_STATUS (UTIL_CSR_BASE_ADDR + 0x118) |
|
| 1210 |
++ |
|
| 1211 |
++#define UTIL_PE_SYS_CLK_RATIO (UTIL_CSR_BASE_ADDR + 0x200) |
|
| 1212 |
++#define UTIL_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x204) |
|
| 1213 |
++#define UTIL_GAP_BETWEEN_READS (UTIL_CSR_BASE_ADDR + 0x208) |
|
| 1214 |
++#define UTIL_MAX_BUF_CNT (UTIL_CSR_BASE_ADDR + 0x20c) |
|
| 1215 |
++#define UTIL_TSQ_FIFO_THRES (UTIL_CSR_BASE_ADDR + 0x210) |
|
| 1216 |
++#define UTIL_TSQ_MAX_CNT (UTIL_CSR_BASE_ADDR + 0x214) |
|
| 1217 |
++#define UTIL_IRAM_DATA_0 (UTIL_CSR_BASE_ADDR + 0x218) |
|
| 1218 |
++#define UTIL_IRAM_DATA_1 (UTIL_CSR_BASE_ADDR + 0x21c) |
|
| 1219 |
++#define UTIL_IRAM_DATA_2 (UTIL_CSR_BASE_ADDR + 0x220) |
|
| 1220 |
++#define UTIL_IRAM_DATA_3 (UTIL_CSR_BASE_ADDR + 0x224) |
|
| 1221 |
++ |
|
| 1222 |
++#define UTIL_BUS_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x228) |
|
| 1223 |
++#define UTIL_BUS_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x22c) |
|
| 1224 |
++#define UTIL_BUS_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x230) |
|
| 1225 |
++ |
|
| 1226 |
++#define UTIL_INQ_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x234) |
|
| 1227 |
++ |
|
| 1228 |
++struct util_cfg {
|
|
| 1229 |
++ u32 pe_sys_clk_ratio; |
|
| 1230 |
++}; |
|
| 1231 |
++ |
|
| 1232 |
++#endif /* _UTIL_CSR_H_ */ |
|
| 1233 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/pfe.h b/drivers/staging/fsl_ppfe/include/pfe/pfe.h |
|
| 1234 |
+new file mode 100644 |
|
| 1235 |
+index 000000000000..d93ae4c60251 |
|
| 1236 |
+--- /dev/null |
|
| 1237 |
+@@ -0,0 +1,372 @@ |
|
| 1238 |
++/* |
|
| 1239 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 1240 |
++ * Copyright 2017 NXP |
|
| 1241 |
++ * |
|
| 1242 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 1243 |
++ * it under the terms of the GNU General Public License as published by |
|
| 1244 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 1245 |
++ * (at your option) any later version. |
|
| 1246 |
++ * |
|
| 1247 |
++ * This program is distributed in the hope that it will be useful, |
|
| 1248 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 1249 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 1250 |
++ * GNU General Public License for more details. |
|
| 1251 |
++ * |
|
| 1252 |
++ * You should have received a copy of the GNU General Public License |
|
| 1253 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 1254 |
++ */ |
|
| 1255 |
++ |
|
| 1256 |
++#ifndef _PFE_H_ |
|
| 1257 |
++#define _PFE_H_ |
|
| 1258 |
++ |
|
| 1259 |
++#include "cbus.h" |
|
| 1260 |
++ |
|
| 1261 |
++#define CLASS_DMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) |
|
| 1262 |
++/* |
|
| 1263 |
++ * Only valid for mem access register interface |
|
| 1264 |
++ */ |
|
| 1265 |
++#define CLASS_IMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) |
|
| 1266 |
++#define CLASS_DMEM_SIZE 0x00002000 |
|
| 1267 |
++#define CLASS_IMEM_SIZE 0x00008000 |
|
| 1268 |
++ |
|
| 1269 |
++#define TMU_DMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20)) |
|
| 1270 |
++/* |
|
| 1271 |
++ * Only valid for mem access register interface |
|
| 1272 |
++ */ |
|
| 1273 |
++#define TMU_IMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20)) |
|
| 1274 |
++#define TMU_DMEM_SIZE 0x00000800 |
|
| 1275 |
++#define TMU_IMEM_SIZE 0x00002000 |
|
| 1276 |
++ |
|
| 1277 |
++#define UTIL_DMEM_BASE_ADDR 0x00000000 |
|
| 1278 |
++#define UTIL_DMEM_SIZE 0x00002000 |
|
| 1279 |
++ |
|
| 1280 |
++#define PE_LMEM_BASE_ADDR 0xc3010000 |
|
| 1281 |
++#define PE_LMEM_SIZE 0x8000 |
|
| 1282 |
++#define PE_LMEM_END (PE_LMEM_BASE_ADDR + PE_LMEM_SIZE) |
|
| 1283 |
++ |
|
| 1284 |
++#define DMEM_BASE_ADDR 0x00000000 |
|
| 1285 |
++#define DMEM_SIZE 0x2000 /* TMU has less... */ |
|
| 1286 |
++#define DMEM_END (DMEM_BASE_ADDR + DMEM_SIZE) |
|
| 1287 |
++ |
|
| 1288 |
++#define PMEM_BASE_ADDR 0x00010000 |
|
| 1289 |
++#define PMEM_SIZE 0x8000 /* TMU has less... */ |
|
| 1290 |
++#define PMEM_END (PMEM_BASE_ADDR + PMEM_SIZE) |
|
| 1291 |
++ |
|
| 1292 |
++/* These check memory ranges from PE point of view/memory map */ |
|
| 1293 |
++#define IS_DMEM(addr, len) \ |
|
| 1294 |
++ ({ typeof(addr) addr_ = (addr); \
|
|
| 1295 |
++ ((unsigned long)(addr_) >= DMEM_BASE_ADDR) && \ |
|
| 1296 |
++ (((unsigned long)(addr_) + (len)) <= DMEM_END); }) |
|
| 1297 |
++ |
|
| 1298 |
++#define IS_PMEM(addr, len) \ |
|
| 1299 |
++ ({ typeof(addr) addr_ = (addr); \
|
|
| 1300 |
++ ((unsigned long)(addr_) >= PMEM_BASE_ADDR) && \ |
|
| 1301 |
++ (((unsigned long)(addr_) + (len)) <= PMEM_END); }) |
|
| 1302 |
++ |
|
| 1303 |
++#define IS_PE_LMEM(addr, len) \ |
|
| 1304 |
++ ({ typeof(addr) addr_ = (addr); \
|
|
| 1305 |
++ ((unsigned long)(addr_) >= \ |
|
| 1306 |
++ PE_LMEM_BASE_ADDR) && \ |
|
| 1307 |
++ (((unsigned long)(addr_) + \ |
|
| 1308 |
++ (len)) <= PE_LMEM_END); }) |
|
| 1309 |
++ |
|
| 1310 |
++#define IS_PFE_LMEM(addr, len) \ |
|
| 1311 |
++ ({ typeof(addr) addr_ = (addr); \
|
|
| 1312 |
++ ((unsigned long)(addr_) >= \ |
|
| 1313 |
++ CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR)) && \ |
|
| 1314 |
++ (((unsigned long)(addr_) + (len)) <= \ |
|
| 1315 |
++ CBUS_VIRT_TO_PFE(LMEM_END)); }) |
|
| 1316 |
++ |
|
| 1317 |
++#define __IS_PHYS_DDR(addr, len) \ |
|
| 1318 |
++ ({ typeof(addr) addr_ = (addr); \
|
|
| 1319 |
++ ((unsigned long)(addr_) >= \ |
|
| 1320 |
++ DDR_PHYS_BASE_ADDR) && \ |
|
| 1321 |
++ (((unsigned long)(addr_) + (len)) <= \ |
|
| 1322 |
++ DDR_PHYS_END); }) |
|
| 1323 |
++ |
|
| 1324 |
++#define IS_PHYS_DDR(addr, len) __IS_PHYS_DDR(DDR_PFE_TO_PHYS(addr), len) |
|
| 1325 |
++ |
|
| 1326 |
++/* |
|
| 1327 |
++ * If using a run-time virtual address for the cbus base address use this code |
|
| 1328 |
++ */ |
|
| 1329 |
++extern void *cbus_base_addr; |
|
| 1330 |
++extern void *ddr_base_addr; |
|
| 1331 |
++extern unsigned long ddr_phys_base_addr; |
|
| 1332 |
++extern unsigned int ddr_size; |
|
| 1333 |
++ |
|
| 1334 |
++#define CBUS_BASE_ADDR cbus_base_addr |
|
| 1335 |
++#define DDR_PHYS_BASE_ADDR ddr_phys_base_addr |
|
| 1336 |
++#define DDR_BASE_ADDR ddr_base_addr |
|
| 1337 |
++#define DDR_SIZE ddr_size |
|
| 1338 |
++ |
|
| 1339 |
++#define DDR_PHYS_END (DDR_PHYS_BASE_ADDR + DDR_SIZE) |
|
| 1340 |
++ |
|
| 1341 |
++#define LS1012A_PFE_RESET_WA /* |
|
| 1342 |
++ * PFE doesn't have global reset and re-init |
|
| 1343 |
++ * should takecare few things to make PFE |
|
| 1344 |
++ * functional after reset |
|
| 1345 |
++ */ |
|
| 1346 |
++#define PFE_CBUS_PHYS_BASE_ADDR 0xc0000000 /* CBUS physical base address |
|
| 1347 |
++ * as seen by PE's. |
|
| 1348 |
++ */ |
|
| 1349 |
++/* CBUS physical base address as seen by PE's. */ |
|
| 1350 |
++#define PFE_CBUS_PHYS_BASE_ADDR_FROM_PFE 0xc0000000 |
|
| 1351 |
++ |
|
| 1352 |
++#define DDR_PHYS_TO_PFE(p) (((unsigned long int)(p)) & 0x7FFFFFFF) |
|
| 1353 |
++#define DDR_PFE_TO_PHYS(p) (((unsigned long int)(p)) | 0x80000000) |
|
| 1354 |
++#define CBUS_PHYS_TO_PFE(p) (((p) - PFE_CBUS_PHYS_BASE_ADDR) + \ |
|
| 1355 |
++ PFE_CBUS_PHYS_BASE_ADDR_FROM_PFE) |
|
| 1356 |
++/* Translates to PFE address map */ |
|
| 1357 |
++ |
|
| 1358 |
++#define DDR_PHYS_TO_VIRT(p) (((p) - DDR_PHYS_BASE_ADDR) + DDR_BASE_ADDR) |
|
| 1359 |
++#define DDR_VIRT_TO_PHYS(v) (((v) - DDR_BASE_ADDR) + DDR_PHYS_BASE_ADDR) |
|
| 1360 |
++#define DDR_VIRT_TO_PFE(p) (DDR_PHYS_TO_PFE(DDR_VIRT_TO_PHYS(p))) |
|
| 1361 |
++ |
|
| 1362 |
++#define CBUS_VIRT_TO_PFE(v) (((v) - CBUS_BASE_ADDR) + \ |
|
| 1363 |
++ PFE_CBUS_PHYS_BASE_ADDR) |
|
| 1364 |
++#define CBUS_PFE_TO_VIRT(p) (((unsigned long int)(p) - \ |
|
| 1365 |
++ PFE_CBUS_PHYS_BASE_ADDR) + CBUS_BASE_ADDR) |
|
| 1366 |
++ |
|
| 1367 |
++/* The below part of the code is used in QOS control driver from host */ |
|
| 1368 |
++#define TMU_APB_BASE_ADDR 0xc1000000 /* TMU base address seen by |
|
| 1369 |
++ * pe's |
|
| 1370 |
++ */ |
|
| 1371 |
++ |
|
| 1372 |
++enum {
|
|
| 1373 |
++ CLASS0_ID = 0, |
|
| 1374 |
++ CLASS1_ID, |
|
| 1375 |
++ CLASS2_ID, |
|
| 1376 |
++ CLASS3_ID, |
|
| 1377 |
++ CLASS4_ID, |
|
| 1378 |
++ CLASS5_ID, |
|
| 1379 |
++ TMU0_ID, |
|
| 1380 |
++ TMU1_ID, |
|
| 1381 |
++ TMU2_ID, |
|
| 1382 |
++ TMU3_ID, |
|
| 1383 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 1384 |
++ UTIL_ID, |
|
| 1385 |
++#endif |
|
| 1386 |
++ MAX_PE |
|
| 1387 |
++}; |
|
| 1388 |
++ |
|
| 1389 |
++#define CLASS_MASK (BIT(CLASS0_ID) | BIT(CLASS1_ID) |\ |
|
| 1390 |
++ BIT(CLASS2_ID) | BIT(CLASS3_ID) |\ |
|
| 1391 |
++ BIT(CLASS4_ID) | BIT(CLASS5_ID)) |
|
| 1392 |
++#define CLASS_MAX_ID CLASS5_ID |
|
| 1393 |
++ |
|
| 1394 |
++#define TMU_MASK (BIT(TMU0_ID) | BIT(TMU1_ID) |\ |
|
| 1395 |
++ BIT(TMU3_ID)) |
|
| 1396 |
++ |
|
| 1397 |
++#define TMU_MAX_ID TMU3_ID |
|
| 1398 |
++ |
|
| 1399 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 1400 |
++#define UTIL_MASK BIT(UTIL_ID) |
|
| 1401 |
++#endif |
|
| 1402 |
++ |
|
| 1403 |
++struct pe_status {
|
|
| 1404 |
++ u32 cpu_state; |
|
| 1405 |
++ u32 activity_counter; |
|
| 1406 |
++ u32 rx; |
|
| 1407 |
++ union {
|
|
| 1408 |
++ u32 tx; |
|
| 1409 |
++ u32 tmu_qstatus; |
|
| 1410 |
++ }; |
|
| 1411 |
++ u32 drop; |
|
| 1412 |
++#if defined(CFG_PE_DEBUG) |
|
| 1413 |
++ u32 debug_indicator; |
|
| 1414 |
++ u32 debug[16]; |
|
| 1415 |
++#endif |
|
| 1416 |
++} __aligned(16); |
|
| 1417 |
++ |
|
| 1418 |
++struct pe_sync_mailbox {
|
|
| 1419 |
++ u32 stop; |
|
| 1420 |
++ u32 stopped; |
|
| 1421 |
++}; |
|
| 1422 |
++ |
|
| 1423 |
++/* Drop counter definitions */ |
|
| 1424 |
++ |
|
| 1425 |
++#define CLASS_NUM_DROP_COUNTERS 13 |
|
| 1426 |
++#define UTIL_NUM_DROP_COUNTERS 8 |
|
| 1427 |
++ |
|
| 1428 |
++/* PE information. |
|
| 1429 |
++ * Structure containing PE's specific information. It is used to create |
|
| 1430 |
++ * generic C functions common to all PE's. |
|
| 1431 |
++ * Before using the library functions this structure needs to be initialized |
|
| 1432 |
++ * with the different registers virtual addresses |
|
| 1433 |
++ * (according to the ARM MMU mmaping). The default initialization supports a |
|
| 1434 |
++ * virtual == physical mapping. |
|
| 1435 |
++ */ |
|
| 1436 |
++struct pe_info {
|
|
| 1437 |
++ u32 dmem_base_addr; /* PE's dmem base address */ |
|
| 1438 |
++ u32 pmem_base_addr; /* PE's pmem base address */ |
|
| 1439 |
++ u32 pmem_size; /* PE's pmem size */ |
|
| 1440 |
++ |
|
| 1441 |
++ void *mem_access_wdata; /* PE's _MEM_ACCESS_WDATA register |
|
| 1442 |
++ * address |
|
| 1443 |
++ */ |
|
| 1444 |
++ void *mem_access_addr; /* PE's _MEM_ACCESS_ADDR register |
|
| 1445 |
++ * address |
|
| 1446 |
++ */ |
|
| 1447 |
++ void *mem_access_rdata; /* PE's _MEM_ACCESS_RDATA register |
|
| 1448 |
++ * address |
|
| 1449 |
++ */ |
|
| 1450 |
++}; |
|
| 1451 |
++ |
|
| 1452 |
++void pe_lmem_read(u32 *dst, u32 len, u32 offset); |
|
| 1453 |
++void pe_lmem_write(u32 *src, u32 len, u32 offset); |
|
| 1454 |
++ |
|
| 1455 |
++void pe_dmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len); |
|
| 1456 |
++void pe_pmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len); |
|
| 1457 |
++ |
|
| 1458 |
++u32 pe_pmem_read(int id, u32 addr, u8 size); |
|
| 1459 |
++ |
|
| 1460 |
++void pe_dmem_write(int id, u32 val, u32 addr, u8 size); |
|
| 1461 |
++u32 pe_dmem_read(int id, u32 addr, u8 size); |
|
| 1462 |
++void class_pe_lmem_memcpy_to32(u32 dst, const void *src, unsigned int len); |
|
| 1463 |
++void class_pe_lmem_memset(u32 dst, int val, unsigned int len); |
|
| 1464 |
++void class_bus_write(u32 val, u32 addr, u8 size); |
|
| 1465 |
++u32 class_bus_read(u32 addr, u8 size); |
|
| 1466 |
++ |
|
| 1467 |
++#define class_bus_readl(addr) class_bus_read(addr, 4) |
|
| 1468 |
++#define class_bus_readw(addr) class_bus_read(addr, 2) |
|
| 1469 |
++#define class_bus_readb(addr) class_bus_read(addr, 1) |
|
| 1470 |
++ |
|
| 1471 |
++#define class_bus_writel(val, addr) class_bus_write(val, addr, 4) |
|
| 1472 |
++#define class_bus_writew(val, addr) class_bus_write(val, addr, 2) |
|
| 1473 |
++#define class_bus_writeb(val, addr) class_bus_write(val, addr, 1) |
|
| 1474 |
++ |
|
| 1475 |
++#define pe_dmem_readl(id, addr) pe_dmem_read(id, addr, 4) |
|
| 1476 |
++#define pe_dmem_readw(id, addr) pe_dmem_read(id, addr, 2) |
|
| 1477 |
++#define pe_dmem_readb(id, addr) pe_dmem_read(id, addr, 1) |
|
| 1478 |
++ |
|
| 1479 |
++#define pe_dmem_writel(id, val, addr) pe_dmem_write(id, val, addr, 4) |
|
| 1480 |
++#define pe_dmem_writew(id, val, addr) pe_dmem_write(id, val, addr, 2) |
|
| 1481 |
++#define pe_dmem_writeb(id, val, addr) pe_dmem_write(id, val, addr, 1) |
|
| 1482 |
++ |
|
| 1483 |
++/*int pe_load_elf_section(int id, const void *data, elf32_shdr *shdr); */ |
|
| 1484 |
++int pe_load_elf_section(int id, const void *data, struct elf32_shdr *shdr, |
|
| 1485 |
++ struct device *dev); |
|
| 1486 |
++ |
|
| 1487 |
++void pfe_lib_init(void *cbus_base, void *ddr_base, unsigned long ddr_phys_base, |
|
| 1488 |
++ unsigned int ddr_size); |
|
| 1489 |
++void bmu_init(void *base, struct BMU_CFG *cfg); |
|
| 1490 |
++void bmu_reset(void *base); |
|
| 1491 |
++void bmu_enable(void *base); |
|
| 1492 |
++void bmu_disable(void *base); |
|
| 1493 |
++void bmu_set_config(void *base, struct BMU_CFG *cfg); |
|
| 1494 |
++ |
|
| 1495 |
++/* |
|
| 1496 |
++ * An enumerated type for loopback values. This can be one of three values, no |
|
| 1497 |
++ * loopback -normal operation, local loopback with internal loopback module of |
|
| 1498 |
++ * MAC or PHY loopback which is through the external PHY. |
|
| 1499 |
++ */ |
|
| 1500 |
++#ifndef __MAC_LOOP_ENUM__ |
|
| 1501 |
++#define __MAC_LOOP_ENUM__ |
|
| 1502 |
++enum mac_loop {LB_NONE, LB_EXT, LB_LOCAL};
|
|
| 1503 |
++#endif |
|
| 1504 |
++ |
|
| 1505 |
++void gemac_init(void *base, void *config); |
|
| 1506 |
++void gemac_disable_rx_checksum_offload(void *base); |
|
| 1507 |
++void gemac_enable_rx_checksum_offload(void *base); |
|
| 1508 |
++void gemac_set_mdc_div(void *base, int mdc_div); |
|
| 1509 |
++void gemac_set_speed(void *base, enum mac_speed gem_speed); |
|
| 1510 |
++void gemac_set_duplex(void *base, int duplex); |
|
| 1511 |
++void gemac_set_mode(void *base, int mode); |
|
| 1512 |
++void gemac_enable(void *base); |
|
| 1513 |
++void gemac_tx_disable(void *base); |
|
| 1514 |
++void gemac_tx_enable(void *base); |
|
| 1515 |
++void gemac_disable(void *base); |
|
| 1516 |
++void gemac_reset(void *base); |
|
| 1517 |
++void gemac_set_address(void *base, struct spec_addr *addr); |
|
| 1518 |
++struct spec_addr gemac_get_address(void *base); |
|
| 1519 |
++void gemac_set_loop(void *base, enum mac_loop gem_loop); |
|
| 1520 |
++void gemac_set_laddr1(void *base, struct pfe_mac_addr *address); |
|
| 1521 |
++void gemac_set_laddr2(void *base, struct pfe_mac_addr *address); |
|
| 1522 |
++void gemac_set_laddr3(void *base, struct pfe_mac_addr *address); |
|
| 1523 |
++void gemac_set_laddr4(void *base, struct pfe_mac_addr *address); |
|
| 1524 |
++void gemac_set_laddrN(void *base, struct pfe_mac_addr *address, |
|
| 1525 |
++ unsigned int entry_index); |
|
| 1526 |
++void gemac_clear_laddr1(void *base); |
|
| 1527 |
++void gemac_clear_laddr2(void *base); |
|
| 1528 |
++void gemac_clear_laddr3(void *base); |
|
| 1529 |
++void gemac_clear_laddr4(void *base); |
|
| 1530 |
++void gemac_clear_laddrN(void *base, unsigned int entry_index); |
|
| 1531 |
++struct pfe_mac_addr gemac_get_hash(void *base); |
|
| 1532 |
++void gemac_set_hash(void *base, struct pfe_mac_addr *hash); |
|
| 1533 |
++struct pfe_mac_addr gem_get_laddr1(void *base); |
|
| 1534 |
++struct pfe_mac_addr gem_get_laddr2(void *base); |
|
| 1535 |
++struct pfe_mac_addr gem_get_laddr3(void *base); |
|
| 1536 |
++struct pfe_mac_addr gem_get_laddr4(void *base); |
|
| 1537 |
++struct pfe_mac_addr gem_get_laddrN(void *base, unsigned int entry_index); |
|
| 1538 |
++void gemac_set_config(void *base, struct gemac_cfg *cfg); |
|
| 1539 |
++void gemac_allow_broadcast(void *base); |
|
| 1540 |
++void gemac_no_broadcast(void *base); |
|
| 1541 |
++void gemac_enable_1536_rx(void *base); |
|
| 1542 |
++void gemac_disable_1536_rx(void *base); |
|
| 1543 |
++void gemac_enable_rx_jmb(void *base); |
|
| 1544 |
++void gemac_disable_rx_jmb(void *base); |
|
| 1545 |
++void gemac_enable_stacked_vlan(void *base); |
|
| 1546 |
++void gemac_disable_stacked_vlan(void *base); |
|
| 1547 |
++void gemac_enable_pause_rx(void *base); |
|
| 1548 |
++void gemac_disable_pause_rx(void *base); |
|
| 1549 |
++void gemac_enable_copy_all(void *base); |
|
| 1550 |
++void gemac_disable_copy_all(void *base); |
|
| 1551 |
++void gemac_set_bus_width(void *base, int width); |
|
| 1552 |
++void gemac_set_wol(void *base, u32 wol_conf); |
|
| 1553 |
++ |
|
| 1554 |
++void gpi_init(void *base, struct gpi_cfg *cfg); |
|
| 1555 |
++void gpi_reset(void *base); |
|
| 1556 |
++void gpi_enable(void *base); |
|
| 1557 |
++void gpi_disable(void *base); |
|
| 1558 |
++void gpi_set_config(void *base, struct gpi_cfg *cfg); |
|
| 1559 |
++ |
|
| 1560 |
++void class_init(struct class_cfg *cfg); |
|
| 1561 |
++void class_reset(void); |
|
| 1562 |
++void class_enable(void); |
|
| 1563 |
++void class_disable(void); |
|
| 1564 |
++void class_set_config(struct class_cfg *cfg); |
|
| 1565 |
++ |
|
| 1566 |
++void tmu_reset(void); |
|
| 1567 |
++void tmu_init(struct tmu_cfg *cfg); |
|
| 1568 |
++void tmu_enable(u32 pe_mask); |
|
| 1569 |
++void tmu_disable(u32 pe_mask); |
|
| 1570 |
++u32 tmu_qstatus(u32 if_id); |
|
| 1571 |
++u32 tmu_pkts_processed(u32 if_id); |
|
| 1572 |
++ |
|
| 1573 |
++void util_init(struct util_cfg *cfg); |
|
| 1574 |
++void util_reset(void); |
|
| 1575 |
++void util_enable(void); |
|
| 1576 |
++void util_disable(void); |
|
| 1577 |
++ |
|
| 1578 |
++void hif_init(void); |
|
| 1579 |
++void hif_tx_enable(void); |
|
| 1580 |
++void hif_tx_disable(void); |
|
| 1581 |
++void hif_rx_enable(void); |
|
| 1582 |
++void hif_rx_disable(void); |
|
| 1583 |
++ |
|
| 1584 |
++/* Get Chip Revision level |
|
| 1585 |
++ * |
|
| 1586 |
++ */ |
|
| 1587 |
++static inline unsigned int CHIP_REVISION(void) |
|
| 1588 |
++{
|
|
| 1589 |
++ /*For LS1012A return always 1 */ |
|
| 1590 |
++ return 1; |
|
| 1591 |
++} |
|
| 1592 |
++ |
|
| 1593 |
++/* Start HIF rx DMA |
|
| 1594 |
++ * |
|
| 1595 |
++ */ |
|
| 1596 |
++static inline void hif_rx_dma_start(void) |
|
| 1597 |
++{
|
|
| 1598 |
++ writel(HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB, HIF_RX_CTRL); |
|
| 1599 |
++} |
|
| 1600 |
++ |
|
| 1601 |
++/* Start HIF tx DMA |
|
| 1602 |
++ * |
|
| 1603 |
++ */ |
|
| 1604 |
++static inline void hif_tx_dma_start(void) |
|
| 1605 |
++{
|
|
| 1606 |
++ writel(HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB, HIF_TX_CTRL); |
|
| 1607 |
++} |
|
| 1608 |
++ |
|
| 1609 |
++#endif /* _PFE_H_ */ |
|
| 1610 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_ctrl.h b/drivers/staging/fsl_ppfe/pfe_ctrl.h |
|
| 1611 |
+new file mode 100644 |
|
| 1612 |
+index 000000000000..22115c76896c |
|
| 1613 |
+--- /dev/null |
|
| 1614 |
+@@ -0,0 +1,112 @@ |
|
| 1615 |
++/* |
|
| 1616 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 1617 |
++ * Copyright 2017 NXP |
|
| 1618 |
++ * |
|
| 1619 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 1620 |
++ * it under the terms of the GNU General Public License as published by |
|
| 1621 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 1622 |
++ * (at your option) any later version. |
|
| 1623 |
++ * |
|
| 1624 |
++ * This program is distributed in the hope that it will be useful, |
|
| 1625 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 1626 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 1627 |
++ * GNU General Public License for more details. |
|
| 1628 |
++ * |
|
| 1629 |
++ * You should have received a copy of the GNU General Public License |
|
| 1630 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 1631 |
++ */ |
|
| 1632 |
++ |
|
| 1633 |
++#ifndef _PFE_CTRL_H_ |
|
| 1634 |
++#define _PFE_CTRL_H_ |
|
| 1635 |
++ |
|
| 1636 |
++#include <linux/dmapool.h> |
|
| 1637 |
++ |
|
| 1638 |
++#include "pfe_mod.h" |
|
| 1639 |
++#include "pfe/pfe.h" |
|
| 1640 |
++ |
|
| 1641 |
++#define DMA_BUF_SIZE_128 0x80 /* enough for 1 conntracks */ |
|
| 1642 |
++#define DMA_BUF_SIZE_256 0x100 |
|
| 1643 |
++/* enough for 2 conntracks, 1 bridge entry or 1 multicast entry */ |
|
| 1644 |
++#define DMA_BUF_SIZE_512 0x200 |
|
| 1645 |
++/* 512bytes dma allocated buffers used by rtp relay feature */ |
|
| 1646 |
++#define DMA_BUF_MIN_ALIGNMENT 8 |
|
| 1647 |
++#define DMA_BUF_BOUNDARY (4 * 1024) |
|
| 1648 |
++/* bursts can not cross 4k boundary */ |
|
| 1649 |
++ |
|
| 1650 |
++#define CMD_TX_ENABLE 0x0501 |
|
| 1651 |
++#define CMD_TX_DISABLE 0x0502 |
|
| 1652 |
++ |
|
| 1653 |
++#define CMD_RX_LRO 0x0011 |
|
| 1654 |
++#define CMD_PKTCAP_ENABLE 0x0d01 |
|
| 1655 |
++#define CMD_QM_EXPT_RATE 0x020c |
|
| 1656 |
++ |
|
| 1657 |
++#define CLASS_DM_SH_STATIC (0x800) |
|
| 1658 |
++#define CLASS_DM_CPU_TICKS (CLASS_DM_SH_STATIC) |
|
| 1659 |
++#define CLASS_DM_SYNC_MBOX (0x808) |
|
| 1660 |
++#define CLASS_DM_MSG_MBOX (0x810) |
|
| 1661 |
++#define CLASS_DM_DROP_CNTR (0x820) |
|
| 1662 |
++#define CLASS_DM_RESUME (0x854) |
|
| 1663 |
++#define CLASS_DM_PESTATUS (0x860) |
|
| 1664 |
++ |
|
| 1665 |
++#define TMU_DM_SH_STATIC (0x80) |
|
| 1666 |
++#define TMU_DM_CPU_TICKS (TMU_DM_SH_STATIC) |
|
| 1667 |
++#define TMU_DM_SYNC_MBOX (0x88) |
|
| 1668 |
++#define TMU_DM_MSG_MBOX (0x90) |
|
| 1669 |
++#define TMU_DM_RESUME (0xA0) |
|
| 1670 |
++#define TMU_DM_PESTATUS (0xB0) |
|
| 1671 |
++#define TMU_DM_CONTEXT (0x300) |
|
| 1672 |
++#define TMU_DM_TX_TRANS (0x480) |
|
| 1673 |
++ |
|
| 1674 |
++#define UTIL_DM_SH_STATIC (0x0) |
|
| 1675 |
++#define UTIL_DM_CPU_TICKS (UTIL_DM_SH_STATIC) |
|
| 1676 |
++#define UTIL_DM_SYNC_MBOX (0x8) |
|
| 1677 |
++#define UTIL_DM_MSG_MBOX (0x10) |
|
| 1678 |
++#define UTIL_DM_DROP_CNTR (0x20) |
|
| 1679 |
++#define UTIL_DM_RESUME (0x40) |
|
| 1680 |
++#define UTIL_DM_PESTATUS (0x50) |
|
| 1681 |
++ |
|
| 1682 |
++struct pfe_ctrl {
|
|
| 1683 |
++ struct mutex mutex; /* to serialize pfe control access */ |
|
| 1684 |
++ spinlock_t lock; |
|
| 1685 |
++ |
|
| 1686 |
++ void *dma_pool; |
|
| 1687 |
++ void *dma_pool_512; |
|
| 1688 |
++ void *dma_pool_128; |
|
| 1689 |
++ |
|
| 1690 |
++ struct device *dev; |
|
| 1691 |
++ |
|
| 1692 |
++ void *hash_array_baseaddr; /* |
|
| 1693 |
++ * Virtual base address of |
|
| 1694 |
++ * the conntrack hash array |
|
| 1695 |
++ */ |
|
| 1696 |
++ unsigned long hash_array_phys_baseaddr; /* |
|
| 1697 |
++ * Physical base address of |
|
| 1698 |
++ * the conntrack hash array |
|
| 1699 |
++ */ |
|
| 1700 |
++ |
|
| 1701 |
++ int (*event_cb)(u16, u16, u16*); |
|
| 1702 |
++ |
|
| 1703 |
++ unsigned long sync_mailbox_baseaddr[MAX_PE]; /* |
|
| 1704 |
++ * Sync mailbox PFE |
|
| 1705 |
++ * internal address, |
|
| 1706 |
++ * initialized |
|
| 1707 |
++ * when parsing elf images |
|
| 1708 |
++ */ |
|
| 1709 |
++ unsigned long msg_mailbox_baseaddr[MAX_PE]; /* |
|
| 1710 |
++ * Msg mailbox PFE internal |
|
| 1711 |
++ * address, initialized |
|
| 1712 |
++ * when parsing elf images |
|
| 1713 |
++ */ |
|
| 1714 |
++ unsigned int sys_clk; /* AXI clock value, in KHz */ |
|
| 1715 |
++}; |
|
| 1716 |
++ |
|
| 1717 |
++int pfe_ctrl_init(struct pfe *pfe); |
|
| 1718 |
++void pfe_ctrl_exit(struct pfe *pfe); |
|
| 1719 |
++int pe_sync_stop(struct pfe_ctrl *ctrl, int pe_mask); |
|
| 1720 |
++void pe_start(struct pfe_ctrl *ctrl, int pe_mask); |
|
| 1721 |
++int pe_reset_all(struct pfe_ctrl *ctrl); |
|
| 1722 |
++void pfe_ctrl_suspend(struct pfe_ctrl *ctrl); |
|
| 1723 |
++void pfe_ctrl_resume(struct pfe_ctrl *ctrl); |
|
| 1724 |
++int relax(unsigned long end); |
|
| 1725 |
++ |
|
| 1726 |
++#endif /* _PFE_CTRL_H_ */ |
|
| 1727 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_debugfs.h b/drivers/staging/fsl_ppfe/pfe_debugfs.h |
|
| 1728 |
+new file mode 100644 |
|
| 1729 |
+index 000000000000..301d9fc22004 |
|
| 1730 |
+--- /dev/null |
|
| 1731 |
+@@ -0,0 +1,25 @@ |
|
| 1732 |
++/* |
|
| 1733 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 1734 |
++ * Copyright 2017 NXP |
|
| 1735 |
++ * |
|
| 1736 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 1737 |
++ * it under the terms of the GNU General Public License as published by |
|
| 1738 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 1739 |
++ * (at your option) any later version. |
|
| 1740 |
++ * |
|
| 1741 |
++ * This program is distributed in the hope that it will be useful, |
|
| 1742 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 1743 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 1744 |
++ * GNU General Public License for more details. |
|
| 1745 |
++ * |
|
| 1746 |
++ * You should have received a copy of the GNU General Public License |
|
| 1747 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 1748 |
++ */ |
|
| 1749 |
++ |
|
| 1750 |
++#ifndef _PFE_DEBUGFS_H_ |
|
| 1751 |
++#define _PFE_DEBUGFS_H_ |
|
| 1752 |
++ |
|
| 1753 |
++int pfe_debugfs_init(struct pfe *pfe); |
|
| 1754 |
++void pfe_debugfs_exit(struct pfe *pfe); |
|
| 1755 |
++ |
|
| 1756 |
++#endif /* _PFE_DEBUGFS_H_ */ |
|
| 1757 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.h b/drivers/staging/fsl_ppfe/pfe_eth.h |
|
| 1758 |
+new file mode 100644 |
|
| 1759 |
+index 000000000000..721bef3ef53b |
|
| 1760 |
+--- /dev/null |
|
| 1761 |
+@@ -0,0 +1,184 @@ |
|
| 1762 |
++/* |
|
| 1763 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 1764 |
++ * Copyright 2017 NXP |
|
| 1765 |
++ * |
|
| 1766 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 1767 |
++ * it under the terms of the GNU General Public License as published by |
|
| 1768 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 1769 |
++ * (at your option) any later version. |
|
| 1770 |
++ * |
|
| 1771 |
++ * This program is distributed in the hope that it will be useful, |
|
| 1772 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 1773 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 1774 |
++ * GNU General Public License for more details. |
|
| 1775 |
++ * |
|
| 1776 |
++ * You should have received a copy of the GNU General Public License |
|
| 1777 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 1778 |
++ */ |
|
| 1779 |
++ |
|
| 1780 |
++#ifndef _PFE_ETH_H_ |
|
| 1781 |
++#define _PFE_ETH_H_ |
|
| 1782 |
++#include <linux/kernel.h> |
|
| 1783 |
++#include <linux/netdevice.h> |
|
| 1784 |
++#include <linux/etherdevice.h> |
|
| 1785 |
++#include <linux/ethtool.h> |
|
| 1786 |
++#include <linux/mii.h> |
|
| 1787 |
++#include <linux/phy.h> |
|
| 1788 |
++#include <linux/clk.h> |
|
| 1789 |
++#include <linux/interrupt.h> |
|
| 1790 |
++#include <linux/time.h> |
|
| 1791 |
++ |
|
| 1792 |
++#define PFE_ETH_NAPI_STATS |
|
| 1793 |
++#define PFE_ETH_TX_STATS |
|
| 1794 |
++ |
|
| 1795 |
++#define PFE_ETH_FRAGS_MAX (65536 / HIF_RX_PKT_MIN_SIZE) |
|
| 1796 |
++#define LRO_LEN_COUNT_MAX 32 |
|
| 1797 |
++#define LRO_NB_COUNT_MAX 32 |
|
| 1798 |
++ |
|
| 1799 |
++#define PFE_PAUSE_FLAG_ENABLE 1 |
|
| 1800 |
++#define PFE_PAUSE_FLAG_AUTONEG 2 |
|
| 1801 |
++ |
|
| 1802 |
++/* GEMAC configured by SW */ |
|
| 1803 |
++/* GEMAC configured by phy lines (not for MII/GMII) */ |
|
| 1804 |
++ |
|
| 1805 |
++#define GEMAC_SW_FULL_DUPLEX BIT(9) |
|
| 1806 |
++#define GEMAC_SW_SPEED_10M (0 << 12) |
|
| 1807 |
++#define GEMAC_SW_SPEED_100M BIT(12) |
|
| 1808 |
++#define GEMAC_SW_SPEED_1G (2 << 12) |
|
| 1809 |
++ |
|
| 1810 |
++#define GEMAC_NO_PHY BIT(0) |
|
| 1811 |
++ |
|
| 1812 |
++struct ls1012a_eth_platform_data {
|
|
| 1813 |
++ /* device specific information */ |
|
| 1814 |
++ u32 device_flags; |
|
| 1815 |
++ char name[16]; |
|
| 1816 |
++ |
|
| 1817 |
++ /* board specific information */ |
|
| 1818 |
++ u32 mii_config; |
|
| 1819 |
++ u32 phy_flags; |
|
| 1820 |
++ u32 gem_id; |
|
| 1821 |
++ u32 bus_id; |
|
| 1822 |
++ u32 phy_id; |
|
| 1823 |
++ u32 mdio_muxval; |
|
| 1824 |
++ u8 mac_addr[ETH_ALEN]; |
|
| 1825 |
++}; |
|
| 1826 |
++ |
|
| 1827 |
++struct ls1012a_mdio_platform_data {
|
|
| 1828 |
++ int enabled; |
|
| 1829 |
++ int irq[32]; |
|
| 1830 |
++ u32 phy_mask; |
|
| 1831 |
++ int mdc_div; |
|
| 1832 |
++}; |
|
| 1833 |
++ |
|
| 1834 |
++struct ls1012a_pfe_platform_data {
|
|
| 1835 |
++ struct ls1012a_eth_platform_data ls1012a_eth_pdata[3]; |
|
| 1836 |
++ struct ls1012a_mdio_platform_data ls1012a_mdio_pdata[3]; |
|
| 1837 |
++}; |
|
| 1838 |
++ |
|
| 1839 |
++#define NUM_GEMAC_SUPPORT 2 |
|
| 1840 |
++#define DRV_NAME "pfe-eth" |
|
| 1841 |
++#define DRV_VERSION "1.0" |
|
| 1842 |
++ |
|
| 1843 |
++#define LS1012A_TX_FAST_RECOVERY_TIMEOUT_MS 3 |
|
| 1844 |
++#define TX_POLL_TIMEOUT_MS 1000 |
|
| 1845 |
++ |
|
| 1846 |
++#define EMAC_TXQ_CNT 16 |
|
| 1847 |
++#define EMAC_TXQ_DEPTH (HIF_TX_DESC_NT) |
|
| 1848 |
++ |
|
| 1849 |
++#define JUMBO_FRAME_SIZE 10258 |
|
| 1850 |
++/* |
|
| 1851 |
++ * Client Tx queue threshold, for txQ flush condition. |
|
| 1852 |
++ * It must be smaller than the queue size (in case we ever change it in the |
|
| 1853 |
++ * future). |
|
| 1854 |
++ */ |
|
| 1855 |
++#define HIF_CL_TX_FLUSH_MARK 32 |
|
| 1856 |
++ |
|
| 1857 |
++/* |
|
| 1858 |
++ * Max number of TX resources (HIF descriptors or skbs) that will be released |
|
| 1859 |
++ * in a single go during batch recycling. |
|
| 1860 |
++ * Should be lower than the flush mark so the SW can provide the HW with a |
|
| 1861 |
++ * continuous stream of packets instead of bursts. |
|
| 1862 |
++ */ |
|
| 1863 |
++#define TX_FREE_MAX_COUNT 16 |
|
| 1864 |
++#define EMAC_RXQ_CNT 3 |
|
| 1865 |
++#define EMAC_RXQ_DEPTH HIF_RX_DESC_NT |
|
| 1866 |
++/* make sure clients can receive a full burst of packets */ |
|
| 1867 |
++#define EMAC_RMON_TXBYTES_POS 0x00 |
|
| 1868 |
++#define EMAC_RMON_RXBYTES_POS 0x14 |
|
| 1869 |
++ |
|
| 1870 |
++#define EMAC_QUEUENUM_MASK (emac_txq_cnt - 1) |
|
| 1871 |
++#define EMAC_MDIO_TIMEOUT 1000 |
|
| 1872 |
++#define MAX_UC_SPEC_ADDR_REG 31 |
|
| 1873 |
++ |
|
| 1874 |
++struct pfe_eth_fast_timer {
|
|
| 1875 |
++ int queuenum; |
|
| 1876 |
++ struct hrtimer timer; |
|
| 1877 |
++ void *base; |
|
| 1878 |
++}; |
|
| 1879 |
++ |
|
| 1880 |
++struct pfe_eth_priv_s {
|
|
| 1881 |
++ struct pfe *pfe; |
|
| 1882 |
++ struct hif_client_s client; |
|
| 1883 |
++ struct napi_struct lro_napi; |
|
| 1884 |
++ struct napi_struct low_napi; |
|
| 1885 |
++ struct napi_struct high_napi; |
|
| 1886 |
++ int low_tmu_q; |
|
| 1887 |
++ int high_tmu_q; |
|
| 1888 |
++ struct net_device_stats stats; |
|
| 1889 |
++ struct net_device *ndev; |
|
| 1890 |
++ int id; |
|
| 1891 |
++ int promisc; |
|
| 1892 |
++ unsigned int msg_enable; |
|
| 1893 |
++ unsigned int usr_features; |
|
| 1894 |
++ |
|
| 1895 |
++ spinlock_t lock; /* protect member variables */ |
|
| 1896 |
++ unsigned int event_status; |
|
| 1897 |
++ int irq; |
|
| 1898 |
++ void *EMAC_baseaddr; |
|
| 1899 |
++ /* This points to the EMAC base from where we access PHY */ |
|
| 1900 |
++ void *PHY_baseaddr; |
|
| 1901 |
++ void *GPI_baseaddr; |
|
| 1902 |
++ /* PHY stuff */ |
|
| 1903 |
++ struct phy_device *phydev; |
|
| 1904 |
++ int oldspeed; |
|
| 1905 |
++ int oldduplex; |
|
| 1906 |
++ int oldlink; |
|
| 1907 |
++ /* mdio info */ |
|
| 1908 |
++ int mdc_div; |
|
| 1909 |
++ struct mii_bus *mii_bus; |
|
| 1910 |
++ struct clk *gemtx_clk; |
|
| 1911 |
++ int wol; |
|
| 1912 |
++ int pause_flag; |
|
| 1913 |
++ |
|
| 1914 |
++ int default_priority; |
|
| 1915 |
++ struct pfe_eth_fast_timer fast_tx_timeout[EMAC_TXQ_CNT]; |
|
| 1916 |
++ |
|
| 1917 |
++ struct ls1012a_eth_platform_data *einfo; |
|
| 1918 |
++ struct sk_buff *skb_inflight[EMAC_RXQ_CNT + 6]; |
|
| 1919 |
++ |
|
| 1920 |
++#ifdef PFE_ETH_TX_STATS |
|
| 1921 |
++ unsigned int stop_queue_total[EMAC_TXQ_CNT]; |
|
| 1922 |
++ unsigned int stop_queue_hif[EMAC_TXQ_CNT]; |
|
| 1923 |
++ unsigned int stop_queue_hif_client[EMAC_TXQ_CNT]; |
|
| 1924 |
++ unsigned int stop_queue_credit[EMAC_TXQ_CNT]; |
|
| 1925 |
++ unsigned int clean_fail[EMAC_TXQ_CNT]; |
|
| 1926 |
++ unsigned int was_stopped[EMAC_TXQ_CNT]; |
|
| 1927 |
++#endif |
|
| 1928 |
++ |
|
| 1929 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 1930 |
++ unsigned int napi_counters[NAPI_MAX_COUNT]; |
|
| 1931 |
++#endif |
|
| 1932 |
++ unsigned int frags_inflight[EMAC_RXQ_CNT + 6]; |
|
| 1933 |
++}; |
|
| 1934 |
++ |
|
| 1935 |
++struct pfe_eth {
|
|
| 1936 |
++ struct pfe_eth_priv_s *eth_priv[3]; |
|
| 1937 |
++}; |
|
| 1938 |
++ |
|
| 1939 |
++int pfe_eth_init(struct pfe *pfe); |
|
| 1940 |
++void pfe_eth_exit(struct pfe *pfe); |
|
| 1941 |
++int pfe_eth_suspend(struct net_device *dev); |
|
| 1942 |
++int pfe_eth_resume(struct net_device *dev); |
|
| 1943 |
++int pfe_eth_mdio_reset(struct mii_bus *bus); |
|
| 1944 |
++ |
|
| 1945 |
++#endif /* _PFE_ETH_H_ */ |
|
| 1946 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_firmware.h b/drivers/staging/fsl_ppfe/pfe_firmware.h |
|
| 1947 |
+new file mode 100644 |
|
| 1948 |
+index 000000000000..5ade848b9d2d |
|
| 1949 |
+--- /dev/null |
|
| 1950 |
+@@ -0,0 +1,32 @@ |
|
| 1951 |
++/* |
|
| 1952 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 1953 |
++ * Copyright 2017 NXP |
|
| 1954 |
++ * |
|
| 1955 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 1956 |
++ * it under the terms of the GNU General Public License as published by |
|
| 1957 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 1958 |
++ * (at your option) any later version. |
|
| 1959 |
++ * |
|
| 1960 |
++ * This program is distributed in the hope that it will be useful, |
|
| 1961 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 1962 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 1963 |
++ * GNU General Public License for more details. |
|
| 1964 |
++ * |
|
| 1965 |
++ * You should have received a copy of the GNU General Public License |
|
| 1966 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 1967 |
++ */ |
|
| 1968 |
++ |
|
| 1969 |
++#ifndef _PFE_FIRMWARE_H_ |
|
| 1970 |
++#define _PFE_FIRMWARE_H_ |
|
| 1971 |
++ |
|
| 1972 |
++#define CLASS_FIRMWARE_FILENAME "ppfe_class_ls1012a.elf" |
|
| 1973 |
++#define TMU_FIRMWARE_FILENAME "ppfe_tmu_ls1012a.elf" |
|
| 1974 |
++ |
|
| 1975 |
++#define PFE_FW_CHECK_PASS 0 |
|
| 1976 |
++#define PFE_FW_CHECK_FAIL 1 |
|
| 1977 |
++#define NUM_PFE_FW 3 |
|
| 1978 |
++ |
|
| 1979 |
++int pfe_firmware_init(struct pfe *pfe); |
|
| 1980 |
++void pfe_firmware_exit(struct pfe *pfe); |
|
| 1981 |
++ |
|
| 1982 |
++#endif /* _PFE_FIRMWARE_H_ */ |
|
| 1983 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif.h b/drivers/staging/fsl_ppfe/pfe_hif.h |
|
| 1984 |
+new file mode 100644 |
|
| 1985 |
+index 000000000000..6e36f0c1f4ff |
|
| 1986 |
+--- /dev/null |
|
| 1987 |
+@@ -0,0 +1,211 @@ |
|
| 1988 |
++/* |
|
| 1989 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 1990 |
++ * Copyright 2017 NXP |
|
| 1991 |
++ * |
|
| 1992 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 1993 |
++ * it under the terms of the GNU General Public License as published by |
|
| 1994 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 1995 |
++ * (at your option) any later version. |
|
| 1996 |
++ * |
|
| 1997 |
++ * This program is distributed in the hope that it will be useful, |
|
| 1998 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 1999 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 2000 |
++ * GNU General Public License for more details. |
|
| 2001 |
++ * |
|
| 2002 |
++ * You should have received a copy of the GNU General Public License |
|
| 2003 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 2004 |
++ */ |
|
| 2005 |
++ |
|
| 2006 |
++#ifndef _PFE_HIF_H_ |
|
| 2007 |
++#define _PFE_HIF_H_ |
|
| 2008 |
++ |
|
| 2009 |
++#include <linux/netdevice.h> |
|
| 2010 |
++ |
|
| 2011 |
++#define HIF_NAPI_STATS |
|
| 2012 |
++ |
|
| 2013 |
++#define HIF_CLIENT_QUEUES_MAX 16 |
|
| 2014 |
++#define HIF_RX_POLL_WEIGHT 64 |
|
| 2015 |
++ |
|
| 2016 |
++#define HIF_RX_PKT_MIN_SIZE 0x800 /* 2KB */ |
|
| 2017 |
++#define HIF_RX_PKT_MIN_SIZE_MASK ~(HIF_RX_PKT_MIN_SIZE - 1) |
|
| 2018 |
++#define ROUND_MIN_RX_SIZE(_sz) (((_sz) + (HIF_RX_PKT_MIN_SIZE - 1)) \ |
|
| 2019 |
++ & HIF_RX_PKT_MIN_SIZE_MASK) |
|
| 2020 |
++#define PRESENT_OFST_IN_PAGE(_buf) (((unsigned long int)(_buf) & (PAGE_SIZE \ |
|
| 2021 |
++ - 1)) & HIF_RX_PKT_MIN_SIZE_MASK) |
|
| 2022 |
++ |
|
| 2023 |
++enum {
|
|
| 2024 |
++ NAPI_SCHED_COUNT = 0, |
|
| 2025 |
++ NAPI_POLL_COUNT, |
|
| 2026 |
++ NAPI_PACKET_COUNT, |
|
| 2027 |
++ NAPI_DESC_COUNT, |
|
| 2028 |
++ NAPI_FULL_BUDGET_COUNT, |
|
| 2029 |
++ NAPI_CLIENT_FULL_COUNT, |
|
| 2030 |
++ NAPI_MAX_COUNT |
|
| 2031 |
++}; |
|
| 2032 |
++ |
|
| 2033 |
++/* |
|
| 2034 |
++ * HIF_TX_DESC_NT value should be always greter than 4, |
|
| 2035 |
++ * Otherwise HIF_TX_POLL_MARK will become zero. |
|
| 2036 |
++ */ |
|
| 2037 |
++#define HIF_RX_DESC_NT 256 |
|
| 2038 |
++#define HIF_TX_DESC_NT 2048 |
|
| 2039 |
++ |
|
| 2040 |
++#define HIF_FIRST_BUFFER BIT(0) |
|
| 2041 |
++#define HIF_LAST_BUFFER BIT(1) |
|
| 2042 |
++#define HIF_DONT_DMA_MAP BIT(2) |
|
| 2043 |
++#define HIF_DATA_VALID BIT(3) |
|
| 2044 |
++#define HIF_TSO BIT(4) |
|
| 2045 |
++ |
|
| 2046 |
++enum {
|
|
| 2047 |
++ PFE_CL_GEM0 = 0, |
|
| 2048 |
++ PFE_CL_GEM1, |
|
| 2049 |
++ HIF_CLIENTS_MAX |
|
| 2050 |
++}; |
|
| 2051 |
++ |
|
| 2052 |
++/*structure to store client queue info */ |
|
| 2053 |
++struct hif_rx_queue {
|
|
| 2054 |
++ struct rx_queue_desc *base; |
|
| 2055 |
++ u32 size; |
|
| 2056 |
++ u32 write_idx; |
|
| 2057 |
++}; |
|
| 2058 |
++ |
|
| 2059 |
++struct hif_tx_queue {
|
|
| 2060 |
++ struct tx_queue_desc *base; |
|
| 2061 |
++ u32 size; |
|
| 2062 |
++ u32 ack_idx; |
|
| 2063 |
++}; |
|
| 2064 |
++ |
|
| 2065 |
++/*Structure to store the client info */ |
|
| 2066 |
++struct hif_client {
|
|
| 2067 |
++ int rx_qn; |
|
| 2068 |
++ struct hif_rx_queue rx_q[HIF_CLIENT_QUEUES_MAX]; |
|
| 2069 |
++ int tx_qn; |
|
| 2070 |
++ struct hif_tx_queue tx_q[HIF_CLIENT_QUEUES_MAX]; |
|
| 2071 |
++}; |
|
| 2072 |
++ |
|
| 2073 |
++/*HIF hardware buffer descriptor */ |
|
| 2074 |
++struct hif_desc {
|
|
| 2075 |
++ u32 ctrl; |
|
| 2076 |
++ u32 status; |
|
| 2077 |
++ u32 data; |
|
| 2078 |
++ u32 next; |
|
| 2079 |
++}; |
|
| 2080 |
++ |
|
| 2081 |
++struct __hif_desc {
|
|
| 2082 |
++ u32 ctrl; |
|
| 2083 |
++ u32 status; |
|
| 2084 |
++ u32 data; |
|
| 2085 |
++}; |
|
| 2086 |
++ |
|
| 2087 |
++struct hif_desc_sw {
|
|
| 2088 |
++ dma_addr_t data; |
|
| 2089 |
++ u16 len; |
|
| 2090 |
++ u8 client_id; |
|
| 2091 |
++ u8 q_no; |
|
| 2092 |
++ u16 flags; |
|
| 2093 |
++}; |
|
| 2094 |
++ |
|
| 2095 |
++struct hif_hdr {
|
|
| 2096 |
++ u8 client_id; |
|
| 2097 |
++ u8 q_num; |
|
| 2098 |
++ u16 client_ctrl; |
|
| 2099 |
++ u16 client_ctrl1; |
|
| 2100 |
++}; |
|
| 2101 |
++ |
|
| 2102 |
++struct __hif_hdr {
|
|
| 2103 |
++ union {
|
|
| 2104 |
++ struct hif_hdr hdr; |
|
| 2105 |
++ u32 word[2]; |
|
| 2106 |
++ }; |
|
| 2107 |
++}; |
|
| 2108 |
++ |
|
| 2109 |
++struct hif_ipsec_hdr {
|
|
| 2110 |
++ u16 sa_handle[2]; |
|
| 2111 |
++} __packed; |
|
| 2112 |
++ |
|
| 2113 |
++/* HIF_CTRL_TX... defines */ |
|
| 2114 |
++#define HIF_CTRL_TX_CHECKSUM BIT(2) |
|
| 2115 |
++ |
|
| 2116 |
++/* HIF_CTRL_RX... defines */ |
|
| 2117 |
++#define HIF_CTRL_RX_OFFSET_OFST (24) |
|
| 2118 |
++#define HIF_CTRL_RX_CHECKSUMMED BIT(2) |
|
| 2119 |
++#define HIF_CTRL_RX_CONTINUED BIT(1) |
|
| 2120 |
++ |
|
| 2121 |
++struct pfe_hif {
|
|
| 2122 |
++ /* To store registered clients in hif layer */ |
|
| 2123 |
++ struct hif_client client[HIF_CLIENTS_MAX]; |
|
| 2124 |
++ struct hif_shm *shm; |
|
| 2125 |
++ int irq; |
|
| 2126 |
++ |
|
| 2127 |
++ void *descr_baseaddr_v; |
|
| 2128 |
++ unsigned long descr_baseaddr_p; |
|
| 2129 |
++ |
|
| 2130 |
++ struct hif_desc *rx_base; |
|
| 2131 |
++ u32 rx_ring_size; |
|
| 2132 |
++ u32 rxtoclean_index; |
|
| 2133 |
++ void *rx_buf_addr[HIF_RX_DESC_NT]; |
|
| 2134 |
++ int rx_buf_len[HIF_RX_DESC_NT]; |
|
| 2135 |
++ unsigned int qno; |
|
| 2136 |
++ unsigned int client_id; |
|
| 2137 |
++ unsigned int client_ctrl; |
|
| 2138 |
++ unsigned int started; |
|
| 2139 |
++ |
|
| 2140 |
++ struct hif_desc *tx_base; |
|
| 2141 |
++ u32 tx_ring_size; |
|
| 2142 |
++ u32 txtosend; |
|
| 2143 |
++ u32 txtoclean; |
|
| 2144 |
++ u32 txavail; |
|
| 2145 |
++ u32 txtoflush; |
|
| 2146 |
++ struct hif_desc_sw tx_sw_queue[HIF_TX_DESC_NT]; |
|
| 2147 |
++ |
|
| 2148 |
++/* tx_lock synchronizes hif packet tx as well as pfe_hif structure access */ |
|
| 2149 |
++ spinlock_t tx_lock; |
|
| 2150 |
++/* lock synchronizes hif rx queue processing */ |
|
| 2151 |
++ spinlock_t lock; |
|
| 2152 |
++ struct net_device dummy_dev; |
|
| 2153 |
++ struct napi_struct napi; |
|
| 2154 |
++ struct device *dev; |
|
| 2155 |
++ |
|
| 2156 |
++#ifdef HIF_NAPI_STATS |
|
| 2157 |
++ unsigned int napi_counters[NAPI_MAX_COUNT]; |
|
| 2158 |
++#endif |
|
| 2159 |
++ struct tasklet_struct tx_cleanup_tasklet; |
|
| 2160 |
++}; |
|
| 2161 |
++ |
|
| 2162 |
++void __hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int |
|
| 2163 |
++ q_no, void *data, u32 len, unsigned int flags); |
|
| 2164 |
++int hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int q_no, |
|
| 2165 |
++ void *data, unsigned int len); |
|
| 2166 |
++void __hif_tx_done_process(struct pfe_hif *hif, int count); |
|
| 2167 |
++void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int |
|
| 2168 |
++ data2); |
|
| 2169 |
++int pfe_hif_init(struct pfe *pfe); |
|
| 2170 |
++void pfe_hif_exit(struct pfe *pfe); |
|
| 2171 |
++void pfe_hif_rx_idle(struct pfe_hif *hif); |
|
| 2172 |
++static inline void hif_tx_done_process(struct pfe_hif *hif, int count) |
|
| 2173 |
++{
|
|
| 2174 |
++ spin_lock_bh(&hif->tx_lock); |
|
| 2175 |
++ __hif_tx_done_process(hif, count); |
|
| 2176 |
++ spin_unlock_bh(&hif->tx_lock); |
|
| 2177 |
++} |
|
| 2178 |
++ |
|
| 2179 |
++static inline void hif_tx_lock(struct pfe_hif *hif) |
|
| 2180 |
++{
|
|
| 2181 |
++ spin_lock_bh(&hif->tx_lock); |
|
| 2182 |
++} |
|
| 2183 |
++ |
|
| 2184 |
++static inline void hif_tx_unlock(struct pfe_hif *hif) |
|
| 2185 |
++{
|
|
| 2186 |
++ spin_unlock_bh(&hif->tx_lock); |
|
| 2187 |
++} |
|
| 2188 |
++ |
|
| 2189 |
++static inline int __hif_tx_avail(struct pfe_hif *hif) |
|
| 2190 |
++{
|
|
| 2191 |
++ return hif->txavail; |
|
| 2192 |
++} |
|
| 2193 |
++ |
|
| 2194 |
++#define __memcpy8(dst, src) memcpy(dst, src, 8) |
|
| 2195 |
++#define __memcpy12(dst, src) memcpy(dst, src, 12) |
|
| 2196 |
++#define __memcpy(dst, src, len) memcpy(dst, src, len) |
|
| 2197 |
++ |
|
| 2198 |
++#endif /* _PFE_HIF_H_ */ |
|
| 2199 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.h b/drivers/staging/fsl_ppfe/pfe_hif_lib.h |
|
| 2200 |
+new file mode 100644 |
|
| 2201 |
+index 000000000000..49e7b5f1f9c3 |
|
| 2202 |
+--- /dev/null |
|
| 2203 |
+@@ -0,0 +1,239 @@ |
|
| 2204 |
++/* |
|
| 2205 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 2206 |
++ * Copyright 2017 NXP |
|
| 2207 |
++ * |
|
| 2208 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 2209 |
++ * it under the terms of the GNU General Public License as published by |
|
| 2210 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 2211 |
++ * (at your option) any later version. |
|
| 2212 |
++ * |
|
| 2213 |
++ * This program is distributed in the hope that it will be useful, |
|
| 2214 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 2215 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 2216 |
++ * GNU General Public License for more details. |
|
| 2217 |
++ * |
|
| 2218 |
++ * You should have received a copy of the GNU General Public License |
|
| 2219 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 2220 |
++ */ |
|
| 2221 |
++ |
|
| 2222 |
++#ifndef _PFE_HIF_LIB_H_ |
|
| 2223 |
++#define _PFE_HIF_LIB_H_ |
|
| 2224 |
++ |
|
| 2225 |
++#include "pfe_hif.h" |
|
| 2226 |
++ |
|
| 2227 |
++#define HIF_CL_REQ_TIMEOUT 10 |
|
| 2228 |
++#define GFP_DMA_PFE 0 |
|
| 2229 |
++ |
|
| 2230 |
++enum {
|
|
| 2231 |
++ REQUEST_CL_REGISTER = 0, |
|
| 2232 |
++ REQUEST_CL_UNREGISTER, |
|
| 2233 |
++ HIF_REQUEST_MAX |
|
| 2234 |
++}; |
|
| 2235 |
++ |
|
| 2236 |
++enum {
|
|
| 2237 |
++ /* Event to indicate that client rx queue is reached water mark level */ |
|
| 2238 |
++ EVENT_HIGH_RX_WM = 0, |
|
| 2239 |
++ /* Event to indicate that, packet received for client */ |
|
| 2240 |
++ EVENT_RX_PKT_IND, |
|
| 2241 |
++ /* Event to indicate that, packet tx done for client */ |
|
| 2242 |
++ EVENT_TXDONE_IND, |
|
| 2243 |
++ HIF_EVENT_MAX |
|
| 2244 |
++}; |
|
| 2245 |
++ |
|
| 2246 |
++/*structure to store client queue info */ |
|
| 2247 |
++ |
|
| 2248 |
++/*structure to store client queue info */ |
|
| 2249 |
++struct hif_client_rx_queue {
|
|
| 2250 |
++ struct rx_queue_desc *base; |
|
| 2251 |
++ u32 size; |
|
| 2252 |
++ u32 read_idx; |
|
| 2253 |
++ u32 write_idx; |
|
| 2254 |
++}; |
|
| 2255 |
++ |
|
| 2256 |
++struct hif_client_tx_queue {
|
|
| 2257 |
++ struct tx_queue_desc *base; |
|
| 2258 |
++ u32 size; |
|
| 2259 |
++ u32 read_idx; |
|
| 2260 |
++ u32 write_idx; |
|
| 2261 |
++ u32 tx_pending; |
|
| 2262 |
++ unsigned long jiffies_last_packet; |
|
| 2263 |
++ u32 nocpy_flag; |
|
| 2264 |
++ u32 prev_tmu_tx_pkts; |
|
| 2265 |
++ u32 done_tmu_tx_pkts; |
|
| 2266 |
++}; |
|
| 2267 |
++ |
|
| 2268 |
++struct hif_client_s {
|
|
| 2269 |
++ int id; |
|
| 2270 |
++ int tx_qn; |
|
| 2271 |
++ int rx_qn; |
|
| 2272 |
++ void *rx_qbase; |
|
| 2273 |
++ void *tx_qbase; |
|
| 2274 |
++ int tx_qsize; |
|
| 2275 |
++ int rx_qsize; |
|
| 2276 |
++ int cpu_id; |
|
| 2277 |
++ struct hif_client_tx_queue tx_q[HIF_CLIENT_QUEUES_MAX]; |
|
| 2278 |
++ struct hif_client_rx_queue rx_q[HIF_CLIENT_QUEUES_MAX]; |
|
| 2279 |
++ int (*event_handler)(void *priv, int event, int data); |
|
| 2280 |
++ unsigned long queue_mask[HIF_EVENT_MAX]; |
|
| 2281 |
++ struct pfe *pfe; |
|
| 2282 |
++ void *priv; |
|
| 2283 |
++}; |
|
| 2284 |
++ |
|
| 2285 |
++/* |
|
| 2286 |
++ * Client specific shared memory |
|
| 2287 |
++ * It contains number of Rx/Tx queues, base addresses and queue sizes |
|
| 2288 |
++ */ |
|
| 2289 |
++struct hif_client_shm {
|
|
| 2290 |
++ u32 ctrl; /*0-7: number of Rx queues, 8-15: number of tx queues */ |
|
| 2291 |
++ unsigned long rx_qbase; /*Rx queue base address */ |
|
| 2292 |
++ u32 rx_qsize; /*each Rx queue size, all Rx queues are of same size */ |
|
| 2293 |
++ unsigned long tx_qbase; /* Tx queue base address */ |
|
| 2294 |
++ u32 tx_qsize; /*each Tx queue size, all Tx queues are of same size */ |
|
| 2295 |
++}; |
|
| 2296 |
++ |
|
| 2297 |
++/*Client shared memory ctrl bit description */ |
|
| 2298 |
++#define CLIENT_CTRL_RX_Q_CNT_OFST 0 |
|
| 2299 |
++#define CLIENT_CTRL_TX_Q_CNT_OFST 8 |
|
| 2300 |
++#define CLIENT_CTRL_RX_Q_CNT(ctrl) (((ctrl) >> CLIENT_CTRL_RX_Q_CNT_OFST) \ |
|
| 2301 |
++ & 0xFF) |
|
| 2302 |
++#define CLIENT_CTRL_TX_Q_CNT(ctrl) (((ctrl) >> CLIENT_CTRL_TX_Q_CNT_OFST) \ |
|
| 2303 |
++ & 0xFF) |
|
| 2304 |
++ |
|
| 2305 |
++/* |
|
| 2306 |
++ * Shared memory used to communicate between HIF driver and host/client drivers |
|
| 2307 |
++ * Before starting the hif driver rx_buf_pool ans rx_buf_pool_cnt should be |
|
| 2308 |
++ * initialized with host buffers and buffers count in the pool. |
|
| 2309 |
++ * rx_buf_pool_cnt should be >= HIF_RX_DESC_NT. |
|
| 2310 |
++ * |
|
| 2311 |
++ */ |
|
| 2312 |
++struct hif_shm {
|
|
| 2313 |
++ u32 rx_buf_pool_cnt; /*Number of rx buffers available*/ |
|
| 2314 |
++ /*Rx buffers required to initialize HIF rx descriptors */ |
|
| 2315 |
++ void *rx_buf_pool[HIF_RX_DESC_NT]; |
|
| 2316 |
++ unsigned long g_client_status[2]; /*Global client status bit mask */ |
|
| 2317 |
++ /* Client specific shared memory */ |
|
| 2318 |
++ struct hif_client_shm client[HIF_CLIENTS_MAX]; |
|
| 2319 |
++}; |
|
| 2320 |
++ |
|
| 2321 |
++#define CL_DESC_OWN BIT(31) |
|
| 2322 |
++/* This sets owner ship to HIF driver */ |
|
| 2323 |
++#define CL_DESC_LAST BIT(30) |
|
| 2324 |
++/* This indicates last packet for multi buffers handling */ |
|
| 2325 |
++#define CL_DESC_FIRST BIT(29) |
|
| 2326 |
++/* This indicates first packet for multi buffers handling */ |
|
| 2327 |
++ |
|
| 2328 |
++#define CL_DESC_BUF_LEN(x) ((x) & 0xFFFF) |
|
| 2329 |
++#define CL_DESC_FLAGS(x) (((x) & 0xF) << 16) |
|
| 2330 |
++#define CL_DESC_GET_FLAGS(x) (((x) >> 16) & 0xF) |
|
| 2331 |
++ |
|
| 2332 |
++struct rx_queue_desc {
|
|
| 2333 |
++ void *data; |
|
| 2334 |
++ u32 ctrl; /*0-15bit len, 16-20bit flags, 31bit owner*/ |
|
| 2335 |
++ u32 client_ctrl; |
|
| 2336 |
++}; |
|
| 2337 |
++ |
|
| 2338 |
++struct tx_queue_desc {
|
|
| 2339 |
++ void *data; |
|
| 2340 |
++ u32 ctrl; /*0-15bit len, 16-20bit flags, 31bit owner*/ |
|
| 2341 |
++}; |
|
| 2342 |
++ |
|
| 2343 |
++/* HIF Rx is not working properly for 2-byte aligned buffers and |
|
| 2344 |
++ * ip_header should be 4byte aligned for better iperformance. |
|
| 2345 |
++ * "ip_header = 64 + 6(hif_header) + 14 (MAC Header)" will be 4byte aligned. |
|
| 2346 |
++ */ |
|
| 2347 |
++#define PFE_PKT_HEADER_SZ sizeof(struct hif_hdr) |
|
| 2348 |
++/* must be big enough for headroom, pkt size and skb shared info */ |
|
| 2349 |
++#define PFE_BUF_SIZE 2048 |
|
| 2350 |
++#define PFE_PKT_HEADROOM 128 |
|
| 2351 |
++ |
|
| 2352 |
++#define SKB_SHARED_INFO_SIZE (sizeof(struct skb_shared_info)) |
|
| 2353 |
++#define PFE_PKT_SIZE (PFE_BUF_SIZE - PFE_PKT_HEADROOM \ |
|
| 2354 |
++ - SKB_SHARED_INFO_SIZE) |
|
| 2355 |
++#define MAX_L2_HDR_SIZE 14 /* Not correct for VLAN/PPPoE */ |
|
| 2356 |
++#define MAX_L3_HDR_SIZE 20 /* Not correct for IPv6 */ |
|
| 2357 |
++#define MAX_L4_HDR_SIZE 60 /* TCP with maximum options */ |
|
| 2358 |
++#define MAX_HDR_SIZE (MAX_L2_HDR_SIZE + MAX_L3_HDR_SIZE \ |
|
| 2359 |
++ + MAX_L4_HDR_SIZE) |
|
| 2360 |
++/* Used in page mode to clamp packet size to the maximum supported by the hif |
|
| 2361 |
++ *hw interface (<16KiB) |
|
| 2362 |
++ */ |
|
| 2363 |
++#define MAX_PFE_PKT_SIZE 16380UL |
|
| 2364 |
++ |
|
| 2365 |
++extern unsigned int pfe_pkt_size; |
|
| 2366 |
++extern unsigned int pfe_pkt_headroom; |
|
| 2367 |
++extern unsigned int page_mode; |
|
| 2368 |
++extern unsigned int lro_mode; |
|
| 2369 |
++extern unsigned int tx_qos; |
|
| 2370 |
++extern unsigned int emac_txq_cnt; |
|
| 2371 |
++ |
|
| 2372 |
++int pfe_hif_lib_init(struct pfe *pfe); |
|
| 2373 |
++void pfe_hif_lib_exit(struct pfe *pfe); |
|
| 2374 |
++int hif_lib_client_register(struct hif_client_s *client); |
|
| 2375 |
++int hif_lib_client_unregister(struct hif_client_s *client); |
|
| 2376 |
++void __hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void |
|
| 2377 |
++ *data, unsigned int len, u32 client_ctrl, |
|
| 2378 |
++ unsigned int flags, void *client_data); |
|
| 2379 |
++int hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void *data, |
|
| 2380 |
++ unsigned int len, u32 client_ctrl, void *client_data); |
|
| 2381 |
++void hif_lib_indicate_client(int cl_id, int event, int data); |
|
| 2382 |
++int hif_lib_event_handler_start(struct hif_client_s *client, int event, int |
|
| 2383 |
++ data); |
|
| 2384 |
++int hif_lib_tmu_queue_start(struct hif_client_s *client, int qno); |
|
| 2385 |
++int hif_lib_tmu_queue_stop(struct hif_client_s *client, int qno); |
|
| 2386 |
++void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, |
|
| 2387 |
++ unsigned int *flags, int count); |
|
| 2388 |
++void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int |
|
| 2389 |
++ *ofst, unsigned int *rx_ctrl, |
|
| 2390 |
++ unsigned int *desc_ctrl, void **priv_data); |
|
| 2391 |
++void hif_lib_set_rx_cpu_affinity(struct hif_client_s *client, int cpu_id); |
|
| 2392 |
++void hif_lib_set_tx_queue_nocpy(struct hif_client_s *client, int qno, int |
|
| 2393 |
++ enable); |
|
| 2394 |
++static inline int hif_lib_tx_avail(struct hif_client_s *client, unsigned int |
|
| 2395 |
++ qno) |
|
| 2396 |
++{
|
|
| 2397 |
++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; |
|
| 2398 |
++ |
|
| 2399 |
++ return (queue->size - queue->tx_pending); |
|
| 2400 |
++} |
|
| 2401 |
++ |
|
| 2402 |
++static inline int hif_lib_get_tx_wr_index(struct hif_client_s *client, unsigned |
|
| 2403 |
++ int qno) |
|
| 2404 |
++{
|
|
| 2405 |
++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; |
|
| 2406 |
++ |
|
| 2407 |
++ return queue->write_idx; |
|
| 2408 |
++} |
|
| 2409 |
++ |
|
| 2410 |
++static inline int hif_lib_tx_pending(struct hif_client_s *client, unsigned int |
|
| 2411 |
++ qno) |
|
| 2412 |
++{
|
|
| 2413 |
++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; |
|
| 2414 |
++ |
|
| 2415 |
++ return queue->tx_pending; |
|
| 2416 |
++} |
|
| 2417 |
++ |
|
| 2418 |
++#define hif_lib_tx_credit_avail(pfe, id, qno) \ |
|
| 2419 |
++ ((pfe)->tmu_credit.tx_credit[id][qno]) |
|
| 2420 |
++ |
|
| 2421 |
++#define hif_lib_tx_credit_max(pfe, id, qno) \ |
|
| 2422 |
++ ((pfe)->tmu_credit.tx_credit_max[id][qno]) |
|
| 2423 |
++ |
|
| 2424 |
++/* |
|
| 2425 |
++ * Test comment |
|
| 2426 |
++ */ |
|
| 2427 |
++#define hif_lib_tx_credit_use(pfe, id, qno, credit) \ |
|
| 2428 |
++ ({ typeof(pfe) pfe_ = pfe; \
|
|
| 2429 |
++ typeof(id) id_ = id; \ |
|
| 2430 |
++ typeof(qno) qno_ = qno_; \ |
|
| 2431 |
++ typeof(credit) credit_ = credit; \ |
|
| 2432 |
++ do { \
|
|
| 2433 |
++ if (tx_qos) { \
|
|
| 2434 |
++ (pfe_)->tmu_credit.tx_credit[id_][qno_]\ |
|
| 2435 |
++ -= credit_; \ |
|
| 2436 |
++ (pfe_)->tmu_credit.tx_packets[id_][qno_]\ |
|
| 2437 |
++ += credit_; \ |
|
| 2438 |
++ } \ |
|
| 2439 |
++ } while (0); \ |
|
| 2440 |
++ }) |
|
| 2441 |
++ |
|
| 2442 |
++#endif /* _PFE_HIF_LIB_H_ */ |
|
| 2443 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hw.h b/drivers/staging/fsl_ppfe/pfe_hw.h |
|
| 2444 |
+new file mode 100644 |
|
| 2445 |
+index 000000000000..53b5fe1400ec |
|
| 2446 |
+--- /dev/null |
|
| 2447 |
+@@ -0,0 +1,27 @@ |
|
| 2448 |
++/* |
|
| 2449 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 2450 |
++ * Copyright 2017 NXP |
|
| 2451 |
++ * |
|
| 2452 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 2453 |
++ * it under the terms of the GNU General Public License as published by |
|
| 2454 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 2455 |
++ * (at your option) any later version. |
|
| 2456 |
++ * |
|
| 2457 |
++ * This program is distributed in the hope that it will be useful, |
|
| 2458 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 2459 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 2460 |
++ * GNU General Public License for more details. |
|
| 2461 |
++ * |
|
| 2462 |
++ * You should have received a copy of the GNU General Public License |
|
| 2463 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 2464 |
++ */ |
|
| 2465 |
++ |
|
| 2466 |
++#ifndef _PFE_HW_H_ |
|
| 2467 |
++#define _PFE_HW_H_ |
|
| 2468 |
++ |
|
| 2469 |
++#define PE_SYS_CLK_RATIO 1 /* SYS/AXI = 250MHz, HFE = 500MHz */ |
|
| 2470 |
++ |
|
| 2471 |
++int pfe_hw_init(struct pfe *pfe, int resume); |
|
| 2472 |
++void pfe_hw_exit(struct pfe *pfe); |
|
| 2473 |
++ |
|
| 2474 |
++#endif /* _PFE_HW_H_ */ |
|
| 2475 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_mod.h b/drivers/staging/fsl_ppfe/pfe_mod.h |
|
| 2476 |
+new file mode 100644 |
|
| 2477 |
+index 000000000000..3012f17fef31 |
|
| 2478 |
+--- /dev/null |
|
| 2479 |
+@@ -0,0 +1,112 @@ |
|
| 2480 |
++/* |
|
| 2481 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 2482 |
++ * Copyright 2017 NXP |
|
| 2483 |
++ * |
|
| 2484 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 2485 |
++ * it under the terms of the GNU General Public License as published by |
|
| 2486 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 2487 |
++ * (at your option) any later version. |
|
| 2488 |
++ * |
|
| 2489 |
++ * This program is distributed in the hope that it will be useful, |
|
| 2490 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 2491 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 2492 |
++ * GNU General Public License for more details. |
|
| 2493 |
++ * |
|
| 2494 |
++ * You should have received a copy of the GNU General Public License |
|
| 2495 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 2496 |
++ */ |
|
| 2497 |
++ |
|
| 2498 |
++#ifndef _PFE_MOD_H_ |
|
| 2499 |
++#define _PFE_MOD_H_ |
|
| 2500 |
++ |
|
| 2501 |
++#include <linux/device.h> |
|
| 2502 |
++#include <linux/elf.h> |
|
| 2503 |
++ |
|
| 2504 |
++struct pfe; |
|
| 2505 |
++ |
|
| 2506 |
++#include "pfe_hw.h" |
|
| 2507 |
++#include "pfe_firmware.h" |
|
| 2508 |
++#include "pfe_ctrl.h" |
|
| 2509 |
++#include "pfe_hif.h" |
|
| 2510 |
++#include "pfe_hif_lib.h" |
|
| 2511 |
++#include "pfe_eth.h" |
|
| 2512 |
++#include "pfe_sysfs.h" |
|
| 2513 |
++#include "pfe_perfmon.h" |
|
| 2514 |
++#include "pfe_debugfs.h" |
|
| 2515 |
++ |
|
| 2516 |
++#define PHYID_MAX_VAL 32 |
|
| 2517 |
++ |
|
| 2518 |
++struct pfe_tmu_credit {
|
|
| 2519 |
++ /* Number of allowed TX packet in-flight, matches TMU queue size */ |
|
| 2520 |
++ unsigned int tx_credit[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; |
|
| 2521 |
++ unsigned int tx_credit_max[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; |
|
| 2522 |
++ unsigned int tx_packets[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; |
|
| 2523 |
++}; |
|
| 2524 |
++ |
|
| 2525 |
++struct pfe {
|
|
| 2526 |
++ struct regmap *scfg; |
|
| 2527 |
++ unsigned long ddr_phys_baseaddr; |
|
| 2528 |
++ void *ddr_baseaddr; |
|
| 2529 |
++ unsigned int ddr_size; |
|
| 2530 |
++ void *cbus_baseaddr; |
|
| 2531 |
++ void *apb_baseaddr; |
|
| 2532 |
++ unsigned long iram_phys_baseaddr; |
|
| 2533 |
++ void *iram_baseaddr; |
|
| 2534 |
++ unsigned long ipsec_phys_baseaddr; |
|
| 2535 |
++ void *ipsec_baseaddr; |
|
| 2536 |
++ int hif_irq; |
|
| 2537 |
++ int wol_irq; |
|
| 2538 |
++ int hif_client_irq; |
|
| 2539 |
++ struct device *dev; |
|
| 2540 |
++ struct dentry *dentry; |
|
| 2541 |
++ struct pfe_ctrl ctrl; |
|
| 2542 |
++ struct pfe_hif hif; |
|
| 2543 |
++ struct pfe_eth eth; |
|
| 2544 |
++ struct hif_client_s *hif_client[HIF_CLIENTS_MAX]; |
|
| 2545 |
++#if defined(CFG_DIAGS) |
|
| 2546 |
++ struct pfe_diags diags; |
|
| 2547 |
++#endif |
|
| 2548 |
++ struct pfe_tmu_credit tmu_credit; |
|
| 2549 |
++ struct pfe_cpumon cpumon; |
|
| 2550 |
++ struct pfe_memmon memmon; |
|
| 2551 |
++ int wake; |
|
| 2552 |
++ int mdio_muxval[PHYID_MAX_VAL]; |
|
| 2553 |
++ struct clk *hfe_clock; |
|
| 2554 |
++}; |
|
| 2555 |
++ |
|
| 2556 |
++extern struct pfe *pfe; |
|
| 2557 |
++ |
|
| 2558 |
++int pfe_probe(struct pfe *pfe); |
|
| 2559 |
++int pfe_remove(struct pfe *pfe); |
|
| 2560 |
++ |
|
| 2561 |
++/* DDR Mapping in reserved memory*/ |
|
| 2562 |
++#define ROUTE_TABLE_BASEADDR 0 |
|
| 2563 |
++#define ROUTE_TABLE_HASH_BITS 15 /* 32K entries */ |
|
| 2564 |
++#define ROUTE_TABLE_SIZE ((1 << ROUTE_TABLE_HASH_BITS) \ |
|
| 2565 |
++ * CLASS_ROUTE_SIZE) |
|
| 2566 |
++#define BMU2_DDR_BASEADDR (ROUTE_TABLE_BASEADDR + ROUTE_TABLE_SIZE) |
|
| 2567 |
++#define BMU2_BUF_COUNT (4096 - 256) |
|
| 2568 |
++/* This is to get a total DDR size of 12MiB */ |
|
| 2569 |
++#define BMU2_DDR_SIZE (DDR_BUF_SIZE * BMU2_BUF_COUNT) |
|
| 2570 |
++#define UTIL_CODE_BASEADDR (BMU2_DDR_BASEADDR + BMU2_DDR_SIZE) |
|
| 2571 |
++#define UTIL_CODE_SIZE (128 * SZ_1K) |
|
| 2572 |
++#define UTIL_DDR_DATA_BASEADDR (UTIL_CODE_BASEADDR + UTIL_CODE_SIZE) |
|
| 2573 |
++#define UTIL_DDR_DATA_SIZE (64 * SZ_1K) |
|
| 2574 |
++#define CLASS_DDR_DATA_BASEADDR (UTIL_DDR_DATA_BASEADDR + UTIL_DDR_DATA_SIZE) |
|
| 2575 |
++#define CLASS_DDR_DATA_SIZE (32 * SZ_1K) |
|
| 2576 |
++#define TMU_DDR_DATA_BASEADDR (CLASS_DDR_DATA_BASEADDR + CLASS_DDR_DATA_SIZE) |
|
| 2577 |
++#define TMU_DDR_DATA_SIZE (32 * SZ_1K) |
|
| 2578 |
++#define TMU_LLM_BASEADDR (TMU_DDR_DATA_BASEADDR + TMU_DDR_DATA_SIZE) |
|
| 2579 |
++#define TMU_LLM_QUEUE_LEN (8 * 512) |
|
| 2580 |
++/* Must be power of two and at least 16 * 8 = 128 bytes */ |
|
| 2581 |
++#define TMU_LLM_SIZE (4 * 16 * TMU_LLM_QUEUE_LEN) |
|
| 2582 |
++/* (4 TMU's x 16 queues x queue_len) */ |
|
| 2583 |
++ |
|
| 2584 |
++#define DDR_MAX_SIZE (TMU_LLM_BASEADDR + TMU_LLM_SIZE) |
|
| 2585 |
++ |
|
| 2586 |
++/* LMEM Mapping */ |
|
| 2587 |
++#define BMU1_LMEM_BASEADDR 0 |
|
| 2588 |
++#define BMU1_BUF_COUNT 256 |
|
| 2589 |
++#define BMU1_LMEM_SIZE (LMEM_BUF_SIZE * BMU1_BUF_COUNT) |
|
| 2590 |
++ |
|
| 2591 |
++#endif /* _PFE_MOD_H */ |
|
| 2592 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_perfmon.h b/drivers/staging/fsl_ppfe/pfe_perfmon.h |
|
| 2593 |
+new file mode 100644 |
|
| 2594 |
+index 000000000000..84908121a6fd |
|
| 2595 |
+--- /dev/null |
|
| 2596 |
+@@ -0,0 +1,38 @@ |
|
| 2597 |
++/* |
|
| 2598 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 2599 |
++ * Copyright 2017 NXP |
|
| 2600 |
++ * |
|
| 2601 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 2602 |
++ * it under the terms of the GNU General Public License as published by |
|
| 2603 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 2604 |
++ * (at your option) any later version. |
|
| 2605 |
++ * |
|
| 2606 |
++ * This program is distributed in the hope that it will be useful, |
|
| 2607 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 2608 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 2609 |
++ * GNU General Public License for more details. |
|
| 2610 |
++ * |
|
| 2611 |
++ * You should have received a copy of the GNU General Public License |
|
| 2612 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 2613 |
++ */ |
|
| 2614 |
++ |
|
| 2615 |
++#ifndef _PFE_PERFMON_H_ |
|
| 2616 |
++#define _PFE_PERFMON_H_ |
|
| 2617 |
++ |
|
| 2618 |
++#include "pfe/pfe.h" |
|
| 2619 |
++ |
|
| 2620 |
++#define CT_CPUMON_INTERVAL (1 * TIMER_TICKS_PER_SEC) |
|
| 2621 |
++ |
|
| 2622 |
++struct pfe_cpumon {
|
|
| 2623 |
++ u32 cpu_usage_pct[MAX_PE]; |
|
| 2624 |
++ u32 class_usage_pct; |
|
| 2625 |
++}; |
|
| 2626 |
++ |
|
| 2627 |
++struct pfe_memmon {
|
|
| 2628 |
++ u32 kernel_memory_allocated; |
|
| 2629 |
++}; |
|
| 2630 |
++ |
|
| 2631 |
++int pfe_perfmon_init(struct pfe *pfe); |
|
| 2632 |
++void pfe_perfmon_exit(struct pfe *pfe); |
|
| 2633 |
++ |
|
| 2634 |
++#endif /* _PFE_PERFMON_H_ */ |
|
| 2635 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_sysfs.h b/drivers/staging/fsl_ppfe/pfe_sysfs.h |
|
| 2636 |
+new file mode 100644 |
|
| 2637 |
+index 000000000000..4fb39c93cbf9 |
|
| 2638 |
+--- /dev/null |
|
| 2639 |
+@@ -0,0 +1,29 @@ |
|
| 2640 |
++/* |
|
| 2641 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 2642 |
++ * Copyright 2017 NXP |
|
| 2643 |
++ * |
|
| 2644 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 2645 |
++ * it under the terms of the GNU General Public License as published by |
|
| 2646 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 2647 |
++ * (at your option) any later version. |
|
| 2648 |
++ * |
|
| 2649 |
++ * This program is distributed in the hope that it will be useful, |
|
| 2650 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 2651 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 2652 |
++ * GNU General Public License for more details. |
|
| 2653 |
++ * |
|
| 2654 |
++ * You should have received a copy of the GNU General Public License |
|
| 2655 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 2656 |
++ */ |
|
| 2657 |
++ |
|
| 2658 |
++#ifndef _PFE_SYSFS_H_ |
|
| 2659 |
++#define _PFE_SYSFS_H_ |
|
| 2660 |
++ |
|
| 2661 |
++#include <linux/proc_fs.h> |
|
| 2662 |
++ |
|
| 2663 |
++u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset); |
|
| 2664 |
++ |
|
| 2665 |
++int pfe_sysfs_init(struct pfe *pfe); |
|
| 2666 |
++void pfe_sysfs_exit(struct pfe *pfe); |
|
| 2667 |
++ |
|
| 2668 |
++#endif /* _PFE_SYSFS_H_ */ |
|
| 2669 |
+-- |
|
| 2670 |
+2.14.2 |
|
| 2671 |
+ |
| 0 | 2672 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,8052 @@ |
| 0 |
+From 37dd30b10a56b9e26af0b7ae58e181d8845549c2 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Sat, 16 Sep 2017 14:22:17 +0530 |
|
| 3 |
+Subject: [PATCH 02/22] staging: fsl_ppfe/eth: introduce pfe driver |
|
| 4 |
+ |
|
| 5 |
+ This patch introduces Linux support for NXP's LS1012A Packet |
|
| 6 |
+Forwarding Engine (pfe_eth). LS1012A uses hardware packet forwarding |
|
| 7 |
+engine to provide high performance Ethernet interfaces. The device |
|
| 8 |
+includes two Ethernet ports. |
|
| 9 |
+ |
|
| 10 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 11 |
+Signed-off-by: Anjaneyulu Jagarlmudi <anji.jagarlmudi@nxp.com> |
|
| 12 |
+ |
|
| 13 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 14 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 15 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 16 |
+] |
|
| 17 |
+ |
|
| 18 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 19 |
+--- |
|
| 20 |
+ drivers/staging/fsl_ppfe/Kconfig | 20 + |
|
| 21 |
+ drivers/staging/fsl_ppfe/Makefile | 19 + |
|
| 22 |
+ drivers/staging/fsl_ppfe/TODO | 2 + |
|
| 23 |
+ drivers/staging/fsl_ppfe/pfe_ctrl.c | 238 +++ |
|
| 24 |
+ drivers/staging/fsl_ppfe/pfe_debugfs.c | 111 ++ |
|
| 25 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 2434 +++++++++++++++++++++++ |
|
| 26 |
+ drivers/staging/fsl_ppfe/pfe_firmware.c | 314 +++ |
|
| 27 |
+ drivers/staging/fsl_ppfe/pfe_hal.c | 1516 ++++++++++++++ |
|
| 28 |
+ drivers/staging/fsl_ppfe/pfe_hif.c | 1094 ++++++++++ |
|
| 29 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.c | 638 ++++++ |
|
| 30 |
+ drivers/staging/fsl_ppfe/pfe_hw.c | 176 ++ |
|
| 31 |
+ drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c | 394 ++++ |
|
| 32 |
+ drivers/staging/fsl_ppfe/pfe_mod.c | 141 ++ |
|
| 33 |
+ drivers/staging/fsl_ppfe/pfe_sysfs.c | 818 ++++++++ |
|
| 34 |
+ 14 files changed, 7915 insertions(+) |
|
| 35 |
+ create mode 100644 drivers/staging/fsl_ppfe/Kconfig |
|
| 36 |
+ create mode 100644 drivers/staging/fsl_ppfe/Makefile |
|
| 37 |
+ create mode 100644 drivers/staging/fsl_ppfe/TODO |
|
| 38 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_ctrl.c |
|
| 39 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_debugfs.c |
|
| 40 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 41 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_firmware.c |
|
| 42 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 43 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_hif.c |
|
| 44 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 45 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_hw.c |
|
| 46 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c |
|
| 47 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_mod.c |
|
| 48 |
+ create mode 100644 drivers/staging/fsl_ppfe/pfe_sysfs.c |
|
| 49 |
+ |
|
| 50 |
+diff --git a/drivers/staging/fsl_ppfe/Kconfig b/drivers/staging/fsl_ppfe/Kconfig |
|
| 51 |
+new file mode 100644 |
|
| 52 |
+index 000000000000..e40964354cad |
|
| 53 |
+--- /dev/null |
|
| 54 |
+@@ -0,0 +1,20 @@ |
|
| 55 |
++# |
|
| 56 |
++# Freescale Programmable Packet Forwarding Engine driver |
|
| 57 |
++# |
|
| 58 |
++config FSL_PPFE |
|
| 59 |
++ bool "Freescale PPFE Driver" |
|
| 60 |
++ default n |
|
| 61 |
++ ---help--- |
|
| 62 |
++ Freescale LS1012A SoC has a Programmable Packet Forwarding Engine. |
|
| 63 |
++ It provides two high performance ethernet interfaces. |
|
| 64 |
++ This driver initializes, programs and controls the PPFE. |
|
| 65 |
++ Use this driver to enable network connectivity on LS1012A platforms. |
|
| 66 |
++ |
|
| 67 |
++if FSL_PPFE |
|
| 68 |
++ |
|
| 69 |
++config FSL_PPFE_UTIL_DISABLED |
|
| 70 |
++ bool "Disable PPFE UTIL Processor Engine" |
|
| 71 |
++ ---help--- |
|
| 72 |
++ UTIL PE has to be enabled only if required. |
|
| 73 |
++ |
|
| 74 |
++endif # FSL_PPFE |
|
| 75 |
+diff --git a/drivers/staging/fsl_ppfe/Makefile b/drivers/staging/fsl_ppfe/Makefile |
|
| 76 |
+new file mode 100644 |
|
| 77 |
+index 000000000000..07cd351b9221 |
|
| 78 |
+--- /dev/null |
|
| 79 |
+@@ -0,0 +1,19 @@ |
|
| 80 |
++# |
|
| 81 |
++# Makefile for Freesecale PPFE driver |
|
| 82 |
++# |
|
| 83 |
++ |
|
| 84 |
++ccflags-y += -I$(src)/include -I$(src) |
|
| 85 |
++ |
|
| 86 |
++obj-m += pfe.o |
|
| 87 |
++ |
|
| 88 |
++pfe-y += pfe_mod.o \ |
|
| 89 |
++ pfe_hw.o \ |
|
| 90 |
++ pfe_firmware.o \ |
|
| 91 |
++ pfe_ctrl.o \ |
|
| 92 |
++ pfe_hif.o \ |
|
| 93 |
++ pfe_hif_lib.o\ |
|
| 94 |
++ pfe_eth.o \ |
|
| 95 |
++ pfe_sysfs.o \ |
|
| 96 |
++ pfe_debugfs.o \ |
|
| 97 |
++ pfe_ls1012a_platform.o \ |
|
| 98 |
++ pfe_hal.o |
|
| 99 |
+diff --git a/drivers/staging/fsl_ppfe/TODO b/drivers/staging/fsl_ppfe/TODO |
|
| 100 |
+new file mode 100644 |
|
| 101 |
+index 000000000000..43c48ccdf81a |
|
| 102 |
+--- /dev/null |
|
| 103 |
+@@ -0,0 +1,2 @@ |
|
| 104 |
++TODO: |
|
| 105 |
++ - provide pfe pe monitoring support |
|
| 106 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_ctrl.c b/drivers/staging/fsl_ppfe/pfe_ctrl.c |
|
| 107 |
+new file mode 100644 |
|
| 108 |
+index 000000000000..dfa8547cb7b4 |
|
| 109 |
+--- /dev/null |
|
| 110 |
+@@ -0,0 +1,238 @@ |
|
| 111 |
++/* |
|
| 112 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 113 |
++ * Copyright 2017 NXP |
|
| 114 |
++ * |
|
| 115 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 116 |
++ * it under the terms of the GNU General Public License as published by |
|
| 117 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 118 |
++ * (at your option) any later version. |
|
| 119 |
++ * |
|
| 120 |
++ * This program is distributed in the hope that it will be useful, |
|
| 121 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 122 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 123 |
++ * GNU General Public License for more details. |
|
| 124 |
++ * |
|
| 125 |
++ * You should have received a copy of the GNU General Public License |
|
| 126 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 127 |
++ */ |
|
| 128 |
++ |
|
| 129 |
++#include <linux/kernel.h> |
|
| 130 |
++#include <linux/sched.h> |
|
| 131 |
++#include <linux/module.h> |
|
| 132 |
++#include <linux/list.h> |
|
| 133 |
++#include <linux/kthread.h> |
|
| 134 |
++ |
|
| 135 |
++#include "pfe_mod.h" |
|
| 136 |
++#include "pfe_ctrl.h" |
|
| 137 |
++ |
|
| 138 |
++#define TIMEOUT_MS 1000 |
|
| 139 |
++ |
|
| 140 |
++int relax(unsigned long end) |
|
| 141 |
++{
|
|
| 142 |
++ if (time_after(jiffies, end)) {
|
|
| 143 |
++ if (time_after(jiffies, end + (TIMEOUT_MS * HZ) / 1000)) |
|
| 144 |
++ return -1; |
|
| 145 |
++ |
|
| 146 |
++ if (need_resched()) |
|
| 147 |
++ schedule(); |
|
| 148 |
++ } |
|
| 149 |
++ |
|
| 150 |
++ return 0; |
|
| 151 |
++} |
|
| 152 |
++ |
|
| 153 |
++void pfe_ctrl_suspend(struct pfe_ctrl *ctrl) |
|
| 154 |
++{
|
|
| 155 |
++ int id; |
|
| 156 |
++ |
|
| 157 |
++ mutex_lock(&ctrl->mutex); |
|
| 158 |
++ |
|
| 159 |
++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) |
|
| 160 |
++ pe_dmem_write(id, cpu_to_be32(0x1), CLASS_DM_RESUME, 4); |
|
| 161 |
++ |
|
| 162 |
++ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) {
|
|
| 163 |
++ if (id == TMU2_ID) |
|
| 164 |
++ continue; |
|
| 165 |
++ pe_dmem_write(id, cpu_to_be32(0x1), TMU_DM_RESUME, 4); |
|
| 166 |
++ } |
|
| 167 |
++ |
|
| 168 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 169 |
++ pe_dmem_write(UTIL_ID, cpu_to_be32(0x1), UTIL_DM_RESUME, 4); |
|
| 170 |
++#endif |
|
| 171 |
++ mutex_unlock(&ctrl->mutex); |
|
| 172 |
++} |
|
| 173 |
++ |
|
| 174 |
++void pfe_ctrl_resume(struct pfe_ctrl *ctrl) |
|
| 175 |
++{
|
|
| 176 |
++ int pe_mask = CLASS_MASK | TMU_MASK; |
|
| 177 |
++ |
|
| 178 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 179 |
++ pe_mask |= UTIL_MASK; |
|
| 180 |
++#endif |
|
| 181 |
++ mutex_lock(&ctrl->mutex); |
|
| 182 |
++ pe_start(&pfe->ctrl, pe_mask); |
|
| 183 |
++ mutex_unlock(&ctrl->mutex); |
|
| 184 |
++} |
|
| 185 |
++ |
|
| 186 |
++/* PE sync stop. |
|
| 187 |
++ * Stops packet processing for a list of PE's (specified using a bitmask). |
|
| 188 |
++ * The caller must hold ctrl->mutex. |
|
| 189 |
++ * |
|
| 190 |
++ * @param ctrl Control context |
|
| 191 |
++ * @param pe_mask Mask of PE id's to stop |
|
| 192 |
++ * |
|
| 193 |
++ */ |
|
| 194 |
++int pe_sync_stop(struct pfe_ctrl *ctrl, int pe_mask) |
|
| 195 |
++{
|
|
| 196 |
++ struct pe_sync_mailbox *mbox; |
|
| 197 |
++ int pe_stopped = 0; |
|
| 198 |
++ unsigned long end = jiffies + 2; |
|
| 199 |
++ int i; |
|
| 200 |
++ |
|
| 201 |
++ pe_mask &= 0x2FF; /*Exclude Util + TMU2 */ |
|
| 202 |
++ |
|
| 203 |
++ for (i = 0; i < MAX_PE; i++) |
|
| 204 |
++ if (pe_mask & (1 << i)) {
|
|
| 205 |
++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; |
|
| 206 |
++ |
|
| 207 |
++ pe_dmem_write(i, cpu_to_be32(0x1), (unsigned |
|
| 208 |
++ long)&mbox->stop, 4); |
|
| 209 |
++ } |
|
| 210 |
++ |
|
| 211 |
++ while (pe_stopped != pe_mask) {
|
|
| 212 |
++ for (i = 0; i < MAX_PE; i++) |
|
| 213 |
++ if ((pe_mask & (1 << i)) && !(pe_stopped & (1 << i))) {
|
|
| 214 |
++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; |
|
| 215 |
++ |
|
| 216 |
++ if (pe_dmem_read(i, (unsigned |
|
| 217 |
++ long)&mbox->stopped, 4) & |
|
| 218 |
++ cpu_to_be32(0x1)) |
|
| 219 |
++ pe_stopped |= (1 << i); |
|
| 220 |
++ } |
|
| 221 |
++ |
|
| 222 |
++ if (relax(end) < 0) |
|
| 223 |
++ goto err; |
|
| 224 |
++ } |
|
| 225 |
++ |
|
| 226 |
++ return 0; |
|
| 227 |
++ |
|
| 228 |
++err: |
|
| 229 |
++ pr_err("%s: timeout, %x %x\n", __func__, pe_mask, pe_stopped);
|
|
| 230 |
++ |
|
| 231 |
++ for (i = 0; i < MAX_PE; i++) |
|
| 232 |
++ if (pe_mask & (1 << i)) {
|
|
| 233 |
++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; |
|
| 234 |
++ |
|
| 235 |
++ pe_dmem_write(i, cpu_to_be32(0x0), (unsigned |
|
| 236 |
++ long)&mbox->stop, 4); |
|
| 237 |
++ } |
|
| 238 |
++ |
|
| 239 |
++ return -EIO; |
|
| 240 |
++} |
|
| 241 |
++ |
|
| 242 |
++/* PE start. |
|
| 243 |
++ * Starts packet processing for a list of PE's (specified using a bitmask). |
|
| 244 |
++ * The caller must hold ctrl->mutex. |
|
| 245 |
++ * |
|
| 246 |
++ * @param ctrl Control context |
|
| 247 |
++ * @param pe_mask Mask of PE id's to start |
|
| 248 |
++ * |
|
| 249 |
++ */ |
|
| 250 |
++void pe_start(struct pfe_ctrl *ctrl, int pe_mask) |
|
| 251 |
++{
|
|
| 252 |
++ struct pe_sync_mailbox *mbox; |
|
| 253 |
++ int i; |
|
| 254 |
++ |
|
| 255 |
++ for (i = 0; i < MAX_PE; i++) |
|
| 256 |
++ if (pe_mask & (1 << i)) {
|
|
| 257 |
++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; |
|
| 258 |
++ |
|
| 259 |
++ pe_dmem_write(i, cpu_to_be32(0x0), (unsigned |
|
| 260 |
++ long)&mbox->stop, 4); |
|
| 261 |
++ } |
|
| 262 |
++} |
|
| 263 |
++ |
|
| 264 |
++/* This function will ensure all PEs are put in to idle state */ |
|
| 265 |
++int pe_reset_all(struct pfe_ctrl *ctrl) |
|
| 266 |
++{
|
|
| 267 |
++ struct pe_sync_mailbox *mbox; |
|
| 268 |
++ int pe_stopped = 0; |
|
| 269 |
++ unsigned long end = jiffies + 2; |
|
| 270 |
++ int i; |
|
| 271 |
++ int pe_mask = CLASS_MASK | TMU_MASK; |
|
| 272 |
++ |
|
| 273 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 274 |
++ pe_mask |= UTIL_MASK; |
|
| 275 |
++#endif |
|
| 276 |
++ |
|
| 277 |
++ for (i = 0; i < MAX_PE; i++) |
|
| 278 |
++ if (pe_mask & (1 << i)) {
|
|
| 279 |
++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; |
|
| 280 |
++ |
|
| 281 |
++ pe_dmem_write(i, cpu_to_be32(0x2), (unsigned |
|
| 282 |
++ long)&mbox->stop, 4); |
|
| 283 |
++ } |
|
| 284 |
++ |
|
| 285 |
++ while (pe_stopped != pe_mask) {
|
|
| 286 |
++ for (i = 0; i < MAX_PE; i++) |
|
| 287 |
++ if ((pe_mask & (1 << i)) && !(pe_stopped & (1 << i))) {
|
|
| 288 |
++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; |
|
| 289 |
++ |
|
| 290 |
++ if (pe_dmem_read(i, (unsigned long) |
|
| 291 |
++ &mbox->stopped, 4) & |
|
| 292 |
++ cpu_to_be32(0x1)) |
|
| 293 |
++ pe_stopped |= (1 << i); |
|
| 294 |
++ } |
|
| 295 |
++ |
|
| 296 |
++ if (relax(end) < 0) |
|
| 297 |
++ goto err; |
|
| 298 |
++ } |
|
| 299 |
++ |
|
| 300 |
++ return 0; |
|
| 301 |
++ |
|
| 302 |
++err: |
|
| 303 |
++ pr_err("%s: timeout, %x %x\n", __func__, pe_mask, pe_stopped);
|
|
| 304 |
++ return -EIO; |
|
| 305 |
++} |
|
| 306 |
++ |
|
| 307 |
++int pfe_ctrl_init(struct pfe *pfe) |
|
| 308 |
++{
|
|
| 309 |
++ struct pfe_ctrl *ctrl = &pfe->ctrl; |
|
| 310 |
++ int id; |
|
| 311 |
++ |
|
| 312 |
++ pr_info("%s\n", __func__);
|
|
| 313 |
++ |
|
| 314 |
++ mutex_init(&ctrl->mutex); |
|
| 315 |
++ spin_lock_init(&ctrl->lock); |
|
| 316 |
++ |
|
| 317 |
++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) {
|
|
| 318 |
++ ctrl->sync_mailbox_baseaddr[id] = CLASS_DM_SYNC_MBOX; |
|
| 319 |
++ ctrl->msg_mailbox_baseaddr[id] = CLASS_DM_MSG_MBOX; |
|
| 320 |
++ } |
|
| 321 |
++ |
|
| 322 |
++ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) {
|
|
| 323 |
++ if (id == TMU2_ID) |
|
| 324 |
++ continue; |
|
| 325 |
++ ctrl->sync_mailbox_baseaddr[id] = TMU_DM_SYNC_MBOX; |
|
| 326 |
++ ctrl->msg_mailbox_baseaddr[id] = TMU_DM_MSG_MBOX; |
|
| 327 |
++ } |
|
| 328 |
++ |
|
| 329 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 330 |
++ ctrl->sync_mailbox_baseaddr[UTIL_ID] = UTIL_DM_SYNC_MBOX; |
|
| 331 |
++ ctrl->msg_mailbox_baseaddr[UTIL_ID] = UTIL_DM_MSG_MBOX; |
|
| 332 |
++#endif |
|
| 333 |
++ |
|
| 334 |
++ ctrl->hash_array_baseaddr = pfe->ddr_baseaddr + ROUTE_TABLE_BASEADDR; |
|
| 335 |
++ ctrl->hash_array_phys_baseaddr = pfe->ddr_phys_baseaddr + |
|
| 336 |
++ ROUTE_TABLE_BASEADDR; |
|
| 337 |
++ |
|
| 338 |
++ ctrl->dev = pfe->dev; |
|
| 339 |
++ |
|
| 340 |
++ pr_info("%s finished\n", __func__);
|
|
| 341 |
++ |
|
| 342 |
++ return 0; |
|
| 343 |
++} |
|
| 344 |
++ |
|
| 345 |
++void pfe_ctrl_exit(struct pfe *pfe) |
|
| 346 |
++{
|
|
| 347 |
++ pr_info("%s\n", __func__);
|
|
| 348 |
++} |
|
| 349 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_debugfs.c b/drivers/staging/fsl_ppfe/pfe_debugfs.c |
|
| 350 |
+new file mode 100644 |
|
| 351 |
+index 000000000000..4156610ddbb3 |
|
| 352 |
+--- /dev/null |
|
| 353 |
+@@ -0,0 +1,111 @@ |
|
| 354 |
++/* |
|
| 355 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 356 |
++ * Copyright 2017 NXP |
|
| 357 |
++ * |
|
| 358 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 359 |
++ * it under the terms of the GNU General Public License as published by |
|
| 360 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 361 |
++ * (at your option) any later version. |
|
| 362 |
++ * |
|
| 363 |
++ * This program is distributed in the hope that it will be useful, |
|
| 364 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 365 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 366 |
++ * GNU General Public License for more details. |
|
| 367 |
++ * |
|
| 368 |
++ * You should have received a copy of the GNU General Public License |
|
| 369 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 370 |
++ */ |
|
| 371 |
++ |
|
| 372 |
++#include <linux/module.h> |
|
| 373 |
++#include <linux/debugfs.h> |
|
| 374 |
++#include <linux/platform_device.h> |
|
| 375 |
++ |
|
| 376 |
++#include "pfe_mod.h" |
|
| 377 |
++ |
|
| 378 |
++static int dmem_show(struct seq_file *s, void *unused) |
|
| 379 |
++{
|
|
| 380 |
++ u32 dmem_addr, val; |
|
| 381 |
++ int id = (long int)s->private; |
|
| 382 |
++ int i; |
|
| 383 |
++ |
|
| 384 |
++ for (dmem_addr = 0; dmem_addr < CLASS_DMEM_SIZE; dmem_addr += 8 * 4) {
|
|
| 385 |
++ seq_printf(s, "%04x:", dmem_addr); |
|
| 386 |
++ |
|
| 387 |
++ for (i = 0; i < 8; i++) {
|
|
| 388 |
++ val = pe_dmem_read(id, dmem_addr + i * 4, 4); |
|
| 389 |
++ seq_printf(s, " %02x %02x %02x %02x", val & 0xff, |
|
| 390 |
++ (val >> 8) & 0xff, (val >> 16) & 0xff, |
|
| 391 |
++ (val >> 24) & 0xff); |
|
| 392 |
++ } |
|
| 393 |
++ |
|
| 394 |
++ seq_puts(s, "\n"); |
|
| 395 |
++ } |
|
| 396 |
++ |
|
| 397 |
++ return 0; |
|
| 398 |
++} |
|
| 399 |
++ |
|
| 400 |
++static int dmem_open(struct inode *inode, struct file *file) |
|
| 401 |
++{
|
|
| 402 |
++ return single_open(file, dmem_show, inode->i_private); |
|
| 403 |
++} |
|
| 404 |
++ |
|
| 405 |
++static const struct file_operations dmem_fops = {
|
|
| 406 |
++ .open = dmem_open, |
|
| 407 |
++ .read = seq_read, |
|
| 408 |
++ .llseek = seq_lseek, |
|
| 409 |
++ .release = single_release, |
|
| 410 |
++}; |
|
| 411 |
++ |
|
| 412 |
++int pfe_debugfs_init(struct pfe *pfe) |
|
| 413 |
++{
|
|
| 414 |
++ struct dentry *d; |
|
| 415 |
++ |
|
| 416 |
++ pr_info("%s\n", __func__);
|
|
| 417 |
++ |
|
| 418 |
++ pfe->dentry = debugfs_create_dir("pfe", NULL);
|
|
| 419 |
++ if (IS_ERR_OR_NULL(pfe->dentry)) |
|
| 420 |
++ goto err_dir; |
|
| 421 |
++ |
|
| 422 |
++ d = debugfs_create_file("pe0_dmem", 0444, pfe->dentry, (void *)0,
|
|
| 423 |
++ &dmem_fops); |
|
| 424 |
++ if (IS_ERR_OR_NULL(d)) |
|
| 425 |
++ goto err_pe; |
|
| 426 |
++ |
|
| 427 |
++ d = debugfs_create_file("pe1_dmem", 0444, pfe->dentry, (void *)1,
|
|
| 428 |
++ &dmem_fops); |
|
| 429 |
++ if (IS_ERR_OR_NULL(d)) |
|
| 430 |
++ goto err_pe; |
|
| 431 |
++ |
|
| 432 |
++ d = debugfs_create_file("pe2_dmem", 0444, pfe->dentry, (void *)2,
|
|
| 433 |
++ &dmem_fops); |
|
| 434 |
++ if (IS_ERR_OR_NULL(d)) |
|
| 435 |
++ goto err_pe; |
|
| 436 |
++ |
|
| 437 |
++ d = debugfs_create_file("pe3_dmem", 0444, pfe->dentry, (void *)3,
|
|
| 438 |
++ &dmem_fops); |
|
| 439 |
++ if (IS_ERR_OR_NULL(d)) |
|
| 440 |
++ goto err_pe; |
|
| 441 |
++ |
|
| 442 |
++ d = debugfs_create_file("pe4_dmem", 0444, pfe->dentry, (void *)4,
|
|
| 443 |
++ &dmem_fops); |
|
| 444 |
++ if (IS_ERR_OR_NULL(d)) |
|
| 445 |
++ goto err_pe; |
|
| 446 |
++ |
|
| 447 |
++ d = debugfs_create_file("pe5_dmem", 0444, pfe->dentry, (void *)5,
|
|
| 448 |
++ &dmem_fops); |
|
| 449 |
++ if (IS_ERR_OR_NULL(d)) |
|
| 450 |
++ goto err_pe; |
|
| 451 |
++ |
|
| 452 |
++ return 0; |
|
| 453 |
++ |
|
| 454 |
++err_pe: |
|
| 455 |
++ debugfs_remove_recursive(pfe->dentry); |
|
| 456 |
++ |
|
| 457 |
++err_dir: |
|
| 458 |
++ return -1; |
|
| 459 |
++} |
|
| 460 |
++ |
|
| 461 |
++void pfe_debugfs_exit(struct pfe *pfe) |
|
| 462 |
++{
|
|
| 463 |
++ debugfs_remove_recursive(pfe->dentry); |
|
| 464 |
++} |
|
| 465 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 466 |
+new file mode 100644 |
|
| 467 |
+index 000000000000..5aa718be42c2 |
|
| 468 |
+--- /dev/null |
|
| 469 |
+@@ -0,0 +1,2434 @@ |
|
| 470 |
++/* |
|
| 471 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 472 |
++ * Copyright 2017 NXP |
|
| 473 |
++ * |
|
| 474 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 475 |
++ * it under the terms of the GNU General Public License as published by |
|
| 476 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 477 |
++ * (at your option) any later version. |
|
| 478 |
++ * |
|
| 479 |
++ * This program is distributed in the hope that it will be useful, |
|
| 480 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 481 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 482 |
++ * GNU General Public License for more details. |
|
| 483 |
++ * |
|
| 484 |
++ * You should have received a copy of the GNU General Public License |
|
| 485 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 486 |
++ */ |
|
| 487 |
++ |
|
| 488 |
++/* @pfe_eth.c. |
|
| 489 |
++ * Ethernet driver for to handle exception path for PFE. |
|
| 490 |
++ * - uses HIF functions to send/receive packets. |
|
| 491 |
++ * - uses ctrl function to start/stop interfaces. |
|
| 492 |
++ * - uses direct register accesses to control phy operation. |
|
| 493 |
++ */ |
|
| 494 |
++#include <linux/version.h> |
|
| 495 |
++#include <linux/kernel.h> |
|
| 496 |
++#include <linux/interrupt.h> |
|
| 497 |
++#include <linux/dma-mapping.h> |
|
| 498 |
++#include <linux/dmapool.h> |
|
| 499 |
++#include <linux/netdevice.h> |
|
| 500 |
++#include <linux/etherdevice.h> |
|
| 501 |
++#include <linux/ethtool.h> |
|
| 502 |
++#include <linux/mii.h> |
|
| 503 |
++#include <linux/phy.h> |
|
| 504 |
++#include <linux/timer.h> |
|
| 505 |
++#include <linux/hrtimer.h> |
|
| 506 |
++#include <linux/platform_device.h> |
|
| 507 |
++ |
|
| 508 |
++#include <net/ip.h> |
|
| 509 |
++#include <net/sock.h> |
|
| 510 |
++ |
|
| 511 |
++#include <linux/io.h> |
|
| 512 |
++#include <asm/irq.h> |
|
| 513 |
++#include <linux/delay.h> |
|
| 514 |
++#include <linux/regmap.h> |
|
| 515 |
++#include <linux/i2c.h> |
|
| 516 |
++ |
|
| 517 |
++#if defined(CONFIG_NF_CONNTRACK_MARK) |
|
| 518 |
++#include <net/netfilter/nf_conntrack.h> |
|
| 519 |
++#endif |
|
| 520 |
++ |
|
| 521 |
++#include "pfe_mod.h" |
|
| 522 |
++#include "pfe_eth.h" |
|
| 523 |
++ |
|
| 524 |
++static void *cbus_emac_base[3]; |
|
| 525 |
++static void *cbus_gpi_base[3]; |
|
| 526 |
++ |
|
| 527 |
++/* Forward Declaration */ |
|
| 528 |
++static void pfe_eth_exit_one(struct pfe_eth_priv_s *priv); |
|
| 529 |
++static void pfe_eth_flush_tx(struct pfe_eth_priv_s *priv); |
|
| 530 |
++static void pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int |
|
| 531 |
++ from_tx, int n_desc); |
|
| 532 |
++ |
|
| 533 |
++unsigned int gemac_regs[] = {
|
|
| 534 |
++ 0x0004, /* Interrupt event */ |
|
| 535 |
++ 0x0008, /* Interrupt mask */ |
|
| 536 |
++ 0x0024, /* Ethernet control */ |
|
| 537 |
++ 0x0064, /* MIB Control/Status */ |
|
| 538 |
++ 0x0084, /* Receive control/status */ |
|
| 539 |
++ 0x00C4, /* Transmit control */ |
|
| 540 |
++ 0x00E4, /* Physical address low */ |
|
| 541 |
++ 0x00E8, /* Physical address high */ |
|
| 542 |
++ 0x0144, /* Transmit FIFO Watermark and Store and Forward Control*/ |
|
| 543 |
++ 0x0190, /* Receive FIFO Section Full Threshold */ |
|
| 544 |
++ 0x01A0, /* Transmit FIFO Section Empty Threshold */ |
|
| 545 |
++ 0x01B0, /* Frame Truncation Length */ |
|
| 546 |
++}; |
|
| 547 |
++ |
|
| 548 |
++/********************************************************************/ |
|
| 549 |
++/* SYSFS INTERFACE */ |
|
| 550 |
++/********************************************************************/ |
|
| 551 |
++ |
|
| 552 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 553 |
++/* |
|
| 554 |
++ * pfe_eth_show_napi_stats |
|
| 555 |
++ */ |
|
| 556 |
++static ssize_t pfe_eth_show_napi_stats(struct device *dev, |
|
| 557 |
++ struct device_attribute *attr, |
|
| 558 |
++ char *buf) |
|
| 559 |
++{
|
|
| 560 |
++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); |
|
| 561 |
++ ssize_t len = 0; |
|
| 562 |
++ |
|
| 563 |
++ len += sprintf(buf + len, "sched: %u\n", |
|
| 564 |
++ priv->napi_counters[NAPI_SCHED_COUNT]); |
|
| 565 |
++ len += sprintf(buf + len, "poll: %u\n", |
|
| 566 |
++ priv->napi_counters[NAPI_POLL_COUNT]); |
|
| 567 |
++ len += sprintf(buf + len, "packet: %u\n", |
|
| 568 |
++ priv->napi_counters[NAPI_PACKET_COUNT]); |
|
| 569 |
++ len += sprintf(buf + len, "budget: %u\n", |
|
| 570 |
++ priv->napi_counters[NAPI_FULL_BUDGET_COUNT]); |
|
| 571 |
++ len += sprintf(buf + len, "desc: %u\n", |
|
| 572 |
++ priv->napi_counters[NAPI_DESC_COUNT]); |
|
| 573 |
++ |
|
| 574 |
++ return len; |
|
| 575 |
++} |
|
| 576 |
++ |
|
| 577 |
++/* |
|
| 578 |
++ * pfe_eth_set_napi_stats |
|
| 579 |
++ */ |
|
| 580 |
++static ssize_t pfe_eth_set_napi_stats(struct device *dev, |
|
| 581 |
++ struct device_attribute *attr, |
|
| 582 |
++ const char *buf, size_t count) |
|
| 583 |
++{
|
|
| 584 |
++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); |
|
| 585 |
++ |
|
| 586 |
++ memset(priv->napi_counters, 0, sizeof(priv->napi_counters)); |
|
| 587 |
++ |
|
| 588 |
++ return count; |
|
| 589 |
++} |
|
| 590 |
++#endif |
|
| 591 |
++#ifdef PFE_ETH_TX_STATS |
|
| 592 |
++/* pfe_eth_show_tx_stats |
|
| 593 |
++ * |
|
| 594 |
++ */ |
|
| 595 |
++static ssize_t pfe_eth_show_tx_stats(struct device *dev, |
|
| 596 |
++ struct device_attribute *attr, |
|
| 597 |
++ char *buf) |
|
| 598 |
++{
|
|
| 599 |
++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); |
|
| 600 |
++ ssize_t len = 0; |
|
| 601 |
++ int i; |
|
| 602 |
++ |
|
| 603 |
++ len += sprintf(buf + len, "TX queues stats:\n"); |
|
| 604 |
++ |
|
| 605 |
++ for (i = 0; i < emac_txq_cnt; i++) {
|
|
| 606 |
++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, |
|
| 607 |
++ i); |
|
| 608 |
++ |
|
| 609 |
++ len += sprintf(buf + len, "\n"); |
|
| 610 |
++ __netif_tx_lock_bh(tx_queue); |
|
| 611 |
++ |
|
| 612 |
++ hif_tx_lock(&pfe->hif); |
|
| 613 |
++ len += sprintf(buf + len, |
|
| 614 |
++ "Queue %2d : credits = %10d\n" |
|
| 615 |
++ , i, hif_lib_tx_credit_avail(pfe, priv->id, i)); |
|
| 616 |
++ len += sprintf(buf + len, |
|
| 617 |
++ " tx packets = %10d\n" |
|
| 618 |
++ , pfe->tmu_credit.tx_packets[priv->id][i]); |
|
| 619 |
++ hif_tx_unlock(&pfe->hif); |
|
| 620 |
++ |
|
| 621 |
++ /* Don't output additionnal stats if queue never used */ |
|
| 622 |
++ if (!pfe->tmu_credit.tx_packets[priv->id][i]) |
|
| 623 |
++ goto skip; |
|
| 624 |
++ |
|
| 625 |
++ len += sprintf(buf + len, |
|
| 626 |
++ " clean_fail = %10d\n" |
|
| 627 |
++ , priv->clean_fail[i]); |
|
| 628 |
++ len += sprintf(buf + len, |
|
| 629 |
++ " stop_queue = %10d\n" |
|
| 630 |
++ , priv->stop_queue_total[i]); |
|
| 631 |
++ len += sprintf(buf + len, |
|
| 632 |
++ " stop_queue_hif = %10d\n" |
|
| 633 |
++ , priv->stop_queue_hif[i]); |
|
| 634 |
++ len += sprintf(buf + len, |
|
| 635 |
++ " stop_queue_hif_client = %10d\n" |
|
| 636 |
++ , priv->stop_queue_hif_client[i]); |
|
| 637 |
++ len += sprintf(buf + len, |
|
| 638 |
++ " stop_queue_credit = %10d\n" |
|
| 639 |
++ , priv->stop_queue_credit[i]); |
|
| 640 |
++skip: |
|
| 641 |
++ __netif_tx_unlock_bh(tx_queue); |
|
| 642 |
++ } |
|
| 643 |
++ return len; |
|
| 644 |
++} |
|
| 645 |
++ |
|
| 646 |
++/* pfe_eth_set_tx_stats |
|
| 647 |
++ * |
|
| 648 |
++ */ |
|
| 649 |
++static ssize_t pfe_eth_set_tx_stats(struct device *dev, |
|
| 650 |
++ struct device_attribute *attr, |
|
| 651 |
++ const char *buf, size_t count) |
|
| 652 |
++{
|
|
| 653 |
++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); |
|
| 654 |
++ int i; |
|
| 655 |
++ |
|
| 656 |
++ for (i = 0; i < emac_txq_cnt; i++) {
|
|
| 657 |
++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, |
|
| 658 |
++ i); |
|
| 659 |
++ |
|
| 660 |
++ __netif_tx_lock_bh(tx_queue); |
|
| 661 |
++ priv->clean_fail[i] = 0; |
|
| 662 |
++ priv->stop_queue_total[i] = 0; |
|
| 663 |
++ priv->stop_queue_hif[i] = 0; |
|
| 664 |
++ priv->stop_queue_hif_client[i] = 0; |
|
| 665 |
++ priv->stop_queue_credit[i] = 0; |
|
| 666 |
++ __netif_tx_unlock_bh(tx_queue); |
|
| 667 |
++ } |
|
| 668 |
++ |
|
| 669 |
++ return count; |
|
| 670 |
++} |
|
| 671 |
++#endif |
|
| 672 |
++/* pfe_eth_show_txavail |
|
| 673 |
++ * |
|
| 674 |
++ */ |
|
| 675 |
++static ssize_t pfe_eth_show_txavail(struct device *dev, |
|
| 676 |
++ struct device_attribute *attr, |
|
| 677 |
++ char *buf) |
|
| 678 |
++{
|
|
| 679 |
++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); |
|
| 680 |
++ ssize_t len = 0; |
|
| 681 |
++ int i; |
|
| 682 |
++ |
|
| 683 |
++ for (i = 0; i < emac_txq_cnt; i++) {
|
|
| 684 |
++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, |
|
| 685 |
++ i); |
|
| 686 |
++ |
|
| 687 |
++ __netif_tx_lock_bh(tx_queue); |
|
| 688 |
++ |
|
| 689 |
++ len += sprintf(buf + len, "%d", |
|
| 690 |
++ hif_lib_tx_avail(&priv->client, i)); |
|
| 691 |
++ |
|
| 692 |
++ __netif_tx_unlock_bh(tx_queue); |
|
| 693 |
++ |
|
| 694 |
++ if (i == (emac_txq_cnt - 1)) |
|
| 695 |
++ len += sprintf(buf + len, "\n"); |
|
| 696 |
++ else |
|
| 697 |
++ len += sprintf(buf + len, " "); |
|
| 698 |
++ } |
|
| 699 |
++ |
|
| 700 |
++ return len; |
|
| 701 |
++} |
|
| 702 |
++ |
|
| 703 |
++/* pfe_eth_show_default_priority |
|
| 704 |
++ * |
|
| 705 |
++ */ |
|
| 706 |
++static ssize_t pfe_eth_show_default_priority(struct device *dev, |
|
| 707 |
++ struct device_attribute *attr, |
|
| 708 |
++ char *buf) |
|
| 709 |
++{
|
|
| 710 |
++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); |
|
| 711 |
++ unsigned long flags; |
|
| 712 |
++ int rc; |
|
| 713 |
++ |
|
| 714 |
++ spin_lock_irqsave(&priv->lock, flags); |
|
| 715 |
++ rc = sprintf(buf, "%d\n", priv->default_priority); |
|
| 716 |
++ spin_unlock_irqrestore(&priv->lock, flags); |
|
| 717 |
++ |
|
| 718 |
++ return rc; |
|
| 719 |
++} |
|
| 720 |
++ |
|
| 721 |
++/* pfe_eth_set_default_priority |
|
| 722 |
++ * |
|
| 723 |
++ */ |
|
| 724 |
++ |
|
| 725 |
++static ssize_t pfe_eth_set_default_priority(struct device *dev, |
|
| 726 |
++ struct device_attribute *attr, |
|
| 727 |
++ const char *buf, size_t count) |
|
| 728 |
++{
|
|
| 729 |
++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); |
|
| 730 |
++ unsigned long flags; |
|
| 731 |
++ |
|
| 732 |
++ spin_lock_irqsave(&priv->lock, flags); |
|
| 733 |
++ priv->default_priority = kstrtoul(buf, 0, 0); |
|
| 734 |
++ spin_unlock_irqrestore(&priv->lock, flags); |
|
| 735 |
++ |
|
| 736 |
++ return count; |
|
| 737 |
++} |
|
| 738 |
++ |
|
| 739 |
++static DEVICE_ATTR(txavail, 0444, pfe_eth_show_txavail, NULL); |
|
| 740 |
++static DEVICE_ATTR(default_priority, 0644, pfe_eth_show_default_priority, |
|
| 741 |
++ pfe_eth_set_default_priority); |
|
| 742 |
++ |
|
| 743 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 744 |
++static DEVICE_ATTR(napi_stats, 0644, pfe_eth_show_napi_stats, |
|
| 745 |
++ pfe_eth_set_napi_stats); |
|
| 746 |
++#endif |
|
| 747 |
++ |
|
| 748 |
++#ifdef PFE_ETH_TX_STATS |
|
| 749 |
++static DEVICE_ATTR(tx_stats, 0644, pfe_eth_show_tx_stats, |
|
| 750 |
++ pfe_eth_set_tx_stats); |
|
| 751 |
++#endif |
|
| 752 |
++ |
|
| 753 |
++/* |
|
| 754 |
++ * pfe_eth_sysfs_init |
|
| 755 |
++ * |
|
| 756 |
++ */ |
|
| 757 |
++static int pfe_eth_sysfs_init(struct net_device *ndev) |
|
| 758 |
++{
|
|
| 759 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 760 |
++ int err; |
|
| 761 |
++ |
|
| 762 |
++ /* Initialize the default values */ |
|
| 763 |
++ |
|
| 764 |
++ /* |
|
| 765 |
++ * By default, packets without conntrack will use this default high |
|
| 766 |
++ * priority queue |
|
| 767 |
++ */ |
|
| 768 |
++ priv->default_priority = 15; |
|
| 769 |
++ |
|
| 770 |
++ /* Create our sysfs files */ |
|
| 771 |
++ err = device_create_file(&ndev->dev, &dev_attr_default_priority); |
|
| 772 |
++ if (err) {
|
|
| 773 |
++ netdev_err(ndev, |
|
| 774 |
++ "failed to create default_priority sysfs files\n"); |
|
| 775 |
++ goto err_priority; |
|
| 776 |
++ } |
|
| 777 |
++ |
|
| 778 |
++ err = device_create_file(&ndev->dev, &dev_attr_txavail); |
|
| 779 |
++ if (err) {
|
|
| 780 |
++ netdev_err(ndev, |
|
| 781 |
++ "failed to create default_priority sysfs files\n"); |
|
| 782 |
++ goto err_txavail; |
|
| 783 |
++ } |
|
| 784 |
++ |
|
| 785 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 786 |
++ err = device_create_file(&ndev->dev, &dev_attr_napi_stats); |
|
| 787 |
++ if (err) {
|
|
| 788 |
++ netdev_err(ndev, "failed to create napi stats sysfs files\n"); |
|
| 789 |
++ goto err_napi; |
|
| 790 |
++ } |
|
| 791 |
++#endif |
|
| 792 |
++ |
|
| 793 |
++#ifdef PFE_ETH_TX_STATS |
|
| 794 |
++ err = device_create_file(&ndev->dev, &dev_attr_tx_stats); |
|
| 795 |
++ if (err) {
|
|
| 796 |
++ netdev_err(ndev, "failed to create tx stats sysfs files\n"); |
|
| 797 |
++ goto err_tx; |
|
| 798 |
++ } |
|
| 799 |
++#endif |
|
| 800 |
++ |
|
| 801 |
++ return 0; |
|
| 802 |
++ |
|
| 803 |
++#ifdef PFE_ETH_TX_STATS |
|
| 804 |
++err_tx: |
|
| 805 |
++#endif |
|
| 806 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 807 |
++ device_remove_file(&ndev->dev, &dev_attr_napi_stats); |
|
| 808 |
++ |
|
| 809 |
++err_napi: |
|
| 810 |
++#endif |
|
| 811 |
++ device_remove_file(&ndev->dev, &dev_attr_txavail); |
|
| 812 |
++ |
|
| 813 |
++err_txavail: |
|
| 814 |
++ device_remove_file(&ndev->dev, &dev_attr_default_priority); |
|
| 815 |
++ |
|
| 816 |
++err_priority: |
|
| 817 |
++ return -1; |
|
| 818 |
++} |
|
| 819 |
++ |
|
| 820 |
++/* pfe_eth_sysfs_exit |
|
| 821 |
++ * |
|
| 822 |
++ */ |
|
| 823 |
++void pfe_eth_sysfs_exit(struct net_device *ndev) |
|
| 824 |
++{
|
|
| 825 |
++#ifdef PFE_ETH_TX_STATS |
|
| 826 |
++ device_remove_file(&ndev->dev, &dev_attr_tx_stats); |
|
| 827 |
++#endif |
|
| 828 |
++ |
|
| 829 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 830 |
++ device_remove_file(&ndev->dev, &dev_attr_napi_stats); |
|
| 831 |
++#endif |
|
| 832 |
++ device_remove_file(&ndev->dev, &dev_attr_txavail); |
|
| 833 |
++ device_remove_file(&ndev->dev, &dev_attr_default_priority); |
|
| 834 |
++} |
|
| 835 |
++ |
|
| 836 |
++/*************************************************************************/ |
|
| 837 |
++/* ETHTOOL INTERCAE */ |
|
| 838 |
++/*************************************************************************/ |
|
| 839 |
++ |
|
| 840 |
++/*MTIP GEMAC */ |
|
| 841 |
++static const struct fec_stat {
|
|
| 842 |
++ char name[ETH_GSTRING_LEN]; |
|
| 843 |
++ u16 offset; |
|
| 844 |
++} fec_stats[] = {
|
|
| 845 |
++ /* RMON TX */ |
|
| 846 |
++ { "tx_dropped", RMON_T_DROP },
|
|
| 847 |
++ { "tx_packets", RMON_T_PACKETS },
|
|
| 848 |
++ { "tx_broadcast", RMON_T_BC_PKT },
|
|
| 849 |
++ { "tx_multicast", RMON_T_MC_PKT },
|
|
| 850 |
++ { "tx_crc_errors", RMON_T_CRC_ALIGN },
|
|
| 851 |
++ { "tx_undersize", RMON_T_UNDERSIZE },
|
|
| 852 |
++ { "tx_oversize", RMON_T_OVERSIZE },
|
|
| 853 |
++ { "tx_fragment", RMON_T_FRAG },
|
|
| 854 |
++ { "tx_jabber", RMON_T_JAB },
|
|
| 855 |
++ { "tx_collision", RMON_T_COL },
|
|
| 856 |
++ { "tx_64byte", RMON_T_P64 },
|
|
| 857 |
++ { "tx_65to127byte", RMON_T_P65TO127 },
|
|
| 858 |
++ { "tx_128to255byte", RMON_T_P128TO255 },
|
|
| 859 |
++ { "tx_256to511byte", RMON_T_P256TO511 },
|
|
| 860 |
++ { "tx_512to1023byte", RMON_T_P512TO1023 },
|
|
| 861 |
++ { "tx_1024to2047byte", RMON_T_P1024TO2047 },
|
|
| 862 |
++ { "tx_GTE2048byte", RMON_T_P_GTE2048 },
|
|
| 863 |
++ { "tx_octets", RMON_T_OCTETS },
|
|
| 864 |
++ |
|
| 865 |
++ /* IEEE TX */ |
|
| 866 |
++ { "IEEE_tx_drop", IEEE_T_DROP },
|
|
| 867 |
++ { "IEEE_tx_frame_ok", IEEE_T_FRAME_OK },
|
|
| 868 |
++ { "IEEE_tx_1col", IEEE_T_1COL },
|
|
| 869 |
++ { "IEEE_tx_mcol", IEEE_T_MCOL },
|
|
| 870 |
++ { "IEEE_tx_def", IEEE_T_DEF },
|
|
| 871 |
++ { "IEEE_tx_lcol", IEEE_T_LCOL },
|
|
| 872 |
++ { "IEEE_tx_excol", IEEE_T_EXCOL },
|
|
| 873 |
++ { "IEEE_tx_macerr", IEEE_T_MACERR },
|
|
| 874 |
++ { "IEEE_tx_cserr", IEEE_T_CSERR },
|
|
| 875 |
++ { "IEEE_tx_sqe", IEEE_T_SQE },
|
|
| 876 |
++ { "IEEE_tx_fdxfc", IEEE_T_FDXFC },
|
|
| 877 |
++ { "IEEE_tx_octets_ok", IEEE_T_OCTETS_OK },
|
|
| 878 |
++ |
|
| 879 |
++ /* RMON RX */ |
|
| 880 |
++ { "rx_packets", RMON_R_PACKETS },
|
|
| 881 |
++ { "rx_broadcast", RMON_R_BC_PKT },
|
|
| 882 |
++ { "rx_multicast", RMON_R_MC_PKT },
|
|
| 883 |
++ { "rx_crc_errors", RMON_R_CRC_ALIGN },
|
|
| 884 |
++ { "rx_undersize", RMON_R_UNDERSIZE },
|
|
| 885 |
++ { "rx_oversize", RMON_R_OVERSIZE },
|
|
| 886 |
++ { "rx_fragment", RMON_R_FRAG },
|
|
| 887 |
++ { "rx_jabber", RMON_R_JAB },
|
|
| 888 |
++ { "rx_64byte", RMON_R_P64 },
|
|
| 889 |
++ { "rx_65to127byte", RMON_R_P65TO127 },
|
|
| 890 |
++ { "rx_128to255byte", RMON_R_P128TO255 },
|
|
| 891 |
++ { "rx_256to511byte", RMON_R_P256TO511 },
|
|
| 892 |
++ { "rx_512to1023byte", RMON_R_P512TO1023 },
|
|
| 893 |
++ { "rx_1024to2047byte", RMON_R_P1024TO2047 },
|
|
| 894 |
++ { "rx_GTE2048byte", RMON_R_P_GTE2048 },
|
|
| 895 |
++ { "rx_octets", RMON_R_OCTETS },
|
|
| 896 |
++ |
|
| 897 |
++ /* IEEE RX */ |
|
| 898 |
++ { "IEEE_rx_drop", IEEE_R_DROP },
|
|
| 899 |
++ { "IEEE_rx_frame_ok", IEEE_R_FRAME_OK },
|
|
| 900 |
++ { "IEEE_rx_crc", IEEE_R_CRC },
|
|
| 901 |
++ { "IEEE_rx_align", IEEE_R_ALIGN },
|
|
| 902 |
++ { "IEEE_rx_macerr", IEEE_R_MACERR },
|
|
| 903 |
++ { "IEEE_rx_fdxfc", IEEE_R_FDXFC },
|
|
| 904 |
++ { "IEEE_rx_octets_ok", IEEE_R_OCTETS_OK },
|
|
| 905 |
++}; |
|
| 906 |
++ |
|
| 907 |
++static void pfe_eth_fill_stats(struct net_device *ndev, struct ethtool_stats |
|
| 908 |
++ *stats, u64 *data) |
|
| 909 |
++{
|
|
| 910 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 911 |
++ int i; |
|
| 912 |
++ |
|
| 913 |
++ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) |
|
| 914 |
++ data[i] = readl(priv->EMAC_baseaddr + fec_stats[i].offset); |
|
| 915 |
++} |
|
| 916 |
++ |
|
| 917 |
++static void pfe_eth_gstrings(struct net_device *netdev, |
|
| 918 |
++ u32 stringset, u8 *data) |
|
| 919 |
++{
|
|
| 920 |
++ int i; |
|
| 921 |
++ |
|
| 922 |
++ switch (stringset) {
|
|
| 923 |
++ case ETH_SS_STATS: |
|
| 924 |
++ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) |
|
| 925 |
++ memcpy(data + i * ETH_GSTRING_LEN, |
|
| 926 |
++ fec_stats[i].name, ETH_GSTRING_LEN); |
|
| 927 |
++ break; |
|
| 928 |
++ } |
|
| 929 |
++} |
|
| 930 |
++ |
|
| 931 |
++static int pfe_eth_stats_count(struct net_device *ndev, int sset) |
|
| 932 |
++{
|
|
| 933 |
++ switch (sset) {
|
|
| 934 |
++ case ETH_SS_STATS: |
|
| 935 |
++ return ARRAY_SIZE(fec_stats); |
|
| 936 |
++ default: |
|
| 937 |
++ return -EOPNOTSUPP; |
|
| 938 |
++ } |
|
| 939 |
++} |
|
| 940 |
++ |
|
| 941 |
++/* |
|
| 942 |
++ * pfe_eth_gemac_reglen - Return the length of the register structure. |
|
| 943 |
++ * |
|
| 944 |
++ */ |
|
| 945 |
++static int pfe_eth_gemac_reglen(struct net_device *ndev) |
|
| 946 |
++{
|
|
| 947 |
++ pr_info("%s()\n", __func__);
|
|
| 948 |
++ return (sizeof(gemac_regs) / sizeof(u32)); |
|
| 949 |
++} |
|
| 950 |
++ |
|
| 951 |
++/* |
|
| 952 |
++ * pfe_eth_gemac_get_regs - Return the gemac register structure. |
|
| 953 |
++ * |
|
| 954 |
++ */ |
|
| 955 |
++static void pfe_eth_gemac_get_regs(struct net_device *ndev, struct ethtool_regs |
|
| 956 |
++ *regs, void *regbuf) |
|
| 957 |
++{
|
|
| 958 |
++ int i; |
|
| 959 |
++ |
|
| 960 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 961 |
++ u32 *buf = (u32 *)regbuf; |
|
| 962 |
++ |
|
| 963 |
++ pr_info("%s()\n", __func__);
|
|
| 964 |
++ for (i = 0; i < sizeof(gemac_regs) / sizeof(u32); i++) |
|
| 965 |
++ buf[i] = readl(priv->EMAC_baseaddr + gemac_regs[i]); |
|
| 966 |
++} |
|
| 967 |
++ |
|
| 968 |
++/* |
|
| 969 |
++ * pfe_eth_set_wol - Set the magic packet option, in WoL register. |
|
| 970 |
++ * |
|
| 971 |
++ */ |
|
| 972 |
++static int pfe_eth_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) |
|
| 973 |
++{
|
|
| 974 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 975 |
++ |
|
| 976 |
++ if (wol->wolopts & ~WAKE_MAGIC) |
|
| 977 |
++ return -EOPNOTSUPP; |
|
| 978 |
++ |
|
| 979 |
++ /* for MTIP we store wol->wolopts */ |
|
| 980 |
++ priv->wol = wol->wolopts; |
|
| 981 |
++ |
|
| 982 |
++ device_set_wakeup_enable(&ndev->dev, wol->wolopts & WAKE_MAGIC); |
|
| 983 |
++ |
|
| 984 |
++ return 0; |
|
| 985 |
++} |
|
| 986 |
++ |
|
| 987 |
++/* |
|
| 988 |
++ * |
|
| 989 |
++ * pfe_eth_get_wol - Get the WoL options. |
|
| 990 |
++ * |
|
| 991 |
++ */ |
|
| 992 |
++static void pfe_eth_get_wol(struct net_device *ndev, struct ethtool_wolinfo |
|
| 993 |
++ *wol) |
|
| 994 |
++{
|
|
| 995 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 996 |
++ |
|
| 997 |
++ wol->supported = WAKE_MAGIC; |
|
| 998 |
++ wol->wolopts = 0; |
|
| 999 |
++ |
|
| 1000 |
++ if (priv->wol & WAKE_MAGIC) |
|
| 1001 |
++ wol->wolopts = WAKE_MAGIC; |
|
| 1002 |
++ |
|
| 1003 |
++ memset(&wol->sopass, 0, sizeof(wol->sopass)); |
|
| 1004 |
++} |
|
| 1005 |
++ |
|
| 1006 |
++/* |
|
| 1007 |
++ * pfe_eth_get_drvinfo - Fills in the drvinfo structure with some basic info |
|
| 1008 |
++ * |
|
| 1009 |
++ */ |
|
| 1010 |
++static void pfe_eth_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo |
|
| 1011 |
++ *drvinfo) |
|
| 1012 |
++{
|
|
| 1013 |
++ strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); |
|
| 1014 |
++ strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); |
|
| 1015 |
++ strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); |
|
| 1016 |
++ strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); |
|
| 1017 |
++} |
|
| 1018 |
++ |
|
| 1019 |
++/* |
|
| 1020 |
++ * pfe_eth_set_settings - Used to send commands to PHY. |
|
| 1021 |
++ * |
|
| 1022 |
++ */ |
|
| 1023 |
++static int pfe_eth_set_settings(struct net_device *ndev, |
|
| 1024 |
++ const struct ethtool_link_ksettings *cmd) |
|
| 1025 |
++{
|
|
| 1026 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1027 |
++ struct phy_device *phydev = priv->phydev; |
|
| 1028 |
++ |
|
| 1029 |
++ if (!phydev) |
|
| 1030 |
++ return -ENODEV; |
|
| 1031 |
++ |
|
| 1032 |
++ return phy_ethtool_ksettings_set(phydev, cmd); |
|
| 1033 |
++} |
|
| 1034 |
++ |
|
| 1035 |
++/* |
|
| 1036 |
++ * pfe_eth_getsettings - Return the current settings in the ethtool_cmd |
|
| 1037 |
++ * structure. |
|
| 1038 |
++ * |
|
| 1039 |
++ */ |
|
| 1040 |
++static int pfe_eth_get_settings(struct net_device *ndev, |
|
| 1041 |
++ struct ethtool_link_ksettings *cmd) |
|
| 1042 |
++{
|
|
| 1043 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1044 |
++ struct phy_device *phydev = priv->phydev; |
|
| 1045 |
++ |
|
| 1046 |
++ if (!phydev) |
|
| 1047 |
++ return -ENODEV; |
|
| 1048 |
++ |
|
| 1049 |
++ return phy_ethtool_ksettings_get(phydev, cmd); |
|
| 1050 |
++} |
|
| 1051 |
++ |
|
| 1052 |
++/* |
|
| 1053 |
++ * pfe_eth_get_msglevel - Gets the debug message mask. |
|
| 1054 |
++ * |
|
| 1055 |
++ */ |
|
| 1056 |
++static uint32_t pfe_eth_get_msglevel(struct net_device *ndev) |
|
| 1057 |
++{
|
|
| 1058 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1059 |
++ |
|
| 1060 |
++ return priv->msg_enable; |
|
| 1061 |
++} |
|
| 1062 |
++ |
|
| 1063 |
++/* |
|
| 1064 |
++ * pfe_eth_set_msglevel - Sets the debug message mask. |
|
| 1065 |
++ * |
|
| 1066 |
++ */ |
|
| 1067 |
++static void pfe_eth_set_msglevel(struct net_device *ndev, uint32_t data) |
|
| 1068 |
++{
|
|
| 1069 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1070 |
++ |
|
| 1071 |
++ priv->msg_enable = data; |
|
| 1072 |
++} |
|
| 1073 |
++ |
|
| 1074 |
++#define HIF_RX_COAL_MAX_CLKS (~(1 << 31)) |
|
| 1075 |
++#define HIF_RX_COAL_CLKS_PER_USEC (pfe->ctrl.sys_clk / 1000) |
|
| 1076 |
++#define HIF_RX_COAL_MAX_USECS (HIF_RX_COAL_MAX_CLKS / \ |
|
| 1077 |
++ HIF_RX_COAL_CLKS_PER_USEC) |
|
| 1078 |
++ |
|
| 1079 |
++/* |
|
| 1080 |
++ * pfe_eth_set_coalesce - Sets rx interrupt coalescing timer. |
|
| 1081 |
++ * |
|
| 1082 |
++ */ |
|
| 1083 |
++static int pfe_eth_set_coalesce(struct net_device *ndev, |
|
| 1084 |
++ struct ethtool_coalesce *ec) |
|
| 1085 |
++{
|
|
| 1086 |
++ if (ec->rx_coalesce_usecs > HIF_RX_COAL_MAX_USECS) |
|
| 1087 |
++ return -EINVAL; |
|
| 1088 |
++ |
|
| 1089 |
++ if (!ec->rx_coalesce_usecs) {
|
|
| 1090 |
++ writel(0, HIF_INT_COAL); |
|
| 1091 |
++ return 0; |
|
| 1092 |
++ } |
|
| 1093 |
++ |
|
| 1094 |
++ writel((ec->rx_coalesce_usecs * HIF_RX_COAL_CLKS_PER_USEC) | |
|
| 1095 |
++ HIF_INT_COAL_ENABLE, HIF_INT_COAL); |
|
| 1096 |
++ |
|
| 1097 |
++ return 0; |
|
| 1098 |
++} |
|
| 1099 |
++ |
|
| 1100 |
++/* |
|
| 1101 |
++ * pfe_eth_get_coalesce - Gets rx interrupt coalescing timer value. |
|
| 1102 |
++ * |
|
| 1103 |
++ */ |
|
| 1104 |
++static int pfe_eth_get_coalesce(struct net_device *ndev, |
|
| 1105 |
++ struct ethtool_coalesce *ec) |
|
| 1106 |
++{
|
|
| 1107 |
++ int reg_val = readl(HIF_INT_COAL); |
|
| 1108 |
++ |
|
| 1109 |
++ if (reg_val & HIF_INT_COAL_ENABLE) |
|
| 1110 |
++ ec->rx_coalesce_usecs = (reg_val & HIF_RX_COAL_MAX_CLKS) / |
|
| 1111 |
++ HIF_RX_COAL_CLKS_PER_USEC; |
|
| 1112 |
++ else |
|
| 1113 |
++ ec->rx_coalesce_usecs = 0; |
|
| 1114 |
++ |
|
| 1115 |
++ return 0; |
|
| 1116 |
++} |
|
| 1117 |
++ |
|
| 1118 |
++/* |
|
| 1119 |
++ * pfe_eth_set_pauseparam - Sets pause parameters |
|
| 1120 |
++ * |
|
| 1121 |
++ */ |
|
| 1122 |
++static int pfe_eth_set_pauseparam(struct net_device *ndev, |
|
| 1123 |
++ struct ethtool_pauseparam *epause) |
|
| 1124 |
++{
|
|
| 1125 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1126 |
++ |
|
| 1127 |
++ if (epause->tx_pause != epause->rx_pause) {
|
|
| 1128 |
++ netdev_info(ndev, |
|
| 1129 |
++ "hardware only support enable/disable both tx and rx\n"); |
|
| 1130 |
++ return -EINVAL; |
|
| 1131 |
++ } |
|
| 1132 |
++ |
|
| 1133 |
++ priv->pause_flag = 0; |
|
| 1134 |
++ priv->pause_flag |= epause->rx_pause ? PFE_PAUSE_FLAG_ENABLE : 0; |
|
| 1135 |
++ priv->pause_flag |= epause->autoneg ? PFE_PAUSE_FLAG_AUTONEG : 0; |
|
| 1136 |
++ |
|
| 1137 |
++ if (epause->rx_pause || epause->autoneg) {
|
|
| 1138 |
++ gemac_enable_pause_rx(priv->EMAC_baseaddr); |
|
| 1139 |
++ writel((readl(priv->GPI_baseaddr + GPI_TX_PAUSE_TIME) | |
|
| 1140 |
++ EGPI_PAUSE_ENABLE), |
|
| 1141 |
++ priv->GPI_baseaddr + GPI_TX_PAUSE_TIME); |
|
| 1142 |
++ if (priv->phydev) {
|
|
| 1143 |
++ priv->phydev->supported |= ADVERTISED_Pause | |
|
| 1144 |
++ ADVERTISED_Asym_Pause; |
|
| 1145 |
++ priv->phydev->advertising |= ADVERTISED_Pause | |
|
| 1146 |
++ ADVERTISED_Asym_Pause; |
|
| 1147 |
++ } |
|
| 1148 |
++ } else {
|
|
| 1149 |
++ gemac_disable_pause_rx(priv->EMAC_baseaddr); |
|
| 1150 |
++ writel((readl(priv->GPI_baseaddr + GPI_TX_PAUSE_TIME) & |
|
| 1151 |
++ ~EGPI_PAUSE_ENABLE), |
|
| 1152 |
++ priv->GPI_baseaddr + GPI_TX_PAUSE_TIME); |
|
| 1153 |
++ if (priv->phydev) {
|
|
| 1154 |
++ priv->phydev->supported &= ~(ADVERTISED_Pause | |
|
| 1155 |
++ ADVERTISED_Asym_Pause); |
|
| 1156 |
++ priv->phydev->advertising &= ~(ADVERTISED_Pause | |
|
| 1157 |
++ ADVERTISED_Asym_Pause); |
|
| 1158 |
++ } |
|
| 1159 |
++ } |
|
| 1160 |
++ |
|
| 1161 |
++ return 0; |
|
| 1162 |
++} |
|
| 1163 |
++ |
|
| 1164 |
++/* |
|
| 1165 |
++ * pfe_eth_get_pauseparam - Gets pause parameters |
|
| 1166 |
++ * |
|
| 1167 |
++ */ |
|
| 1168 |
++static void pfe_eth_get_pauseparam(struct net_device *ndev, |
|
| 1169 |
++ struct ethtool_pauseparam *epause) |
|
| 1170 |
++{
|
|
| 1171 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1172 |
++ |
|
| 1173 |
++ epause->autoneg = (priv->pause_flag & PFE_PAUSE_FLAG_AUTONEG) != 0; |
|
| 1174 |
++ epause->tx_pause = (priv->pause_flag & PFE_PAUSE_FLAG_ENABLE) != 0; |
|
| 1175 |
++ epause->rx_pause = epause->tx_pause; |
|
| 1176 |
++} |
|
| 1177 |
++ |
|
| 1178 |
++/* |
|
| 1179 |
++ * pfe_eth_get_hash |
|
| 1180 |
++ */ |
|
| 1181 |
++#define PFE_HASH_BITS 6 /* #bits in hash */ |
|
| 1182 |
++#define CRC32_POLY 0xEDB88320 |
|
| 1183 |
++ |
|
| 1184 |
++static int pfe_eth_get_hash(u8 *addr) |
|
| 1185 |
++{
|
|
| 1186 |
++ unsigned int i, bit, data, crc, hash; |
|
| 1187 |
++ |
|
| 1188 |
++ /* calculate crc32 value of mac address */ |
|
| 1189 |
++ crc = 0xffffffff; |
|
| 1190 |
++ |
|
| 1191 |
++ for (i = 0; i < 6; i++) {
|
|
| 1192 |
++ data = addr[i]; |
|
| 1193 |
++ for (bit = 0; bit < 8; bit++, data >>= 1) {
|
|
| 1194 |
++ crc = (crc >> 1) ^ |
|
| 1195 |
++ (((crc ^ data) & 1) ? CRC32_POLY : 0); |
|
| 1196 |
++ } |
|
| 1197 |
++ } |
|
| 1198 |
++ |
|
| 1199 |
++ /* |
|
| 1200 |
++ * only upper 6 bits (PFE_HASH_BITS) are used |
|
| 1201 |
++ * which point to specific bit in the hash registers |
|
| 1202 |
++ */ |
|
| 1203 |
++ hash = (crc >> (32 - PFE_HASH_BITS)) & 0x3f; |
|
| 1204 |
++ |
|
| 1205 |
++ return hash; |
|
| 1206 |
++} |
|
| 1207 |
++ |
|
| 1208 |
++const struct ethtool_ops pfe_ethtool_ops = {
|
|
| 1209 |
++ .get_drvinfo = pfe_eth_get_drvinfo, |
|
| 1210 |
++ .get_regs_len = pfe_eth_gemac_reglen, |
|
| 1211 |
++ .get_regs = pfe_eth_gemac_get_regs, |
|
| 1212 |
++ .get_link = ethtool_op_get_link, |
|
| 1213 |
++ .get_wol = pfe_eth_get_wol, |
|
| 1214 |
++ .set_wol = pfe_eth_set_wol, |
|
| 1215 |
++ .set_pauseparam = pfe_eth_set_pauseparam, |
|
| 1216 |
++ .get_pauseparam = pfe_eth_get_pauseparam, |
|
| 1217 |
++ .get_strings = pfe_eth_gstrings, |
|
| 1218 |
++ .get_sset_count = pfe_eth_stats_count, |
|
| 1219 |
++ .get_ethtool_stats = pfe_eth_fill_stats, |
|
| 1220 |
++ .get_msglevel = pfe_eth_get_msglevel, |
|
| 1221 |
++ .set_msglevel = pfe_eth_set_msglevel, |
|
| 1222 |
++ .set_coalesce = pfe_eth_set_coalesce, |
|
| 1223 |
++ .get_coalesce = pfe_eth_get_coalesce, |
|
| 1224 |
++ .get_link_ksettings = pfe_eth_get_settings, |
|
| 1225 |
++ .set_link_ksettings = pfe_eth_set_settings, |
|
| 1226 |
++}; |
|
| 1227 |
++ |
|
| 1228 |
++/* pfe_eth_mdio_reset |
|
| 1229 |
++ */ |
|
| 1230 |
++int pfe_eth_mdio_reset(struct mii_bus *bus) |
|
| 1231 |
++{
|
|
| 1232 |
++ struct pfe_eth_priv_s *priv = (struct pfe_eth_priv_s *)bus->priv; |
|
| 1233 |
++ u32 phy_speed; |
|
| 1234 |
++ |
|
| 1235 |
++ netif_info(priv, hw, priv->ndev, "%s\n", __func__); |
|
| 1236 |
++ |
|
| 1237 |
++ mutex_lock(&bus->mdio_lock); |
|
| 1238 |
++ |
|
| 1239 |
++ /* |
|
| 1240 |
++ * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed) |
|
| 1241 |
++ * |
|
| 1242 |
++ * The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while |
|
| 1243 |
++ * for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'. |
|
| 1244 |
++ */ |
|
| 1245 |
++ phy_speed = (DIV_ROUND_UP((pfe->ctrl.sys_clk * 1000), 4000000) |
|
| 1246 |
++ << EMAC_MII_SPEED_SHIFT); |
|
| 1247 |
++ phy_speed |= EMAC_HOLDTIME(0x5); |
|
| 1248 |
++ __raw_writel(phy_speed, priv->PHY_baseaddr + EMAC_MII_CTRL_REG); |
|
| 1249 |
++ |
|
| 1250 |
++ mutex_unlock(&bus->mdio_lock); |
|
| 1251 |
++ |
|
| 1252 |
++ return 0; |
|
| 1253 |
++} |
|
| 1254 |
++ |
|
| 1255 |
++/* pfe_eth_gemac_phy_timeout |
|
| 1256 |
++ * |
|
| 1257 |
++ */ |
|
| 1258 |
++static int pfe_eth_gemac_phy_timeout(struct pfe_eth_priv_s *priv, int timeout) |
|
| 1259 |
++{
|
|
| 1260 |
++ while (!(__raw_readl(priv->PHY_baseaddr + EMAC_IEVENT_REG) & |
|
| 1261 |
++ EMAC_IEVENT_MII)) {
|
|
| 1262 |
++ if (timeout-- <= 0) |
|
| 1263 |
++ return -1; |
|
| 1264 |
++ usleep_range(10, 20); |
|
| 1265 |
++ } |
|
| 1266 |
++ __raw_writel(EMAC_IEVENT_MII, priv->PHY_baseaddr + EMAC_IEVENT_REG); |
|
| 1267 |
++ return 0; |
|
| 1268 |
++} |
|
| 1269 |
++ |
|
| 1270 |
++static int pfe_eth_mdio_mux(u8 muxval) |
|
| 1271 |
++{
|
|
| 1272 |
++ struct i2c_adapter *a; |
|
| 1273 |
++ struct i2c_msg msg; |
|
| 1274 |
++ unsigned char buf[2]; |
|
| 1275 |
++ int ret; |
|
| 1276 |
++ |
|
| 1277 |
++ a = i2c_get_adapter(0); |
|
| 1278 |
++ if (!a) |
|
| 1279 |
++ return -ENODEV; |
|
| 1280 |
++ |
|
| 1281 |
++ /* set bit 1 (the second bit) of chip at 0x09, register 0x13 */ |
|
| 1282 |
++ buf[0] = 0x54; /* reg number */ |
|
| 1283 |
++ buf[1] = (muxval << 6) | 0x3; /* data */ |
|
| 1284 |
++ msg.addr = 0x66; |
|
| 1285 |
++ msg.buf = buf; |
|
| 1286 |
++ msg.len = 2; |
|
| 1287 |
++ msg.flags = 0; |
|
| 1288 |
++ ret = i2c_transfer(a, &msg, 1); |
|
| 1289 |
++ i2c_put_adapter(a); |
|
| 1290 |
++ if (ret != 1) |
|
| 1291 |
++ return -ENODEV; |
|
| 1292 |
++ return 0; |
|
| 1293 |
++} |
|
| 1294 |
++ |
|
| 1295 |
++static int pfe_eth_mdio_write_addr(struct mii_bus *bus, int mii_id, |
|
| 1296 |
++ int dev_addr, int regnum) |
|
| 1297 |
++{
|
|
| 1298 |
++ struct pfe_eth_priv_s *priv = (struct pfe_eth_priv_s *)bus->priv; |
|
| 1299 |
++ |
|
| 1300 |
++ __raw_writel(EMAC_MII_DATA_PA(mii_id) | |
|
| 1301 |
++ EMAC_MII_DATA_RA(dev_addr) | |
|
| 1302 |
++ EMAC_MII_DATA_TA | EMAC_MII_DATA(regnum), |
|
| 1303 |
++ priv->PHY_baseaddr + EMAC_MII_DATA_REG); |
|
| 1304 |
++ |
|
| 1305 |
++ if (pfe_eth_gemac_phy_timeout(priv, EMAC_MDIO_TIMEOUT)) {
|
|
| 1306 |
++ netdev_err(priv->ndev, "%s: phy MDIO address write timeout\n", |
|
| 1307 |
++ __func__); |
|
| 1308 |
++ return -1; |
|
| 1309 |
++ } |
|
| 1310 |
++ |
|
| 1311 |
++ return 0; |
|
| 1312 |
++} |
|
| 1313 |
++ |
|
| 1314 |
++static int pfe_eth_mdio_write(struct mii_bus *bus, int mii_id, int regnum, |
|
| 1315 |
++ u16 value) |
|
| 1316 |
++{
|
|
| 1317 |
++ struct pfe_eth_priv_s *priv = (struct pfe_eth_priv_s *)bus->priv; |
|
| 1318 |
++ |
|
| 1319 |
++ /*To access external PHYs on QDS board mux needs to be configured*/ |
|
| 1320 |
++ if ((mii_id) && (pfe->mdio_muxval[mii_id])) |
|
| 1321 |
++ pfe_eth_mdio_mux(pfe->mdio_muxval[mii_id]); |
|
| 1322 |
++ |
|
| 1323 |
++ if (regnum & MII_ADDR_C45) {
|
|
| 1324 |
++ pfe_eth_mdio_write_addr(bus, mii_id, (regnum >> 16) & 0x1f, |
|
| 1325 |
++ regnum & 0xffff); |
|
| 1326 |
++ __raw_writel(EMAC_MII_DATA_OP_CL45_WR | |
|
| 1327 |
++ EMAC_MII_DATA_PA(mii_id) | |
|
| 1328 |
++ EMAC_MII_DATA_RA((regnum >> 16) & 0x1f) | |
|
| 1329 |
++ EMAC_MII_DATA_TA | EMAC_MII_DATA(value), |
|
| 1330 |
++ priv->PHY_baseaddr + EMAC_MII_DATA_REG); |
|
| 1331 |
++ } else {
|
|
| 1332 |
++ /* start a write op */ |
|
| 1333 |
++ __raw_writel(EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR | |
|
| 1334 |
++ EMAC_MII_DATA_PA(mii_id) | |
|
| 1335 |
++ EMAC_MII_DATA_RA(regnum) | |
|
| 1336 |
++ EMAC_MII_DATA_TA | EMAC_MII_DATA(value), |
|
| 1337 |
++ priv->PHY_baseaddr + EMAC_MII_DATA_REG); |
|
| 1338 |
++ } |
|
| 1339 |
++ |
|
| 1340 |
++ if (pfe_eth_gemac_phy_timeout(priv, EMAC_MDIO_TIMEOUT)) {
|
|
| 1341 |
++ netdev_err(priv->ndev, "%s: phy MDIO write timeout\n", |
|
| 1342 |
++ __func__); |
|
| 1343 |
++ return -1; |
|
| 1344 |
++ } |
|
| 1345 |
++ netif_info(priv, hw, priv->ndev, "%s: phy %x reg %x val %x\n", __func__, |
|
| 1346 |
++ mii_id, regnum, value); |
|
| 1347 |
++ |
|
| 1348 |
++ return 0; |
|
| 1349 |
++} |
|
| 1350 |
++ |
|
| 1351 |
++static int pfe_eth_mdio_read(struct mii_bus *bus, int mii_id, int regnum) |
|
| 1352 |
++{
|
|
| 1353 |
++ struct pfe_eth_priv_s *priv = (struct pfe_eth_priv_s *)bus->priv; |
|
| 1354 |
++ u16 value = 0; |
|
| 1355 |
++ |
|
| 1356 |
++ /*To access external PHYs on QDS board mux needs to be configured*/ |
|
| 1357 |
++ if ((mii_id) && (pfe->mdio_muxval[mii_id])) |
|
| 1358 |
++ pfe_eth_mdio_mux(pfe->mdio_muxval[mii_id]); |
|
| 1359 |
++ |
|
| 1360 |
++ if (regnum & MII_ADDR_C45) {
|
|
| 1361 |
++ pfe_eth_mdio_write_addr(bus, mii_id, (regnum >> 16) & 0x1f, |
|
| 1362 |
++ regnum & 0xffff); |
|
| 1363 |
++ __raw_writel(EMAC_MII_DATA_OP_CL45_RD | |
|
| 1364 |
++ EMAC_MII_DATA_PA(mii_id) | |
|
| 1365 |
++ EMAC_MII_DATA_RA((regnum >> 16) & 0x1f) | |
|
| 1366 |
++ EMAC_MII_DATA_TA, |
|
| 1367 |
++ priv->PHY_baseaddr + EMAC_MII_DATA_REG); |
|
| 1368 |
++ } else {
|
|
| 1369 |
++ /* start a read op */ |
|
| 1370 |
++ __raw_writel(EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD | |
|
| 1371 |
++ EMAC_MII_DATA_PA(mii_id) | |
|
| 1372 |
++ EMAC_MII_DATA_RA(regnum) | |
|
| 1373 |
++ EMAC_MII_DATA_TA, priv->PHY_baseaddr + |
|
| 1374 |
++ EMAC_MII_DATA_REG); |
|
| 1375 |
++ } |
|
| 1376 |
++ |
|
| 1377 |
++ if (pfe_eth_gemac_phy_timeout(priv, EMAC_MDIO_TIMEOUT)) {
|
|
| 1378 |
++ netdev_err(priv->ndev, "%s: phy MDIO read timeout\n", __func__); |
|
| 1379 |
++ return -1; |
|
| 1380 |
++ } |
|
| 1381 |
++ |
|
| 1382 |
++ value = EMAC_MII_DATA(__raw_readl(priv->PHY_baseaddr + |
|
| 1383 |
++ EMAC_MII_DATA_REG)); |
|
| 1384 |
++ netif_info(priv, hw, priv->ndev, "%s: phy %x reg %x val %x\n", __func__, |
|
| 1385 |
++ mii_id, regnum, value); |
|
| 1386 |
++ return value; |
|
| 1387 |
++} |
|
| 1388 |
++ |
|
| 1389 |
++static int pfe_eth_mdio_init(struct pfe_eth_priv_s *priv, |
|
| 1390 |
++ struct ls1012a_mdio_platform_data *minfo) |
|
| 1391 |
++{
|
|
| 1392 |
++ struct mii_bus *bus; |
|
| 1393 |
++ int rc; |
|
| 1394 |
++ |
|
| 1395 |
++ netif_info(priv, drv, priv->ndev, "%s\n", __func__); |
|
| 1396 |
++ pr_info("%s\n", __func__);
|
|
| 1397 |
++ |
|
| 1398 |
++ bus = mdiobus_alloc(); |
|
| 1399 |
++ if (!bus) {
|
|
| 1400 |
++ netdev_err(priv->ndev, "mdiobus_alloc() failed\n"); |
|
| 1401 |
++ rc = -ENOMEM; |
|
| 1402 |
++ goto err0; |
|
| 1403 |
++ } |
|
| 1404 |
++ |
|
| 1405 |
++ bus->name = "ls1012a MDIO Bus"; |
|
| 1406 |
++ bus->read = &pfe_eth_mdio_read; |
|
| 1407 |
++ bus->write = &pfe_eth_mdio_write; |
|
| 1408 |
++ bus->reset = &pfe_eth_mdio_reset; |
|
| 1409 |
++ snprintf(bus->id, MII_BUS_ID_SIZE, "ls1012a-%x", priv->id); |
|
| 1410 |
++ bus->priv = priv; |
|
| 1411 |
++ |
|
| 1412 |
++ bus->phy_mask = minfo->phy_mask; |
|
| 1413 |
++ priv->mdc_div = minfo->mdc_div; |
|
| 1414 |
++ |
|
| 1415 |
++ if (!priv->mdc_div) |
|
| 1416 |
++ priv->mdc_div = 64; |
|
| 1417 |
++ |
|
| 1418 |
++ bus->irq[0] = minfo->irq[0]; |
|
| 1419 |
++ |
|
| 1420 |
++ bus->parent = priv->pfe->dev; |
|
| 1421 |
++ |
|
| 1422 |
++ netif_info(priv, drv, priv->ndev, "%s: mdc_div: %d, phy_mask: %x\n", |
|
| 1423 |
++ __func__, priv->mdc_div, bus->phy_mask); |
|
| 1424 |
++ rc = mdiobus_register(bus); |
|
| 1425 |
++ if (rc) {
|
|
| 1426 |
++ netdev_err(priv->ndev, "mdiobus_register(%s) failed\n", |
|
| 1427 |
++ bus->name); |
|
| 1428 |
++ goto err1; |
|
| 1429 |
++ } |
|
| 1430 |
++ |
|
| 1431 |
++ priv->mii_bus = bus; |
|
| 1432 |
++ pfe_eth_mdio_reset(bus); |
|
| 1433 |
++ |
|
| 1434 |
++ return 0; |
|
| 1435 |
++ |
|
| 1436 |
++err1: |
|
| 1437 |
++ mdiobus_free(bus); |
|
| 1438 |
++err0: |
|
| 1439 |
++ return rc; |
|
| 1440 |
++} |
|
| 1441 |
++ |
|
| 1442 |
++/* pfe_eth_mdio_exit |
|
| 1443 |
++ */ |
|
| 1444 |
++static void pfe_eth_mdio_exit(struct mii_bus *bus) |
|
| 1445 |
++{
|
|
| 1446 |
++ if (!bus) |
|
| 1447 |
++ return; |
|
| 1448 |
++ |
|
| 1449 |
++ netif_info((struct pfe_eth_priv_s *)bus->priv, drv, ((struct |
|
| 1450 |
++ pfe_eth_priv_s *)(bus->priv))->ndev, "%s\n", __func__); |
|
| 1451 |
++ |
|
| 1452 |
++ mdiobus_unregister(bus); |
|
| 1453 |
++ mdiobus_free(bus); |
|
| 1454 |
++} |
|
| 1455 |
++ |
|
| 1456 |
++/* pfe_get_phydev_speed |
|
| 1457 |
++ */ |
|
| 1458 |
++static int pfe_get_phydev_speed(struct phy_device *phydev) |
|
| 1459 |
++{
|
|
| 1460 |
++ switch (phydev->speed) {
|
|
| 1461 |
++ case 10: |
|
| 1462 |
++ return SPEED_10M; |
|
| 1463 |
++ case 100: |
|
| 1464 |
++ return SPEED_100M; |
|
| 1465 |
++ case 1000: |
|
| 1466 |
++ default: |
|
| 1467 |
++ return SPEED_1000M; |
|
| 1468 |
++ } |
|
| 1469 |
++} |
|
| 1470 |
++ |
|
| 1471 |
++/* pfe_set_rgmii_speed |
|
| 1472 |
++ */ |
|
| 1473 |
++#define RGMIIPCR 0x434 |
|
| 1474 |
++/* RGMIIPCR bit definitions*/ |
|
| 1475 |
++#define SCFG_RGMIIPCR_EN_AUTO (0x00000008) |
|
| 1476 |
++#define SCFG_RGMIIPCR_SETSP_1000M (0x00000004) |
|
| 1477 |
++#define SCFG_RGMIIPCR_SETSP_100M (0x00000000) |
|
| 1478 |
++#define SCFG_RGMIIPCR_SETSP_10M (0x00000002) |
|
| 1479 |
++#define SCFG_RGMIIPCR_SETFD (0x00000001) |
|
| 1480 |
++ |
|
| 1481 |
++static void pfe_set_rgmii_speed(struct phy_device *phydev) |
|
| 1482 |
++{
|
|
| 1483 |
++ u32 rgmii_pcr; |
|
| 1484 |
++ |
|
| 1485 |
++ regmap_read(pfe->scfg, RGMIIPCR, &rgmii_pcr); |
|
| 1486 |
++ rgmii_pcr &= ~(SCFG_RGMIIPCR_SETSP_1000M | SCFG_RGMIIPCR_SETSP_10M); |
|
| 1487 |
++ |
|
| 1488 |
++ switch (phydev->speed) {
|
|
| 1489 |
++ case 10: |
|
| 1490 |
++ rgmii_pcr |= SCFG_RGMIIPCR_SETSP_10M; |
|
| 1491 |
++ break; |
|
| 1492 |
++ case 1000: |
|
| 1493 |
++ rgmii_pcr |= SCFG_RGMIIPCR_SETSP_1000M; |
|
| 1494 |
++ break; |
|
| 1495 |
++ case 100: |
|
| 1496 |
++ default: |
|
| 1497 |
++ /* Default is 100M */ |
|
| 1498 |
++ break; |
|
| 1499 |
++ } |
|
| 1500 |
++ regmap_write(pfe->scfg, RGMIIPCR, rgmii_pcr); |
|
| 1501 |
++} |
|
| 1502 |
++ |
|
| 1503 |
++/* pfe_get_phydev_duplex |
|
| 1504 |
++ */ |
|
| 1505 |
++static int pfe_get_phydev_duplex(struct phy_device *phydev) |
|
| 1506 |
++{
|
|
| 1507 |
++ /*return (phydev->duplex == DUPLEX_HALF) ? DUP_HALF:DUP_FULL ; */ |
|
| 1508 |
++ return DUPLEX_FULL; |
|
| 1509 |
++} |
|
| 1510 |
++ |
|
| 1511 |
++/* pfe_eth_adjust_link |
|
| 1512 |
++ */ |
|
| 1513 |
++static void pfe_eth_adjust_link(struct net_device *ndev) |
|
| 1514 |
++{
|
|
| 1515 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1516 |
++ unsigned long flags; |
|
| 1517 |
++ struct phy_device *phydev = priv->phydev; |
|
| 1518 |
++ int new_state = 0; |
|
| 1519 |
++ |
|
| 1520 |
++ netif_info(priv, drv, ndev, "%s\n", __func__); |
|
| 1521 |
++ |
|
| 1522 |
++ spin_lock_irqsave(&priv->lock, flags); |
|
| 1523 |
++ |
|
| 1524 |
++ if (phydev->link) {
|
|
| 1525 |
++ /* |
|
| 1526 |
++ * Now we make sure that we can be in full duplex mode. |
|
| 1527 |
++ * If not, we operate in half-duplex mode. |
|
| 1528 |
++ */ |
|
| 1529 |
++ if (phydev->duplex != priv->oldduplex) {
|
|
| 1530 |
++ new_state = 1; |
|
| 1531 |
++ gemac_set_duplex(priv->EMAC_baseaddr, |
|
| 1532 |
++ pfe_get_phydev_duplex(phydev)); |
|
| 1533 |
++ priv->oldduplex = phydev->duplex; |
|
| 1534 |
++ } |
|
| 1535 |
++ |
|
| 1536 |
++ if (phydev->speed != priv->oldspeed) {
|
|
| 1537 |
++ new_state = 1; |
|
| 1538 |
++ gemac_set_speed(priv->EMAC_baseaddr, |
|
| 1539 |
++ pfe_get_phydev_speed(phydev)); |
|
| 1540 |
++ if (priv->einfo->mii_config == PHY_INTERFACE_MODE_RGMII) |
|
| 1541 |
++ pfe_set_rgmii_speed(phydev); |
|
| 1542 |
++ priv->oldspeed = phydev->speed; |
|
| 1543 |
++ } |
|
| 1544 |
++ |
|
| 1545 |
++ if (!priv->oldlink) {
|
|
| 1546 |
++ new_state = 1; |
|
| 1547 |
++ priv->oldlink = 1; |
|
| 1548 |
++ } |
|
| 1549 |
++ |
|
| 1550 |
++ } else if (priv->oldlink) {
|
|
| 1551 |
++ new_state = 1; |
|
| 1552 |
++ priv->oldlink = 0; |
|
| 1553 |
++ priv->oldspeed = 0; |
|
| 1554 |
++ priv->oldduplex = -1; |
|
| 1555 |
++ } |
|
| 1556 |
++ |
|
| 1557 |
++ if (new_state && netif_msg_link(priv)) |
|
| 1558 |
++ phy_print_status(phydev); |
|
| 1559 |
++ |
|
| 1560 |
++ spin_unlock_irqrestore(&priv->lock, flags); |
|
| 1561 |
++} |
|
| 1562 |
++ |
|
| 1563 |
++/* pfe_phy_exit |
|
| 1564 |
++ */ |
|
| 1565 |
++static void pfe_phy_exit(struct net_device *ndev) |
|
| 1566 |
++{
|
|
| 1567 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1568 |
++ |
|
| 1569 |
++ netif_info(priv, drv, ndev, "%s\n", __func__); |
|
| 1570 |
++ |
|
| 1571 |
++ phy_disconnect(priv->phydev); |
|
| 1572 |
++ priv->phydev = NULL; |
|
| 1573 |
++} |
|
| 1574 |
++ |
|
| 1575 |
++/* pfe_eth_stop |
|
| 1576 |
++ */ |
|
| 1577 |
++static void pfe_eth_stop(struct net_device *ndev, int wake) |
|
| 1578 |
++{
|
|
| 1579 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1580 |
++ |
|
| 1581 |
++ netif_info(priv, drv, ndev, "%s\n", __func__); |
|
| 1582 |
++ |
|
| 1583 |
++ if (wake) {
|
|
| 1584 |
++ gemac_tx_disable(priv->EMAC_baseaddr); |
|
| 1585 |
++ } else {
|
|
| 1586 |
++ gemac_disable(priv->EMAC_baseaddr); |
|
| 1587 |
++ gpi_disable(priv->GPI_baseaddr); |
|
| 1588 |
++ |
|
| 1589 |
++ if (priv->phydev) |
|
| 1590 |
++ phy_stop(priv->phydev); |
|
| 1591 |
++ } |
|
| 1592 |
++} |
|
| 1593 |
++ |
|
| 1594 |
++/* pfe_eth_start |
|
| 1595 |
++ */ |
|
| 1596 |
++static int pfe_eth_start(struct pfe_eth_priv_s *priv) |
|
| 1597 |
++{
|
|
| 1598 |
++ netif_info(priv, drv, priv->ndev, "%s\n", __func__); |
|
| 1599 |
++ |
|
| 1600 |
++ if (priv->phydev) |
|
| 1601 |
++ phy_start(priv->phydev); |
|
| 1602 |
++ |
|
| 1603 |
++ gpi_enable(priv->GPI_baseaddr); |
|
| 1604 |
++ gemac_enable(priv->EMAC_baseaddr); |
|
| 1605 |
++ |
|
| 1606 |
++ return 0; |
|
| 1607 |
++} |
|
| 1608 |
++ |
|
| 1609 |
++/* |
|
| 1610 |
++ * Configure on chip serdes through mdio |
|
| 1611 |
++ */ |
|
| 1612 |
++static void ls1012a_configure_serdes(struct net_device *ndev) |
|
| 1613 |
++{
|
|
| 1614 |
++ struct pfe_eth_priv_s *priv = pfe->eth.eth_priv[0]; |
|
| 1615 |
++ int sgmii_2500 = 0; |
|
| 1616 |
++ struct mii_bus *bus = priv->mii_bus; |
|
| 1617 |
++ |
|
| 1618 |
++ if (priv->einfo->mii_config == PHY_INTERFACE_MODE_SGMII_2500) |
|
| 1619 |
++ sgmii_2500 = 1; |
|
| 1620 |
++ |
|
| 1621 |
++ netif_info(priv, drv, ndev, "%s\n", __func__); |
|
| 1622 |
++ /* PCS configuration done with corresponding GEMAC */ |
|
| 1623 |
++ |
|
| 1624 |
++ pfe_eth_mdio_read(bus, 0, 0); |
|
| 1625 |
++ pfe_eth_mdio_read(bus, 0, 1); |
|
| 1626 |
++ |
|
| 1627 |
++ /*These settings taken from validtion team */ |
|
| 1628 |
++ pfe_eth_mdio_write(bus, 0, 0x0, 0x8000); |
|
| 1629 |
++ if (sgmii_2500) {
|
|
| 1630 |
++ pfe_eth_mdio_write(bus, 0, 0x14, 0x9); |
|
| 1631 |
++ pfe_eth_mdio_write(bus, 0, 0x4, 0x4001); |
|
| 1632 |
++ pfe_eth_mdio_write(bus, 0, 0x12, 0xa120); |
|
| 1633 |
++ pfe_eth_mdio_write(bus, 0, 0x13, 0x7); |
|
| 1634 |
++ } else {
|
|
| 1635 |
++ pfe_eth_mdio_write(bus, 0, 0x14, 0xb); |
|
| 1636 |
++ pfe_eth_mdio_write(bus, 0, 0x4, 0x1a1); |
|
| 1637 |
++ pfe_eth_mdio_write(bus, 0, 0x12, 0x400); |
|
| 1638 |
++ pfe_eth_mdio_write(bus, 0, 0x13, 0x0); |
|
| 1639 |
++ } |
|
| 1640 |
++ |
|
| 1641 |
++ pfe_eth_mdio_write(bus, 0, 0x0, 0x1140); |
|
| 1642 |
++} |
|
| 1643 |
++ |
|
| 1644 |
++/* |
|
| 1645 |
++ * pfe_phy_init |
|
| 1646 |
++ * |
|
| 1647 |
++ */ |
|
| 1648 |
++static int pfe_phy_init(struct net_device *ndev) |
|
| 1649 |
++{
|
|
| 1650 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1651 |
++ struct phy_device *phydev; |
|
| 1652 |
++ char phy_id[MII_BUS_ID_SIZE + 3]; |
|
| 1653 |
++ char bus_id[MII_BUS_ID_SIZE]; |
|
| 1654 |
++ phy_interface_t interface; |
|
| 1655 |
++ |
|
| 1656 |
++ priv->oldlink = 0; |
|
| 1657 |
++ priv->oldspeed = 0; |
|
| 1658 |
++ priv->oldduplex = -1; |
|
| 1659 |
++ |
|
| 1660 |
++ snprintf(bus_id, MII_BUS_ID_SIZE, "ls1012a-%d", 0); |
|
| 1661 |
++ snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, |
|
| 1662 |
++ priv->einfo->phy_id); |
|
| 1663 |
++ |
|
| 1664 |
++ netif_info(priv, drv, ndev, "%s: %s\n", __func__, phy_id); |
|
| 1665 |
++ interface = priv->einfo->mii_config; |
|
| 1666 |
++ if ((interface == PHY_INTERFACE_MODE_SGMII) || |
|
| 1667 |
++ (interface == PHY_INTERFACE_MODE_SGMII_2500)) {
|
|
| 1668 |
++ /*Configure SGMII PCS */ |
|
| 1669 |
++ if (pfe->scfg) {
|
|
| 1670 |
++ /*Config MDIO from serdes */ |
|
| 1671 |
++ regmap_write(pfe->scfg, 0x484, 0x00000000); |
|
| 1672 |
++ } |
|
| 1673 |
++ ls1012a_configure_serdes(ndev); |
|
| 1674 |
++ } |
|
| 1675 |
++ |
|
| 1676 |
++ if (pfe->scfg) {
|
|
| 1677 |
++ /*Config MDIO from PAD */ |
|
| 1678 |
++ regmap_write(pfe->scfg, 0x484, 0x80000000); |
|
| 1679 |
++ } |
|
| 1680 |
++ |
|
| 1681 |
++ priv->oldlink = 0; |
|
| 1682 |
++ priv->oldspeed = 0; |
|
| 1683 |
++ priv->oldduplex = -1; |
|
| 1684 |
++ pr_info("%s interface %x\n", __func__, interface);
|
|
| 1685 |
++ phydev = phy_connect(ndev, phy_id, &pfe_eth_adjust_link, interface); |
|
| 1686 |
++ |
|
| 1687 |
++ if (IS_ERR(phydev)) {
|
|
| 1688 |
++ netdev_err(ndev, "phy_connect() failed\n"); |
|
| 1689 |
++ return PTR_ERR(phydev); |
|
| 1690 |
++ } |
|
| 1691 |
++ |
|
| 1692 |
++ priv->phydev = phydev; |
|
| 1693 |
++ phydev->irq = PHY_POLL; |
|
| 1694 |
++ |
|
| 1695 |
++ return 0; |
|
| 1696 |
++} |
|
| 1697 |
++ |
|
| 1698 |
++/* pfe_gemac_init |
|
| 1699 |
++ */ |
|
| 1700 |
++static int pfe_gemac_init(struct pfe_eth_priv_s *priv) |
|
| 1701 |
++{
|
|
| 1702 |
++ struct gemac_cfg cfg; |
|
| 1703 |
++ |
|
| 1704 |
++ netif_info(priv, ifup, priv->ndev, "%s\n", __func__); |
|
| 1705 |
++ |
|
| 1706 |
++ cfg.speed = SPEED_1000M; |
|
| 1707 |
++ cfg.duplex = DUPLEX_FULL; |
|
| 1708 |
++ |
|
| 1709 |
++ gemac_set_config(priv->EMAC_baseaddr, &cfg); |
|
| 1710 |
++ gemac_allow_broadcast(priv->EMAC_baseaddr); |
|
| 1711 |
++ gemac_enable_1536_rx(priv->EMAC_baseaddr); |
|
| 1712 |
++ gemac_enable_rx_jmb(priv->EMAC_baseaddr); |
|
| 1713 |
++ gemac_enable_stacked_vlan(priv->EMAC_baseaddr); |
|
| 1714 |
++ gemac_enable_pause_rx(priv->EMAC_baseaddr); |
|
| 1715 |
++ gemac_set_bus_width(priv->EMAC_baseaddr, 64); |
|
| 1716 |
++ |
|
| 1717 |
++ /*GEM will perform checksum verifications*/ |
|
| 1718 |
++ if (priv->ndev->features & NETIF_F_RXCSUM) |
|
| 1719 |
++ gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr); |
|
| 1720 |
++ else |
|
| 1721 |
++ gemac_disable_rx_checksum_offload(priv->EMAC_baseaddr); |
|
| 1722 |
++ |
|
| 1723 |
++ return 0; |
|
| 1724 |
++} |
|
| 1725 |
++ |
|
| 1726 |
++/* pfe_eth_event_handler |
|
| 1727 |
++ */ |
|
| 1728 |
++static int pfe_eth_event_handler(void *data, int event, int qno) |
|
| 1729 |
++{
|
|
| 1730 |
++ struct pfe_eth_priv_s *priv = data; |
|
| 1731 |
++ |
|
| 1732 |
++ switch (event) {
|
|
| 1733 |
++ case EVENT_RX_PKT_IND: |
|
| 1734 |
++ |
|
| 1735 |
++ if (qno == 0) {
|
|
| 1736 |
++ if (napi_schedule_prep(&priv->high_napi)) {
|
|
| 1737 |
++ netif_info(priv, intr, priv->ndev, |
|
| 1738 |
++ "%s: schedule high prio poll\n" |
|
| 1739 |
++ , __func__); |
|
| 1740 |
++ |
|
| 1741 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 1742 |
++ priv->napi_counters[NAPI_SCHED_COUNT]++; |
|
| 1743 |
++#endif |
|
| 1744 |
++ |
|
| 1745 |
++ __napi_schedule(&priv->high_napi); |
|
| 1746 |
++ } |
|
| 1747 |
++ } else if (qno == 1) {
|
|
| 1748 |
++ if (napi_schedule_prep(&priv->low_napi)) {
|
|
| 1749 |
++ netif_info(priv, intr, priv->ndev, |
|
| 1750 |
++ "%s: schedule low prio poll\n" |
|
| 1751 |
++ , __func__); |
|
| 1752 |
++ |
|
| 1753 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 1754 |
++ priv->napi_counters[NAPI_SCHED_COUNT]++; |
|
| 1755 |
++#endif |
|
| 1756 |
++ __napi_schedule(&priv->low_napi); |
|
| 1757 |
++ } |
|
| 1758 |
++ } else if (qno == 2) {
|
|
| 1759 |
++ if (napi_schedule_prep(&priv->lro_napi)) {
|
|
| 1760 |
++ netif_info(priv, intr, priv->ndev, |
|
| 1761 |
++ "%s: schedule lro prio poll\n" |
|
| 1762 |
++ , __func__); |
|
| 1763 |
++ |
|
| 1764 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 1765 |
++ priv->napi_counters[NAPI_SCHED_COUNT]++; |
|
| 1766 |
++#endif |
|
| 1767 |
++ __napi_schedule(&priv->lro_napi); |
|
| 1768 |
++ } |
|
| 1769 |
++ } |
|
| 1770 |
++ |
|
| 1771 |
++ break; |
|
| 1772 |
++ |
|
| 1773 |
++ case EVENT_TXDONE_IND: |
|
| 1774 |
++ pfe_eth_flush_tx(priv); |
|
| 1775 |
++ hif_lib_event_handler_start(&priv->client, EVENT_TXDONE_IND, 0); |
|
| 1776 |
++ break; |
|
| 1777 |
++ case EVENT_HIGH_RX_WM: |
|
| 1778 |
++ default: |
|
| 1779 |
++ break; |
|
| 1780 |
++ } |
|
| 1781 |
++ |
|
| 1782 |
++ return 0; |
|
| 1783 |
++} |
|
| 1784 |
++ |
|
| 1785 |
++/* pfe_eth_open |
|
| 1786 |
++ */ |
|
| 1787 |
++static int pfe_eth_open(struct net_device *ndev) |
|
| 1788 |
++{
|
|
| 1789 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1790 |
++ struct hif_client_s *client; |
|
| 1791 |
++ int rc; |
|
| 1792 |
++ |
|
| 1793 |
++ netif_info(priv, ifup, ndev, "%s\n", __func__); |
|
| 1794 |
++ |
|
| 1795 |
++ /* Register client driver with HIF */ |
|
| 1796 |
++ client = &priv->client; |
|
| 1797 |
++ memset(client, 0, sizeof(*client)); |
|
| 1798 |
++ client->id = PFE_CL_GEM0 + priv->id; |
|
| 1799 |
++ client->tx_qn = emac_txq_cnt; |
|
| 1800 |
++ client->rx_qn = EMAC_RXQ_CNT; |
|
| 1801 |
++ client->priv = priv; |
|
| 1802 |
++ client->pfe = priv->pfe; |
|
| 1803 |
++ client->event_handler = pfe_eth_event_handler; |
|
| 1804 |
++ |
|
| 1805 |
++ client->tx_qsize = EMAC_TXQ_DEPTH; |
|
| 1806 |
++ client->rx_qsize = EMAC_RXQ_DEPTH; |
|
| 1807 |
++ |
|
| 1808 |
++ rc = hif_lib_client_register(client); |
|
| 1809 |
++ if (rc) {
|
|
| 1810 |
++ netdev_err(ndev, "%s: hif_lib_client_register(%d) failed\n", |
|
| 1811 |
++ __func__, client->id); |
|
| 1812 |
++ goto err0; |
|
| 1813 |
++ } |
|
| 1814 |
++ |
|
| 1815 |
++ netif_info(priv, drv, ndev, "%s: registered client: %p\n", __func__, |
|
| 1816 |
++ client); |
|
| 1817 |
++ |
|
| 1818 |
++ pfe_gemac_init(priv); |
|
| 1819 |
++ |
|
| 1820 |
++ if (!is_valid_ether_addr(ndev->dev_addr)) {
|
|
| 1821 |
++ netdev_err(ndev, "%s: invalid MAC address\n", __func__); |
|
| 1822 |
++ rc = -EADDRNOTAVAIL; |
|
| 1823 |
++ goto err1; |
|
| 1824 |
++ } |
|
| 1825 |
++ |
|
| 1826 |
++ gemac_set_laddrN(priv->EMAC_baseaddr, |
|
| 1827 |
++ (struct pfe_mac_addr *)ndev->dev_addr, 1); |
|
| 1828 |
++ |
|
| 1829 |
++ napi_enable(&priv->high_napi); |
|
| 1830 |
++ napi_enable(&priv->low_napi); |
|
| 1831 |
++ napi_enable(&priv->lro_napi); |
|
| 1832 |
++ |
|
| 1833 |
++ rc = pfe_eth_start(priv); |
|
| 1834 |
++ |
|
| 1835 |
++ netif_tx_wake_all_queues(ndev); |
|
| 1836 |
++ |
|
| 1837 |
++ return rc; |
|
| 1838 |
++ |
|
| 1839 |
++err1: |
|
| 1840 |
++ hif_lib_client_unregister(&priv->client); |
|
| 1841 |
++ |
|
| 1842 |
++err0: |
|
| 1843 |
++ return rc; |
|
| 1844 |
++} |
|
| 1845 |
++ |
|
| 1846 |
++/* |
|
| 1847 |
++ * pfe_eth_shutdown |
|
| 1848 |
++ */ |
|
| 1849 |
++int pfe_eth_shutdown(struct net_device *ndev, int wake) |
|
| 1850 |
++{
|
|
| 1851 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1852 |
++ int i, qstatus; |
|
| 1853 |
++ unsigned long next_poll = jiffies + 1, end = jiffies + |
|
| 1854 |
++ (TX_POLL_TIMEOUT_MS * HZ) / 1000; |
|
| 1855 |
++ int tx_pkts, prv_tx_pkts; |
|
| 1856 |
++ |
|
| 1857 |
++ netif_info(priv, ifdown, ndev, "%s\n", __func__); |
|
| 1858 |
++ |
|
| 1859 |
++ for (i = 0; i < emac_txq_cnt; i++) |
|
| 1860 |
++ hrtimer_cancel(&priv->fast_tx_timeout[i].timer); |
|
| 1861 |
++ |
|
| 1862 |
++ netif_tx_stop_all_queues(ndev); |
|
| 1863 |
++ |
|
| 1864 |
++ do {
|
|
| 1865 |
++ tx_pkts = 0; |
|
| 1866 |
++ pfe_eth_flush_tx(priv); |
|
| 1867 |
++ |
|
| 1868 |
++ for (i = 0; i < emac_txq_cnt; i++) |
|
| 1869 |
++ tx_pkts += hif_lib_tx_pending(&priv->client, i); |
|
| 1870 |
++ |
|
| 1871 |
++ if (tx_pkts) {
|
|
| 1872 |
++ /*Don't wait forever, break if we cross max timeout */ |
|
| 1873 |
++ if (time_after(jiffies, end)) {
|
|
| 1874 |
++ pr_err( |
|
| 1875 |
++ "(%s)Tx is not complete after %dmsec\n", |
|
| 1876 |
++ ndev->name, TX_POLL_TIMEOUT_MS); |
|
| 1877 |
++ break; |
|
| 1878 |
++ } |
|
| 1879 |
++ |
|
| 1880 |
++ pr_info("%s : (%s) Waiting for tx packets to free. Pending tx pkts = %d.\n"
|
|
| 1881 |
++ , __func__, ndev->name, tx_pkts); |
|
| 1882 |
++ if (need_resched()) |
|
| 1883 |
++ schedule(); |
|
| 1884 |
++ } |
|
| 1885 |
++ |
|
| 1886 |
++ } while (tx_pkts); |
|
| 1887 |
++ |
|
| 1888 |
++ end = jiffies + (TX_POLL_TIMEOUT_MS * HZ) / 1000; |
|
| 1889 |
++ |
|
| 1890 |
++ prv_tx_pkts = tmu_pkts_processed(priv->id); |
|
| 1891 |
++ /* |
|
| 1892 |
++ * Wait till TMU transmits all pending packets |
|
| 1893 |
++ * poll tmu_qstatus and pkts processed by TMU for every 10ms |
|
| 1894 |
++ * Consider TMU is busy, If we see TMU qeueu pending or any packets |
|
| 1895 |
++ * processed by TMU |
|
| 1896 |
++ */ |
|
| 1897 |
++ while (1) {
|
|
| 1898 |
++ if (time_after(jiffies, next_poll)) {
|
|
| 1899 |
++ tx_pkts = tmu_pkts_processed(priv->id); |
|
| 1900 |
++ qstatus = tmu_qstatus(priv->id) & 0x7ffff; |
|
| 1901 |
++ |
|
| 1902 |
++ if (!qstatus && (tx_pkts == prv_tx_pkts)) |
|
| 1903 |
++ break; |
|
| 1904 |
++ /* Don't wait forever, break if we cross max |
|
| 1905 |
++ * timeout(TX_POLL_TIMEOUT_MS) |
|
| 1906 |
++ */ |
|
| 1907 |
++ if (time_after(jiffies, end)) {
|
|
| 1908 |
++ pr_err("TMU%d is busy after %dmsec\n",
|
|
| 1909 |
++ priv->id, TX_POLL_TIMEOUT_MS); |
|
| 1910 |
++ break; |
|
| 1911 |
++ } |
|
| 1912 |
++ prv_tx_pkts = tx_pkts; |
|
| 1913 |
++ next_poll++; |
|
| 1914 |
++ } |
|
| 1915 |
++ if (need_resched()) |
|
| 1916 |
++ schedule(); |
|
| 1917 |
++ } |
|
| 1918 |
++ /* Wait for some more time to complete transmitting packet if any */ |
|
| 1919 |
++ next_poll = jiffies + 1; |
|
| 1920 |
++ while (1) {
|
|
| 1921 |
++ if (time_after(jiffies, next_poll)) |
|
| 1922 |
++ break; |
|
| 1923 |
++ if (need_resched()) |
|
| 1924 |
++ schedule(); |
|
| 1925 |
++ } |
|
| 1926 |
++ |
|
| 1927 |
++ pfe_eth_stop(ndev, wake); |
|
| 1928 |
++ |
|
| 1929 |
++ napi_disable(&priv->lro_napi); |
|
| 1930 |
++ napi_disable(&priv->low_napi); |
|
| 1931 |
++ napi_disable(&priv->high_napi); |
|
| 1932 |
++ |
|
| 1933 |
++ hif_lib_client_unregister(&priv->client); |
|
| 1934 |
++ |
|
| 1935 |
++ return 0; |
|
| 1936 |
++} |
|
| 1937 |
++ |
|
| 1938 |
++/* pfe_eth_close |
|
| 1939 |
++ * |
|
| 1940 |
++ */ |
|
| 1941 |
++static int pfe_eth_close(struct net_device *ndev) |
|
| 1942 |
++{
|
|
| 1943 |
++ pfe_eth_shutdown(ndev, 0); |
|
| 1944 |
++ |
|
| 1945 |
++ return 0; |
|
| 1946 |
++} |
|
| 1947 |
++ |
|
| 1948 |
++/* pfe_eth_suspend |
|
| 1949 |
++ * |
|
| 1950 |
++ * return value : 1 if netdevice is configured to wakeup system |
|
| 1951 |
++ * 0 otherwise |
|
| 1952 |
++ */ |
|
| 1953 |
++int pfe_eth_suspend(struct net_device *ndev) |
|
| 1954 |
++{
|
|
| 1955 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1956 |
++ int retval = 0; |
|
| 1957 |
++ |
|
| 1958 |
++ if (priv->wol) {
|
|
| 1959 |
++ gemac_set_wol(priv->EMAC_baseaddr, priv->wol); |
|
| 1960 |
++ retval = 1; |
|
| 1961 |
++ } |
|
| 1962 |
++ pfe_eth_shutdown(ndev, priv->wol); |
|
| 1963 |
++ |
|
| 1964 |
++ return retval; |
|
| 1965 |
++} |
|
| 1966 |
++ |
|
| 1967 |
++/* pfe_eth_resume |
|
| 1968 |
++ * |
|
| 1969 |
++ */ |
|
| 1970 |
++int pfe_eth_resume(struct net_device *ndev) |
|
| 1971 |
++{
|
|
| 1972 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 1973 |
++ |
|
| 1974 |
++ if (priv->wol) |
|
| 1975 |
++ gemac_set_wol(priv->EMAC_baseaddr, 0); |
|
| 1976 |
++ gemac_tx_enable(priv->EMAC_baseaddr); |
|
| 1977 |
++ |
|
| 1978 |
++ return pfe_eth_open(ndev); |
|
| 1979 |
++} |
|
| 1980 |
++ |
|
| 1981 |
++/* pfe_eth_get_queuenum |
|
| 1982 |
++ */ |
|
| 1983 |
++static int pfe_eth_get_queuenum(struct pfe_eth_priv_s *priv, struct sk_buff |
|
| 1984 |
++ *skb) |
|
| 1985 |
++{
|
|
| 1986 |
++ int queuenum = 0; |
|
| 1987 |
++ unsigned long flags; |
|
| 1988 |
++ |
|
| 1989 |
++ /* Get the Fast Path queue number */ |
|
| 1990 |
++ /* |
|
| 1991 |
++ * Use conntrack mark (if conntrack exists), then packet mark (if any), |
|
| 1992 |
++ * then fallback to default |
|
| 1993 |
++ */ |
|
| 1994 |
++#if defined(CONFIG_IP_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_MARK) |
|
| 1995 |
++ if (skb->_nfct) {
|
|
| 1996 |
++ enum ip_conntrack_info cinfo; |
|
| 1997 |
++ struct nf_conn *ct; |
|
| 1998 |
++ |
|
| 1999 |
++ ct = nf_ct_get(skb, &cinfo); |
|
| 2000 |
++ |
|
| 2001 |
++ if (ct) {
|
|
| 2002 |
++ u32 connmark; |
|
| 2003 |
++ |
|
| 2004 |
++ connmark = ct->mark; |
|
| 2005 |
++ |
|
| 2006 |
++ if ((connmark & 0x80000000) && priv->id != 0) |
|
| 2007 |
++ connmark >>= 16; |
|
| 2008 |
++ |
|
| 2009 |
++ queuenum = connmark & EMAC_QUEUENUM_MASK; |
|
| 2010 |
++ } |
|
| 2011 |
++ } else {/* continued after #endif ... */
|
|
| 2012 |
++#endif |
|
| 2013 |
++ if (skb->mark) {
|
|
| 2014 |
++ queuenum = skb->mark & EMAC_QUEUENUM_MASK; |
|
| 2015 |
++ } else {
|
|
| 2016 |
++ spin_lock_irqsave(&priv->lock, flags); |
|
| 2017 |
++ queuenum = priv->default_priority & EMAC_QUEUENUM_MASK; |
|
| 2018 |
++ spin_unlock_irqrestore(&priv->lock, flags); |
|
| 2019 |
++ } |
|
| 2020 |
++#if defined(CONFIG_IP_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_MARK) |
|
| 2021 |
++ } |
|
| 2022 |
++#endif |
|
| 2023 |
++ return queuenum; |
|
| 2024 |
++} |
|
| 2025 |
++ |
|
| 2026 |
++/* pfe_eth_might_stop_tx |
|
| 2027 |
++ * |
|
| 2028 |
++ */ |
|
| 2029 |
++static int pfe_eth_might_stop_tx(struct pfe_eth_priv_s *priv, int queuenum, |
|
| 2030 |
++ struct netdev_queue *tx_queue, |
|
| 2031 |
++ unsigned int n_desc, |
|
| 2032 |
++ unsigned int n_segs) |
|
| 2033 |
++{
|
|
| 2034 |
++ ktime_t kt; |
|
| 2035 |
++ |
|
| 2036 |
++ if (unlikely((__hif_tx_avail(&pfe->hif) < n_desc) || |
|
| 2037 |
++ (hif_lib_tx_avail(&priv->client, queuenum) < n_desc) || |
|
| 2038 |
++ (hif_lib_tx_credit_avail(pfe, priv->id, queuenum) < n_segs))) {
|
|
| 2039 |
++#ifdef PFE_ETH_TX_STATS |
|
| 2040 |
++ if (__hif_tx_avail(&pfe->hif) < n_desc) {
|
|
| 2041 |
++ priv->stop_queue_hif[queuenum]++; |
|
| 2042 |
++ } else if (hif_lib_tx_avail(&priv->client, queuenum) < n_desc) {
|
|
| 2043 |
++ priv->stop_queue_hif_client[queuenum]++; |
|
| 2044 |
++ } else if (hif_lib_tx_credit_avail(pfe, priv->id, queuenum) < |
|
| 2045 |
++ n_segs) {
|
|
| 2046 |
++ priv->stop_queue_credit[queuenum]++; |
|
| 2047 |
++ } |
|
| 2048 |
++ priv->stop_queue_total[queuenum]++; |
|
| 2049 |
++#endif |
|
| 2050 |
++ netif_tx_stop_queue(tx_queue); |
|
| 2051 |
++ |
|
| 2052 |
++ kt = ktime_set(0, LS1012A_TX_FAST_RECOVERY_TIMEOUT_MS * |
|
| 2053 |
++ NSEC_PER_MSEC); |
|
| 2054 |
++ hrtimer_start(&priv->fast_tx_timeout[queuenum].timer, kt, |
|
| 2055 |
++ HRTIMER_MODE_REL); |
|
| 2056 |
++ return -1; |
|
| 2057 |
++ } else {
|
|
| 2058 |
++ return 0; |
|
| 2059 |
++ } |
|
| 2060 |
++} |
|
| 2061 |
++ |
|
| 2062 |
++#define SA_MAX_OP 2 |
|
| 2063 |
++/* pfe_hif_send_packet |
|
| 2064 |
++ * |
|
| 2065 |
++ * At this level if TX fails we drop the packet |
|
| 2066 |
++ */ |
|
| 2067 |
++static void pfe_hif_send_packet(struct sk_buff *skb, struct pfe_eth_priv_s |
|
| 2068 |
++ *priv, int queuenum) |
|
| 2069 |
++{
|
|
| 2070 |
++ struct skb_shared_info *sh = skb_shinfo(skb); |
|
| 2071 |
++ unsigned int nr_frags; |
|
| 2072 |
++ u32 ctrl = 0; |
|
| 2073 |
++ |
|
| 2074 |
++ netif_info(priv, tx_queued, priv->ndev, "%s\n", __func__); |
|
| 2075 |
++ |
|
| 2076 |
++ if (skb_is_gso(skb)) {
|
|
| 2077 |
++ priv->stats.tx_dropped++; |
|
| 2078 |
++ return; |
|
| 2079 |
++ } |
|
| 2080 |
++ |
|
| 2081 |
++ if (skb->ip_summed == CHECKSUM_PARTIAL) |
|
| 2082 |
++ ctrl = HIF_CTRL_TX_CHECKSUM; |
|
| 2083 |
++ |
|
| 2084 |
++ nr_frags = sh->nr_frags; |
|
| 2085 |
++ |
|
| 2086 |
++ if (nr_frags) {
|
|
| 2087 |
++ skb_frag_t *f; |
|
| 2088 |
++ int i; |
|
| 2089 |
++ |
|
| 2090 |
++ __hif_lib_xmit_pkt(&priv->client, queuenum, skb->data, |
|
| 2091 |
++ skb_headlen(skb), ctrl, HIF_FIRST_BUFFER, |
|
| 2092 |
++ skb); |
|
| 2093 |
++ |
|
| 2094 |
++ for (i = 0; i < nr_frags - 1; i++) {
|
|
| 2095 |
++ f = &sh->frags[i]; |
|
| 2096 |
++ __hif_lib_xmit_pkt(&priv->client, queuenum, |
|
| 2097 |
++ skb_frag_address(f), |
|
| 2098 |
++ skb_frag_size(f), |
|
| 2099 |
++ 0x0, 0x0, skb); |
|
| 2100 |
++ } |
|
| 2101 |
++ |
|
| 2102 |
++ f = &sh->frags[i]; |
|
| 2103 |
++ |
|
| 2104 |
++ __hif_lib_xmit_pkt(&priv->client, queuenum, |
|
| 2105 |
++ skb_frag_address(f), skb_frag_size(f), |
|
| 2106 |
++ 0x0, HIF_LAST_BUFFER | HIF_DATA_VALID, |
|
| 2107 |
++ skb); |
|
| 2108 |
++ |
|
| 2109 |
++ netif_info(priv, tx_queued, priv->ndev, |
|
| 2110 |
++ "%s: pkt sent successfully skb:%p nr_frags:%d len:%d\n", |
|
| 2111 |
++ __func__, skb, nr_frags, skb->len); |
|
| 2112 |
++ } else {
|
|
| 2113 |
++ __hif_lib_xmit_pkt(&priv->client, queuenum, skb->data, |
|
| 2114 |
++ skb->len, ctrl, HIF_FIRST_BUFFER | |
|
| 2115 |
++ HIF_LAST_BUFFER | HIF_DATA_VALID, |
|
| 2116 |
++ skb); |
|
| 2117 |
++ netif_info(priv, tx_queued, priv->ndev, |
|
| 2118 |
++ "%s: pkt sent successfully skb:%p len:%d\n", |
|
| 2119 |
++ __func__, skb, skb->len); |
|
| 2120 |
++ } |
|
| 2121 |
++ hif_tx_dma_start(); |
|
| 2122 |
++ priv->stats.tx_packets++; |
|
| 2123 |
++ priv->stats.tx_bytes += skb->len; |
|
| 2124 |
++ hif_lib_tx_credit_use(pfe, priv->id, queuenum, 1); |
|
| 2125 |
++} |
|
| 2126 |
++ |
|
| 2127 |
++/* pfe_eth_flush_txQ |
|
| 2128 |
++ */ |
|
| 2129 |
++static void pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int |
|
| 2130 |
++ from_tx, int n_desc) |
|
| 2131 |
++{
|
|
| 2132 |
++ struct sk_buff *skb; |
|
| 2133 |
++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, |
|
| 2134 |
++ tx_q_num); |
|
| 2135 |
++ unsigned int flags; |
|
| 2136 |
++ |
|
| 2137 |
++ netif_info(priv, tx_done, priv->ndev, "%s\n", __func__); |
|
| 2138 |
++ |
|
| 2139 |
++ if (!from_tx) |
|
| 2140 |
++ __netif_tx_lock_bh(tx_queue); |
|
| 2141 |
++ |
|
| 2142 |
++ /* Clean HIF and client queue */ |
|
| 2143 |
++ while ((skb = hif_lib_tx_get_next_complete(&priv->client, |
|
| 2144 |
++ tx_q_num, &flags, |
|
| 2145 |
++ HIF_TX_DESC_NT))) {
|
|
| 2146 |
++ if (flags & HIF_DATA_VALID) |
|
| 2147 |
++ dev_kfree_skb_any(skb); |
|
| 2148 |
++ } |
|
| 2149 |
++ if (!from_tx) |
|
| 2150 |
++ __netif_tx_unlock_bh(tx_queue); |
|
| 2151 |
++} |
|
| 2152 |
++ |
|
| 2153 |
++/* pfe_eth_flush_tx |
|
| 2154 |
++ */ |
|
| 2155 |
++static void pfe_eth_flush_tx(struct pfe_eth_priv_s *priv) |
|
| 2156 |
++{
|
|
| 2157 |
++ int ii; |
|
| 2158 |
++ |
|
| 2159 |
++ netif_info(priv, tx_done, priv->ndev, "%s\n", __func__); |
|
| 2160 |
++ |
|
| 2161 |
++ for (ii = 0; ii < emac_txq_cnt; ii++) |
|
| 2162 |
++ pfe_eth_flush_txQ(priv, ii, 0, 0); |
|
| 2163 |
++} |
|
| 2164 |
++ |
|
| 2165 |
++void pfe_tx_get_req_desc(struct sk_buff *skb, unsigned int *n_desc, unsigned int |
|
| 2166 |
++ *n_segs) |
|
| 2167 |
++{
|
|
| 2168 |
++ struct skb_shared_info *sh = skb_shinfo(skb); |
|
| 2169 |
++ |
|
| 2170 |
++ /* Scattered data */ |
|
| 2171 |
++ if (sh->nr_frags) {
|
|
| 2172 |
++ *n_desc = sh->nr_frags + 1; |
|
| 2173 |
++ *n_segs = 1; |
|
| 2174 |
++ /* Regular case */ |
|
| 2175 |
++ } else {
|
|
| 2176 |
++ *n_desc = 1; |
|
| 2177 |
++ *n_segs = 1; |
|
| 2178 |
++ } |
|
| 2179 |
++} |
|
| 2180 |
++ |
|
| 2181 |
++/* pfe_eth_send_packet |
|
| 2182 |
++ */ |
|
| 2183 |
++static int pfe_eth_send_packet(struct sk_buff *skb, struct net_device *ndev) |
|
| 2184 |
++{
|
|
| 2185 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 2186 |
++ int tx_q_num = skb_get_queue_mapping(skb); |
|
| 2187 |
++ int n_desc, n_segs; |
|
| 2188 |
++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, |
|
| 2189 |
++ tx_q_num); |
|
| 2190 |
++ |
|
| 2191 |
++ netif_info(priv, tx_queued, ndev, "%s\n", __func__); |
|
| 2192 |
++ |
|
| 2193 |
++ if ((!skb_is_gso(skb)) && (skb_headroom(skb) < (PFE_PKT_HEADER_SZ + |
|
| 2194 |
++ sizeof(unsigned long)))) {
|
|
| 2195 |
++ netif_warn(priv, tx_err, priv->ndev, "%s: copying skb\n", |
|
| 2196 |
++ __func__); |
|
| 2197 |
++ |
|
| 2198 |
++ if (pskb_expand_head(skb, (PFE_PKT_HEADER_SZ + sizeof(unsigned |
|
| 2199 |
++ long)), 0, GFP_ATOMIC)) {
|
|
| 2200 |
++ /* No need to re-transmit, no way to recover*/ |
|
| 2201 |
++ kfree_skb(skb); |
|
| 2202 |
++ priv->stats.tx_dropped++; |
|
| 2203 |
++ return NETDEV_TX_OK; |
|
| 2204 |
++ } |
|
| 2205 |
++ } |
|
| 2206 |
++ |
|
| 2207 |
++ pfe_tx_get_req_desc(skb, &n_desc, &n_segs); |
|
| 2208 |
++ |
|
| 2209 |
++ hif_tx_lock(&pfe->hif); |
|
| 2210 |
++ if (unlikely(pfe_eth_might_stop_tx(priv, tx_q_num, tx_queue, n_desc, |
|
| 2211 |
++ n_segs))) {
|
|
| 2212 |
++#ifdef PFE_ETH_TX_STATS |
|
| 2213 |
++ if (priv->was_stopped[tx_q_num]) {
|
|
| 2214 |
++ priv->clean_fail[tx_q_num]++; |
|
| 2215 |
++ priv->was_stopped[tx_q_num] = 0; |
|
| 2216 |
++ } |
|
| 2217 |
++#endif |
|
| 2218 |
++ hif_tx_unlock(&pfe->hif); |
|
| 2219 |
++ return NETDEV_TX_BUSY; |
|
| 2220 |
++ } |
|
| 2221 |
++ |
|
| 2222 |
++ pfe_hif_send_packet(skb, priv, tx_q_num); |
|
| 2223 |
++ |
|
| 2224 |
++ hif_tx_unlock(&pfe->hif); |
|
| 2225 |
++ |
|
| 2226 |
++ tx_queue->trans_start = jiffies; |
|
| 2227 |
++ |
|
| 2228 |
++#ifdef PFE_ETH_TX_STATS |
|
| 2229 |
++ priv->was_stopped[tx_q_num] = 0; |
|
| 2230 |
++#endif |
|
| 2231 |
++ |
|
| 2232 |
++ return NETDEV_TX_OK; |
|
| 2233 |
++} |
|
| 2234 |
++ |
|
| 2235 |
++/* pfe_eth_select_queue |
|
| 2236 |
++ * |
|
| 2237 |
++ */ |
|
| 2238 |
++static u16 pfe_eth_select_queue(struct net_device *ndev, struct sk_buff *skb, |
|
| 2239 |
++ void *accel_priv, |
|
| 2240 |
++ select_queue_fallback_t fallback) |
|
| 2241 |
++{
|
|
| 2242 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 2243 |
++ |
|
| 2244 |
++ return pfe_eth_get_queuenum(priv, skb); |
|
| 2245 |
++} |
|
| 2246 |
++ |
|
| 2247 |
++/* pfe_eth_get_stats |
|
| 2248 |
++ */ |
|
| 2249 |
++static struct net_device_stats *pfe_eth_get_stats(struct net_device *ndev) |
|
| 2250 |
++{
|
|
| 2251 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 2252 |
++ |
|
| 2253 |
++ netif_info(priv, drv, ndev, "%s\n", __func__); |
|
| 2254 |
++ |
|
| 2255 |
++ return &priv->stats; |
|
| 2256 |
++} |
|
| 2257 |
++ |
|
| 2258 |
++/* pfe_eth_set_mac_address |
|
| 2259 |
++ */ |
|
| 2260 |
++static int pfe_eth_set_mac_address(struct net_device *ndev, void *addr) |
|
| 2261 |
++{
|
|
| 2262 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 2263 |
++ struct sockaddr *sa = addr; |
|
| 2264 |
++ |
|
| 2265 |
++ netif_info(priv, drv, ndev, "%s\n", __func__); |
|
| 2266 |
++ |
|
| 2267 |
++ if (!is_valid_ether_addr(sa->sa_data)) |
|
| 2268 |
++ return -EADDRNOTAVAIL; |
|
| 2269 |
++ |
|
| 2270 |
++ memcpy(ndev->dev_addr, sa->sa_data, ETH_ALEN); |
|
| 2271 |
++ |
|
| 2272 |
++ gemac_set_laddrN(priv->EMAC_baseaddr, |
|
| 2273 |
++ (struct pfe_mac_addr *)ndev->dev_addr, 1); |
|
| 2274 |
++ |
|
| 2275 |
++ return 0; |
|
| 2276 |
++} |
|
| 2277 |
++ |
|
| 2278 |
++/* pfe_eth_enet_addr_byte_mac |
|
| 2279 |
++ */ |
|
| 2280 |
++int pfe_eth_enet_addr_byte_mac(u8 *enet_byte_addr, |
|
| 2281 |
++ struct pfe_mac_addr *enet_addr) |
|
| 2282 |
++{
|
|
| 2283 |
++ if (!enet_byte_addr || !enet_addr) {
|
|
| 2284 |
++ return -1; |
|
| 2285 |
++ |
|
| 2286 |
++ } else {
|
|
| 2287 |
++ enet_addr->bottom = enet_byte_addr[0] | |
|
| 2288 |
++ (enet_byte_addr[1] << 8) | |
|
| 2289 |
++ (enet_byte_addr[2] << 16) | |
|
| 2290 |
++ (enet_byte_addr[3] << 24); |
|
| 2291 |
++ enet_addr->top = enet_byte_addr[4] | |
|
| 2292 |
++ (enet_byte_addr[5] << 8); |
|
| 2293 |
++ return 0; |
|
| 2294 |
++ } |
|
| 2295 |
++} |
|
| 2296 |
++ |
|
| 2297 |
++/* pfe_eth_set_multi |
|
| 2298 |
++ */ |
|
| 2299 |
++static void pfe_eth_set_multi(struct net_device *ndev) |
|
| 2300 |
++{
|
|
| 2301 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 2302 |
++ struct pfe_mac_addr hash_addr; /* hash register structure */ |
|
| 2303 |
++ /* specific mac address register structure */ |
|
| 2304 |
++ struct pfe_mac_addr spec_addr; |
|
| 2305 |
++ int result; /* index into hash register to set.. */ |
|
| 2306 |
++ int uc_count = 0; |
|
| 2307 |
++ struct netdev_hw_addr *ha; |
|
| 2308 |
++ |
|
| 2309 |
++ if (ndev->flags & IFF_PROMISC) {
|
|
| 2310 |
++ netif_info(priv, drv, ndev, "entering promiscuous mode\n"); |
|
| 2311 |
++ |
|
| 2312 |
++ priv->promisc = 1; |
|
| 2313 |
++ gemac_enable_copy_all(priv->EMAC_baseaddr); |
|
| 2314 |
++ } else {
|
|
| 2315 |
++ priv->promisc = 0; |
|
| 2316 |
++ gemac_disable_copy_all(priv->EMAC_baseaddr); |
|
| 2317 |
++ } |
|
| 2318 |
++ |
|
| 2319 |
++ /* Enable broadcast frame reception if required. */ |
|
| 2320 |
++ if (ndev->flags & IFF_BROADCAST) {
|
|
| 2321 |
++ gemac_allow_broadcast(priv->EMAC_baseaddr); |
|
| 2322 |
++ } else {
|
|
| 2323 |
++ netif_info(priv, drv, ndev, |
|
| 2324 |
++ "disabling broadcast frame reception\n"); |
|
| 2325 |
++ |
|
| 2326 |
++ gemac_no_broadcast(priv->EMAC_baseaddr); |
|
| 2327 |
++ } |
|
| 2328 |
++ |
|
| 2329 |
++ if (ndev->flags & IFF_ALLMULTI) {
|
|
| 2330 |
++ /* Set the hash to rx all multicast frames */ |
|
| 2331 |
++ hash_addr.bottom = 0xFFFFFFFF; |
|
| 2332 |
++ hash_addr.top = 0xFFFFFFFF; |
|
| 2333 |
++ gemac_set_hash(priv->EMAC_baseaddr, &hash_addr); |
|
| 2334 |
++ netdev_for_each_uc_addr(ha, ndev) {
|
|
| 2335 |
++ if (uc_count >= MAX_UC_SPEC_ADDR_REG) |
|
| 2336 |
++ break; |
|
| 2337 |
++ pfe_eth_enet_addr_byte_mac(ha->addr, &spec_addr); |
|
| 2338 |
++ gemac_set_laddrN(priv->EMAC_baseaddr, &spec_addr, |
|
| 2339 |
++ uc_count + 2); |
|
| 2340 |
++ uc_count++; |
|
| 2341 |
++ } |
|
| 2342 |
++ } else if ((netdev_mc_count(ndev) > 0) || (netdev_uc_count(ndev))) {
|
|
| 2343 |
++ u8 *addr; |
|
| 2344 |
++ |
|
| 2345 |
++ hash_addr.bottom = 0; |
|
| 2346 |
++ hash_addr.top = 0; |
|
| 2347 |
++ |
|
| 2348 |
++ netdev_for_each_mc_addr(ha, ndev) {
|
|
| 2349 |
++ addr = ha->addr; |
|
| 2350 |
++ |
|
| 2351 |
++ netif_info(priv, drv, ndev, |
|
| 2352 |
++ "adding multicast address %X:%X:%X:%X:%X:%X to gem filter\n", |
|
| 2353 |
++ addr[0], addr[1], addr[2], |
|
| 2354 |
++ addr[3], addr[4], addr[5]); |
|
| 2355 |
++ |
|
| 2356 |
++ result = pfe_eth_get_hash(addr); |
|
| 2357 |
++ |
|
| 2358 |
++ if (result < EMAC_HASH_REG_BITS) {
|
|
| 2359 |
++ if (result < 32) |
|
| 2360 |
++ hash_addr.bottom |= (1 << result); |
|
| 2361 |
++ else |
|
| 2362 |
++ hash_addr.top |= (1 << (result - 32)); |
|
| 2363 |
++ } else {
|
|
| 2364 |
++ break; |
|
| 2365 |
++ } |
|
| 2366 |
++ } |
|
| 2367 |
++ |
|
| 2368 |
++ uc_count = -1; |
|
| 2369 |
++ netdev_for_each_uc_addr(ha, ndev) {
|
|
| 2370 |
++ addr = ha->addr; |
|
| 2371 |
++ |
|
| 2372 |
++ if (++uc_count < MAX_UC_SPEC_ADDR_REG) {
|
|
| 2373 |
++ netdev_info(ndev, |
|
| 2374 |
++ "adding unicast address %02x:%02x:%02x:%02x:%02x:%02x to gem filter\n", |
|
| 2375 |
++ addr[0], addr[1], addr[2], |
|
| 2376 |
++ addr[3], addr[4], addr[5]); |
|
| 2377 |
++ pfe_eth_enet_addr_byte_mac(addr, &spec_addr); |
|
| 2378 |
++ gemac_set_laddrN(priv->EMAC_baseaddr, |
|
| 2379 |
++ &spec_addr, uc_count + 2); |
|
| 2380 |
++ } else {
|
|
| 2381 |
++ netif_info(priv, drv, ndev, |
|
| 2382 |
++ "adding unicast address %02x:%02x:%02x:%02x:%02x:%02x to gem hash\n", |
|
| 2383 |
++ addr[0], addr[1], addr[2], |
|
| 2384 |
++ addr[3], addr[4], addr[5]); |
|
| 2385 |
++ |
|
| 2386 |
++ result = pfe_eth_get_hash(addr); |
|
| 2387 |
++ if (result >= EMAC_HASH_REG_BITS) {
|
|
| 2388 |
++ break; |
|
| 2389 |
++ |
|
| 2390 |
++ } else {
|
|
| 2391 |
++ if (result < 32) |
|
| 2392 |
++ hash_addr.bottom |= (1 << |
|
| 2393 |
++ result); |
|
| 2394 |
++ else |
|
| 2395 |
++ hash_addr.top |= (1 << |
|
| 2396 |
++ (result - 32)); |
|
| 2397 |
++ } |
|
| 2398 |
++ } |
|
| 2399 |
++ } |
|
| 2400 |
++ |
|
| 2401 |
++ gemac_set_hash(priv->EMAC_baseaddr, &hash_addr); |
|
| 2402 |
++ } |
|
| 2403 |
++ |
|
| 2404 |
++ if (!(netdev_uc_count(ndev) >= MAX_UC_SPEC_ADDR_REG)) {
|
|
| 2405 |
++ /* |
|
| 2406 |
++ * Check if there are any specific address HW registers that |
|
| 2407 |
++ * need to be flushed |
|
| 2408 |
++ */ |
|
| 2409 |
++ for (uc_count = netdev_uc_count(ndev); uc_count < |
|
| 2410 |
++ MAX_UC_SPEC_ADDR_REG; uc_count++) |
|
| 2411 |
++ gemac_clear_laddrN(priv->EMAC_baseaddr, uc_count + 2); |
|
| 2412 |
++ } |
|
| 2413 |
++ |
|
| 2414 |
++ if (ndev->flags & IFF_LOOPBACK) |
|
| 2415 |
++ gemac_set_loop(priv->EMAC_baseaddr, LB_LOCAL); |
|
| 2416 |
++} |
|
| 2417 |
++ |
|
| 2418 |
++/* pfe_eth_set_features |
|
| 2419 |
++ */ |
|
| 2420 |
++static int pfe_eth_set_features(struct net_device *ndev, netdev_features_t |
|
| 2421 |
++ features) |
|
| 2422 |
++{
|
|
| 2423 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 2424 |
++ int rc = 0; |
|
| 2425 |
++ |
|
| 2426 |
++ if (features & NETIF_F_RXCSUM) |
|
| 2427 |
++ gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr); |
|
| 2428 |
++ else |
|
| 2429 |
++ gemac_disable_rx_checksum_offload(priv->EMAC_baseaddr); |
|
| 2430 |
++ return rc; |
|
| 2431 |
++} |
|
| 2432 |
++ |
|
| 2433 |
++/* pfe_eth_fast_tx_timeout |
|
| 2434 |
++ */ |
|
| 2435 |
++static enum hrtimer_restart pfe_eth_fast_tx_timeout(struct hrtimer *timer) |
|
| 2436 |
++{
|
|
| 2437 |
++ struct pfe_eth_fast_timer *fast_tx_timeout = container_of(timer, struct |
|
| 2438 |
++ pfe_eth_fast_timer, |
|
| 2439 |
++ timer); |
|
| 2440 |
++ struct pfe_eth_priv_s *priv = container_of(fast_tx_timeout->base, |
|
| 2441 |
++ struct pfe_eth_priv_s, |
|
| 2442 |
++ fast_tx_timeout); |
|
| 2443 |
++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, |
|
| 2444 |
++ fast_tx_timeout->queuenum); |
|
| 2445 |
++ |
|
| 2446 |
++ if (netif_tx_queue_stopped(tx_queue)) {
|
|
| 2447 |
++#ifdef PFE_ETH_TX_STATS |
|
| 2448 |
++ priv->was_stopped[fast_tx_timeout->queuenum] = 1; |
|
| 2449 |
++#endif |
|
| 2450 |
++ netif_tx_wake_queue(tx_queue); |
|
| 2451 |
++ } |
|
| 2452 |
++ |
|
| 2453 |
++ return HRTIMER_NORESTART; |
|
| 2454 |
++} |
|
| 2455 |
++ |
|
| 2456 |
++/* pfe_eth_fast_tx_timeout_init |
|
| 2457 |
++ */ |
|
| 2458 |
++static void pfe_eth_fast_tx_timeout_init(struct pfe_eth_priv_s *priv) |
|
| 2459 |
++{
|
|
| 2460 |
++ int i; |
|
| 2461 |
++ |
|
| 2462 |
++ for (i = 0; i < emac_txq_cnt; i++) {
|
|
| 2463 |
++ priv->fast_tx_timeout[i].queuenum = i; |
|
| 2464 |
++ hrtimer_init(&priv->fast_tx_timeout[i].timer, CLOCK_MONOTONIC, |
|
| 2465 |
++ HRTIMER_MODE_REL); |
|
| 2466 |
++ priv->fast_tx_timeout[i].timer.function = |
|
| 2467 |
++ pfe_eth_fast_tx_timeout; |
|
| 2468 |
++ priv->fast_tx_timeout[i].base = priv->fast_tx_timeout; |
|
| 2469 |
++ } |
|
| 2470 |
++} |
|
| 2471 |
++ |
|
| 2472 |
++static struct sk_buff *pfe_eth_rx_skb(struct net_device *ndev, |
|
| 2473 |
++ struct pfe_eth_priv_s *priv, |
|
| 2474 |
++ unsigned int qno) |
|
| 2475 |
++{
|
|
| 2476 |
++ void *buf_addr; |
|
| 2477 |
++ unsigned int rx_ctrl; |
|
| 2478 |
++ unsigned int desc_ctrl = 0; |
|
| 2479 |
++ struct hif_ipsec_hdr *ipsec_hdr = NULL; |
|
| 2480 |
++ struct sk_buff *skb; |
|
| 2481 |
++ struct sk_buff *skb_frag, *skb_frag_last = NULL; |
|
| 2482 |
++ int length = 0, offset; |
|
| 2483 |
++ |
|
| 2484 |
++ skb = priv->skb_inflight[qno]; |
|
| 2485 |
++ |
|
| 2486 |
++ if (skb) {
|
|
| 2487 |
++ skb_frag_last = skb_shinfo(skb)->frag_list; |
|
| 2488 |
++ if (skb_frag_last) {
|
|
| 2489 |
++ while (skb_frag_last->next) |
|
| 2490 |
++ skb_frag_last = skb_frag_last->next; |
|
| 2491 |
++ } |
|
| 2492 |
++ } |
|
| 2493 |
++ |
|
| 2494 |
++ while (!(desc_ctrl & CL_DESC_LAST)) {
|
|
| 2495 |
++ buf_addr = hif_lib_receive_pkt(&priv->client, qno, &length, |
|
| 2496 |
++ &offset, &rx_ctrl, &desc_ctrl, |
|
| 2497 |
++ (void **)&ipsec_hdr); |
|
| 2498 |
++ if (!buf_addr) |
|
| 2499 |
++ goto incomplete; |
|
| 2500 |
++ |
|
| 2501 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 2502 |
++ priv->napi_counters[NAPI_DESC_COUNT]++; |
|
| 2503 |
++#endif |
|
| 2504 |
++ |
|
| 2505 |
++ /* First frag */ |
|
| 2506 |
++ if (desc_ctrl & CL_DESC_FIRST) {
|
|
| 2507 |
++ skb = build_skb(buf_addr, 0); |
|
| 2508 |
++ if (unlikely(!skb)) |
|
| 2509 |
++ goto pkt_drop; |
|
| 2510 |
++ |
|
| 2511 |
++ skb_reserve(skb, offset); |
|
| 2512 |
++ skb_put(skb, length); |
|
| 2513 |
++ skb->dev = ndev; |
|
| 2514 |
++ |
|
| 2515 |
++ if ((ndev->features & NETIF_F_RXCSUM) && (rx_ctrl & |
|
| 2516 |
++ HIF_CTRL_RX_CHECKSUMMED)) |
|
| 2517 |
++ skb->ip_summed = CHECKSUM_UNNECESSARY; |
|
| 2518 |
++ else |
|
| 2519 |
++ skb_checksum_none_assert(skb); |
|
| 2520 |
++ |
|
| 2521 |
++ } else {
|
|
| 2522 |
++ /* Next frags */ |
|
| 2523 |
++ if (unlikely(!skb)) {
|
|
| 2524 |
++ pr_err("%s: NULL skb_inflight\n",
|
|
| 2525 |
++ __func__); |
|
| 2526 |
++ goto pkt_drop; |
|
| 2527 |
++ } |
|
| 2528 |
++ |
|
| 2529 |
++ skb_frag = build_skb(buf_addr, 0); |
|
| 2530 |
++ |
|
| 2531 |
++ if (unlikely(!skb_frag)) {
|
|
| 2532 |
++ kfree(buf_addr); |
|
| 2533 |
++ goto pkt_drop; |
|
| 2534 |
++ } |
|
| 2535 |
++ |
|
| 2536 |
++ skb_reserve(skb_frag, offset); |
|
| 2537 |
++ skb_put(skb_frag, length); |
|
| 2538 |
++ |
|
| 2539 |
++ skb_frag->dev = ndev; |
|
| 2540 |
++ |
|
| 2541 |
++ if (skb_shinfo(skb)->frag_list) |
|
| 2542 |
++ skb_frag_last->next = skb_frag; |
|
| 2543 |
++ else |
|
| 2544 |
++ skb_shinfo(skb)->frag_list = skb_frag; |
|
| 2545 |
++ |
|
| 2546 |
++ skb->truesize += skb_frag->truesize; |
|
| 2547 |
++ skb->data_len += length; |
|
| 2548 |
++ skb->len += length; |
|
| 2549 |
++ skb_frag_last = skb_frag; |
|
| 2550 |
++ } |
|
| 2551 |
++ } |
|
| 2552 |
++ |
|
| 2553 |
++ priv->skb_inflight[qno] = NULL; |
|
| 2554 |
++ return skb; |
|
| 2555 |
++ |
|
| 2556 |
++incomplete: |
|
| 2557 |
++ priv->skb_inflight[qno] = skb; |
|
| 2558 |
++ return NULL; |
|
| 2559 |
++ |
|
| 2560 |
++pkt_drop: |
|
| 2561 |
++ priv->skb_inflight[qno] = NULL; |
|
| 2562 |
++ |
|
| 2563 |
++ if (skb) |
|
| 2564 |
++ kfree_skb(skb); |
|
| 2565 |
++ else |
|
| 2566 |
++ kfree(buf_addr); |
|
| 2567 |
++ |
|
| 2568 |
++ priv->stats.rx_errors++; |
|
| 2569 |
++ |
|
| 2570 |
++ return NULL; |
|
| 2571 |
++} |
|
| 2572 |
++ |
|
| 2573 |
++/* pfe_eth_poll |
|
| 2574 |
++ */ |
|
| 2575 |
++static int pfe_eth_poll(struct pfe_eth_priv_s *priv, struct napi_struct *napi, |
|
| 2576 |
++ unsigned int qno, int budget) |
|
| 2577 |
++{
|
|
| 2578 |
++ struct net_device *ndev = priv->ndev; |
|
| 2579 |
++ struct sk_buff *skb; |
|
| 2580 |
++ int work_done = 0; |
|
| 2581 |
++ unsigned int len; |
|
| 2582 |
++ |
|
| 2583 |
++ netif_info(priv, intr, priv->ndev, "%s\n", __func__); |
|
| 2584 |
++ |
|
| 2585 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 2586 |
++ priv->napi_counters[NAPI_POLL_COUNT]++; |
|
| 2587 |
++#endif |
|
| 2588 |
++ |
|
| 2589 |
++ do {
|
|
| 2590 |
++ skb = pfe_eth_rx_skb(ndev, priv, qno); |
|
| 2591 |
++ |
|
| 2592 |
++ if (!skb) |
|
| 2593 |
++ break; |
|
| 2594 |
++ |
|
| 2595 |
++ len = skb->len; |
|
| 2596 |
++ |
|
| 2597 |
++ /* Packet will be processed */ |
|
| 2598 |
++ skb->protocol = eth_type_trans(skb, ndev); |
|
| 2599 |
++ |
|
| 2600 |
++ netif_receive_skb(skb); |
|
| 2601 |
++ |
|
| 2602 |
++ priv->stats.rx_packets++; |
|
| 2603 |
++ priv->stats.rx_bytes += len; |
|
| 2604 |
++ |
|
| 2605 |
++ work_done++; |
|
| 2606 |
++ |
|
| 2607 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 2608 |
++ priv->napi_counters[NAPI_PACKET_COUNT]++; |
|
| 2609 |
++#endif |
|
| 2610 |
++ |
|
| 2611 |
++ } while (work_done < budget); |
|
| 2612 |
++ |
|
| 2613 |
++ /* |
|
| 2614 |
++ * If no Rx receive nor cleanup work was done, exit polling mode. |
|
| 2615 |
++ * No more netif_running(dev) check is required here , as this is |
|
| 2616 |
++ * checked in net/core/dev.c (2.6.33.5 kernel specific). |
|
| 2617 |
++ */ |
|
| 2618 |
++ if (work_done < budget) {
|
|
| 2619 |
++ napi_complete(napi); |
|
| 2620 |
++ |
|
| 2621 |
++ hif_lib_event_handler_start(&priv->client, EVENT_RX_PKT_IND, |
|
| 2622 |
++ qno); |
|
| 2623 |
++ } |
|
| 2624 |
++#ifdef PFE_ETH_NAPI_STATS |
|
| 2625 |
++ else |
|
| 2626 |
++ priv->napi_counters[NAPI_FULL_BUDGET_COUNT]++; |
|
| 2627 |
++#endif |
|
| 2628 |
++ |
|
| 2629 |
++ return work_done; |
|
| 2630 |
++} |
|
| 2631 |
++ |
|
| 2632 |
++/* |
|
| 2633 |
++ * pfe_eth_lro_poll |
|
| 2634 |
++ */ |
|
| 2635 |
++static int pfe_eth_lro_poll(struct napi_struct *napi, int budget) |
|
| 2636 |
++{
|
|
| 2637 |
++ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, |
|
| 2638 |
++ lro_napi); |
|
| 2639 |
++ |
|
| 2640 |
++ netif_info(priv, intr, priv->ndev, "%s\n", __func__); |
|
| 2641 |
++ |
|
| 2642 |
++ return pfe_eth_poll(priv, napi, 2, budget); |
|
| 2643 |
++} |
|
| 2644 |
++ |
|
| 2645 |
++/* pfe_eth_low_poll |
|
| 2646 |
++ */ |
|
| 2647 |
++static int pfe_eth_low_poll(struct napi_struct *napi, int budget) |
|
| 2648 |
++{
|
|
| 2649 |
++ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, |
|
| 2650 |
++ low_napi); |
|
| 2651 |
++ |
|
| 2652 |
++ netif_info(priv, intr, priv->ndev, "%s\n", __func__); |
|
| 2653 |
++ |
|
| 2654 |
++ return pfe_eth_poll(priv, napi, 1, budget); |
|
| 2655 |
++} |
|
| 2656 |
++ |
|
| 2657 |
++/* pfe_eth_high_poll |
|
| 2658 |
++ */ |
|
| 2659 |
++static int pfe_eth_high_poll(struct napi_struct *napi, int budget) |
|
| 2660 |
++{
|
|
| 2661 |
++ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, |
|
| 2662 |
++ high_napi); |
|
| 2663 |
++ |
|
| 2664 |
++ netif_info(priv, intr, priv->ndev, "%s\n", __func__); |
|
| 2665 |
++ |
|
| 2666 |
++ return pfe_eth_poll(priv, napi, 0, budget); |
|
| 2667 |
++} |
|
| 2668 |
++ |
|
| 2669 |
++static const struct net_device_ops pfe_netdev_ops = {
|
|
| 2670 |
++ .ndo_open = pfe_eth_open, |
|
| 2671 |
++ .ndo_stop = pfe_eth_close, |
|
| 2672 |
++ .ndo_start_xmit = pfe_eth_send_packet, |
|
| 2673 |
++ .ndo_select_queue = pfe_eth_select_queue, |
|
| 2674 |
++ .ndo_get_stats = pfe_eth_get_stats, |
|
| 2675 |
++ .ndo_set_mac_address = pfe_eth_set_mac_address, |
|
| 2676 |
++ .ndo_set_rx_mode = pfe_eth_set_multi, |
|
| 2677 |
++ .ndo_set_features = pfe_eth_set_features, |
|
| 2678 |
++ .ndo_validate_addr = eth_validate_addr, |
|
| 2679 |
++}; |
|
| 2680 |
++ |
|
| 2681 |
++/* pfe_eth_init_one |
|
| 2682 |
++ */ |
|
| 2683 |
++static int pfe_eth_init_one(struct pfe *pfe, int id) |
|
| 2684 |
++{
|
|
| 2685 |
++ struct net_device *ndev = NULL; |
|
| 2686 |
++ struct pfe_eth_priv_s *priv = NULL; |
|
| 2687 |
++ struct ls1012a_eth_platform_data *einfo; |
|
| 2688 |
++ struct ls1012a_mdio_platform_data *minfo; |
|
| 2689 |
++ struct ls1012a_pfe_platform_data *pfe_info; |
|
| 2690 |
++ int err; |
|
| 2691 |
++ |
|
| 2692 |
++ /* Extract pltform data */ |
|
| 2693 |
++ pfe_info = (struct ls1012a_pfe_platform_data *) |
|
| 2694 |
++ pfe->dev->platform_data; |
|
| 2695 |
++ if (!pfe_info) {
|
|
| 2696 |
++ pr_err( |
|
| 2697 |
++ "%s: pfe missing additional platform data\n" |
|
| 2698 |
++ , __func__); |
|
| 2699 |
++ err = -ENODEV; |
|
| 2700 |
++ goto err0; |
|
| 2701 |
++ } |
|
| 2702 |
++ |
|
| 2703 |
++ einfo = (struct ls1012a_eth_platform_data *) |
|
| 2704 |
++ pfe_info->ls1012a_eth_pdata; |
|
| 2705 |
++ |
|
| 2706 |
++ /* einfo never be NULL, but no harm in having this check */ |
|
| 2707 |
++ if (!einfo) {
|
|
| 2708 |
++ pr_err( |
|
| 2709 |
++ "%s: pfe missing additional gemacs platform data\n" |
|
| 2710 |
++ , __func__); |
|
| 2711 |
++ err = -ENODEV; |
|
| 2712 |
++ goto err0; |
|
| 2713 |
++ } |
|
| 2714 |
++ |
|
| 2715 |
++ minfo = (struct ls1012a_mdio_platform_data *) |
|
| 2716 |
++ pfe_info->ls1012a_mdio_pdata; |
|
| 2717 |
++ |
|
| 2718 |
++ /* einfo never be NULL, but no harm in having this check */ |
|
| 2719 |
++ if (!minfo) {
|
|
| 2720 |
++ pr_err( |
|
| 2721 |
++ "%s: pfe missing additional mdios platform data\n", |
|
| 2722 |
++ __func__); |
|
| 2723 |
++ err = -ENODEV; |
|
| 2724 |
++ goto err0; |
|
| 2725 |
++ } |
|
| 2726 |
++ |
|
| 2727 |
++ /* Create an ethernet device instance */ |
|
| 2728 |
++ ndev = alloc_etherdev_mq(sizeof(*priv), emac_txq_cnt); |
|
| 2729 |
++ |
|
| 2730 |
++ if (!ndev) {
|
|
| 2731 |
++ pr_err("%s: gemac %d device allocation failed\n",
|
|
| 2732 |
++ __func__, einfo[id].gem_id); |
|
| 2733 |
++ err = -ENOMEM; |
|
| 2734 |
++ goto err0; |
|
| 2735 |
++ } |
|
| 2736 |
++ |
|
| 2737 |
++ priv = netdev_priv(ndev); |
|
| 2738 |
++ priv->ndev = ndev; |
|
| 2739 |
++ priv->id = einfo[id].gem_id; |
|
| 2740 |
++ priv->pfe = pfe; |
|
| 2741 |
++ |
|
| 2742 |
++ SET_NETDEV_DEV(priv->ndev, priv->pfe->dev); |
|
| 2743 |
++ |
|
| 2744 |
++ pfe->eth.eth_priv[id] = priv; |
|
| 2745 |
++ |
|
| 2746 |
++ /* Set the info in the priv to the current info */ |
|
| 2747 |
++ priv->einfo = &einfo[id]; |
|
| 2748 |
++ priv->EMAC_baseaddr = cbus_emac_base[id]; |
|
| 2749 |
++ priv->PHY_baseaddr = cbus_emac_base[0]; |
|
| 2750 |
++ priv->GPI_baseaddr = cbus_gpi_base[id]; |
|
| 2751 |
++ |
|
| 2752 |
++#define HIF_GEMAC_TMUQ_BASE 6 |
|
| 2753 |
++ priv->low_tmu_q = HIF_GEMAC_TMUQ_BASE + (id * 2); |
|
| 2754 |
++ priv->high_tmu_q = priv->low_tmu_q + 1; |
|
| 2755 |
++ |
|
| 2756 |
++ spin_lock_init(&priv->lock); |
|
| 2757 |
++ |
|
| 2758 |
++ pfe_eth_fast_tx_timeout_init(priv); |
|
| 2759 |
++ |
|
| 2760 |
++ /* Copy the station address into the dev structure, */ |
|
| 2761 |
++ memcpy(ndev->dev_addr, einfo[id].mac_addr, ETH_ALEN); |
|
| 2762 |
++ |
|
| 2763 |
++ /* Initialize mdio */ |
|
| 2764 |
++ if (minfo[id].enabled) {
|
|
| 2765 |
++ err = pfe_eth_mdio_init(priv, &minfo[id]); |
|
| 2766 |
++ if (err) {
|
|
| 2767 |
++ netdev_err(ndev, "%s: pfe_eth_mdio_init() failed\n", |
|
| 2768 |
++ __func__); |
|
| 2769 |
++ goto err2; |
|
| 2770 |
++ } |
|
| 2771 |
++ } |
|
| 2772 |
++ |
|
| 2773 |
++ ndev->mtu = 1500; |
|
| 2774 |
++ |
|
| 2775 |
++ /* Set MTU limits */ |
|
| 2776 |
++ ndev->min_mtu = ETH_MIN_MTU; |
|
| 2777 |
++ ndev->max_mtu = JUMBO_FRAME_SIZE; |
|
| 2778 |
++ |
|
| 2779 |
++ /* supported features */ |
|
| 2780 |
++ ndev->hw_features = NETIF_F_SG; |
|
| 2781 |
++ |
|
| 2782 |
++ /*Enable after checksum offload is validated */ |
|
| 2783 |
++ ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | |
|
| 2784 |
++ NETIF_F_IPV6_CSUM | NETIF_F_SG; |
|
| 2785 |
++ |
|
| 2786 |
++ /* enabled by default */ |
|
| 2787 |
++ ndev->features = ndev->hw_features; |
|
| 2788 |
++ |
|
| 2789 |
++ priv->usr_features = ndev->features; |
|
| 2790 |
++ |
|
| 2791 |
++ ndev->netdev_ops = &pfe_netdev_ops; |
|
| 2792 |
++ |
|
| 2793 |
++ ndev->ethtool_ops = &pfe_ethtool_ops; |
|
| 2794 |
++ |
|
| 2795 |
++ /* Enable basic messages by default */ |
|
| 2796 |
++ priv->msg_enable = NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_LINK | |
|
| 2797 |
++ NETIF_MSG_PROBE; |
|
| 2798 |
++ |
|
| 2799 |
++ netif_napi_add(ndev, &priv->low_napi, pfe_eth_low_poll, |
|
| 2800 |
++ HIF_RX_POLL_WEIGHT - 16); |
|
| 2801 |
++ netif_napi_add(ndev, &priv->high_napi, pfe_eth_high_poll, |
|
| 2802 |
++ HIF_RX_POLL_WEIGHT - 16); |
|
| 2803 |
++ netif_napi_add(ndev, &priv->lro_napi, pfe_eth_lro_poll, |
|
| 2804 |
++ HIF_RX_POLL_WEIGHT - 16); |
|
| 2805 |
++ |
|
| 2806 |
++ err = register_netdev(ndev); |
|
| 2807 |
++ |
|
| 2808 |
++ if (err) {
|
|
| 2809 |
++ netdev_err(ndev, "register_netdev() failed\n"); |
|
| 2810 |
++ goto err3; |
|
| 2811 |
++ } |
|
| 2812 |
++ device_init_wakeup(&ndev->dev, WAKE_MAGIC); |
|
| 2813 |
++ |
|
| 2814 |
++ if (!(priv->einfo->phy_flags & GEMAC_NO_PHY)) {
|
|
| 2815 |
++ err = pfe_phy_init(ndev); |
|
| 2816 |
++ if (err) {
|
|
| 2817 |
++ netdev_err(ndev, "%s: pfe_phy_init() failed\n", |
|
| 2818 |
++ __func__); |
|
| 2819 |
++ goto err4; |
|
| 2820 |
++ } |
|
| 2821 |
++ } |
|
| 2822 |
++ |
|
| 2823 |
++ netif_carrier_on(ndev); |
|
| 2824 |
++ |
|
| 2825 |
++ /* Create all the sysfs files */ |
|
| 2826 |
++ if (pfe_eth_sysfs_init(ndev)) |
|
| 2827 |
++ goto err4; |
|
| 2828 |
++ |
|
| 2829 |
++ netif_info(priv, probe, ndev, "%s: created interface, baseaddr: %p\n", |
|
| 2830 |
++ __func__, priv->EMAC_baseaddr); |
|
| 2831 |
++ |
|
| 2832 |
++ return 0; |
|
| 2833 |
++err4: |
|
| 2834 |
++ unregister_netdev(ndev); |
|
| 2835 |
++err3: |
|
| 2836 |
++ pfe_eth_mdio_exit(priv->mii_bus); |
|
| 2837 |
++err2: |
|
| 2838 |
++ free_netdev(priv->ndev); |
|
| 2839 |
++err0: |
|
| 2840 |
++ return err; |
|
| 2841 |
++} |
|
| 2842 |
++ |
|
| 2843 |
++/* pfe_eth_init |
|
| 2844 |
++ */ |
|
| 2845 |
++int pfe_eth_init(struct pfe *pfe) |
|
| 2846 |
++{
|
|
| 2847 |
++ int ii = 0; |
|
| 2848 |
++ int err; |
|
| 2849 |
++ |
|
| 2850 |
++ pr_info("%s\n", __func__);
|
|
| 2851 |
++ |
|
| 2852 |
++ cbus_emac_base[0] = EMAC1_BASE_ADDR; |
|
| 2853 |
++ cbus_emac_base[1] = EMAC2_BASE_ADDR; |
|
| 2854 |
++ |
|
| 2855 |
++ cbus_gpi_base[0] = EGPI1_BASE_ADDR; |
|
| 2856 |
++ cbus_gpi_base[1] = EGPI2_BASE_ADDR; |
|
| 2857 |
++ |
|
| 2858 |
++ for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) {
|
|
| 2859 |
++ err = pfe_eth_init_one(pfe, ii); |
|
| 2860 |
++ if (err) |
|
| 2861 |
++ goto err0; |
|
| 2862 |
++ } |
|
| 2863 |
++ |
|
| 2864 |
++ return 0; |
|
| 2865 |
++ |
|
| 2866 |
++err0: |
|
| 2867 |
++ while (ii--) |
|
| 2868 |
++ pfe_eth_exit_one(pfe->eth.eth_priv[ii]); |
|
| 2869 |
++ |
|
| 2870 |
++ /* Register three network devices in the kernel */ |
|
| 2871 |
++ return err; |
|
| 2872 |
++} |
|
| 2873 |
++ |
|
| 2874 |
++/* pfe_eth_exit_one |
|
| 2875 |
++ */ |
|
| 2876 |
++static void pfe_eth_exit_one(struct pfe_eth_priv_s *priv) |
|
| 2877 |
++{
|
|
| 2878 |
++ netif_info(priv, probe, priv->ndev, "%s\n", __func__); |
|
| 2879 |
++ |
|
| 2880 |
++ pfe_eth_sysfs_exit(priv->ndev); |
|
| 2881 |
++ |
|
| 2882 |
++ unregister_netdev(priv->ndev); |
|
| 2883 |
++ |
|
| 2884 |
++ if (!(priv->einfo->phy_flags & GEMAC_NO_PHY)) |
|
| 2885 |
++ pfe_phy_exit(priv->ndev); |
|
| 2886 |
++ |
|
| 2887 |
++ if (priv->mii_bus) |
|
| 2888 |
++ pfe_eth_mdio_exit(priv->mii_bus); |
|
| 2889 |
++ |
|
| 2890 |
++ free_netdev(priv->ndev); |
|
| 2891 |
++} |
|
| 2892 |
++ |
|
| 2893 |
++/* pfe_eth_exit |
|
| 2894 |
++ */ |
|
| 2895 |
++void pfe_eth_exit(struct pfe *pfe) |
|
| 2896 |
++{
|
|
| 2897 |
++ int ii; |
|
| 2898 |
++ |
|
| 2899 |
++ pr_info("%s\n", __func__);
|
|
| 2900 |
++ |
|
| 2901 |
++ for (ii = NUM_GEMAC_SUPPORT - 1; ii >= 0; ii--) |
|
| 2902 |
++ pfe_eth_exit_one(pfe->eth.eth_priv[ii]); |
|
| 2903 |
++} |
|
| 2904 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_firmware.c b/drivers/staging/fsl_ppfe/pfe_firmware.c |
|
| 2905 |
+new file mode 100644 |
|
| 2906 |
+index 000000000000..47462b9fe2ea |
|
| 2907 |
+--- /dev/null |
|
| 2908 |
+@@ -0,0 +1,314 @@ |
|
| 2909 |
++/* |
|
| 2910 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 2911 |
++ * Copyright 2017 NXP |
|
| 2912 |
++ * |
|
| 2913 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 2914 |
++ * it under the terms of the GNU General Public License as published by |
|
| 2915 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 2916 |
++ * (at your option) any later version. |
|
| 2917 |
++ * |
|
| 2918 |
++ * This program is distributed in the hope that it will be useful, |
|
| 2919 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 2920 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 2921 |
++ * GNU General Public License for more details. |
|
| 2922 |
++ * |
|
| 2923 |
++ * You should have received a copy of the GNU General Public License |
|
| 2924 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 2925 |
++ */ |
|
| 2926 |
++ |
|
| 2927 |
++/* |
|
| 2928 |
++ * @file |
|
| 2929 |
++ * Contains all the functions to handle parsing and loading of PE firmware |
|
| 2930 |
++ * files. |
|
| 2931 |
++ */ |
|
| 2932 |
++#include <linux/firmware.h> |
|
| 2933 |
++ |
|
| 2934 |
++#include "pfe_mod.h" |
|
| 2935 |
++#include "pfe_firmware.h" |
|
| 2936 |
++#include "pfe/pfe.h" |
|
| 2937 |
++ |
|
| 2938 |
++static struct elf32_shdr *get_elf_section_header(const struct firmware *fw, |
|
| 2939 |
++ const char *section) |
|
| 2940 |
++{
|
|
| 2941 |
++ struct elf32_hdr *elf_hdr = (struct elf32_hdr *)fw->data; |
|
| 2942 |
++ struct elf32_shdr *shdr; |
|
| 2943 |
++ struct elf32_shdr *shdr_shstr; |
|
| 2944 |
++ Elf32_Off e_shoff = be32_to_cpu(elf_hdr->e_shoff); |
|
| 2945 |
++ Elf32_Half e_shentsize = be16_to_cpu(elf_hdr->e_shentsize); |
|
| 2946 |
++ Elf32_Half e_shnum = be16_to_cpu(elf_hdr->e_shnum); |
|
| 2947 |
++ Elf32_Half e_shstrndx = be16_to_cpu(elf_hdr->e_shstrndx); |
|
| 2948 |
++ Elf32_Off shstr_offset; |
|
| 2949 |
++ Elf32_Word sh_name; |
|
| 2950 |
++ const char *name; |
|
| 2951 |
++ int i; |
|
| 2952 |
++ |
|
| 2953 |
++ /* Section header strings */ |
|
| 2954 |
++ shdr_shstr = (struct elf32_shdr *)(fw->data + e_shoff + e_shstrndx * |
|
| 2955 |
++ e_shentsize); |
|
| 2956 |
++ shstr_offset = be32_to_cpu(shdr_shstr->sh_offset); |
|
| 2957 |
++ |
|
| 2958 |
++ for (i = 0; i < e_shnum; i++) {
|
|
| 2959 |
++ shdr = (struct elf32_shdr *)(fw->data + e_shoff |
|
| 2960 |
++ + i * e_shentsize); |
|
| 2961 |
++ |
|
| 2962 |
++ sh_name = be32_to_cpu(shdr->sh_name); |
|
| 2963 |
++ |
|
| 2964 |
++ name = (const char *)(fw->data + shstr_offset + sh_name); |
|
| 2965 |
++ |
|
| 2966 |
++ if (!strcmp(name, section)) |
|
| 2967 |
++ return shdr; |
|
| 2968 |
++ } |
|
| 2969 |
++ |
|
| 2970 |
++ pr_err("%s: didn't find section %s\n", __func__, section);
|
|
| 2971 |
++ |
|
| 2972 |
++ return NULL; |
|
| 2973 |
++} |
|
| 2974 |
++ |
|
| 2975 |
++#if defined(CFG_DIAGS) |
|
| 2976 |
++static int pfe_get_diags_info(const struct firmware *fw, struct pfe_diags_info |
|
| 2977 |
++ *diags_info) |
|
| 2978 |
++{
|
|
| 2979 |
++ struct elf32_shdr *shdr; |
|
| 2980 |
++ unsigned long offset, size; |
|
| 2981 |
++ |
|
| 2982 |
++ shdr = get_elf_section_header(fw, ".pfe_diags_str"); |
|
| 2983 |
++ if (shdr) {
|
|
| 2984 |
++ offset = be32_to_cpu(shdr->sh_offset); |
|
| 2985 |
++ size = be32_to_cpu(shdr->sh_size); |
|
| 2986 |
++ diags_info->diags_str_base = be32_to_cpu(shdr->sh_addr); |
|
| 2987 |
++ diags_info->diags_str_size = size; |
|
| 2988 |
++ diags_info->diags_str_array = kmalloc(size, GFP_KERNEL); |
|
| 2989 |
++ memcpy(diags_info->diags_str_array, fw->data + offset, size); |
|
| 2990 |
++ |
|
| 2991 |
++ return 0; |
|
| 2992 |
++ } else {
|
|
| 2993 |
++ return -1; |
|
| 2994 |
++ } |
|
| 2995 |
++} |
|
| 2996 |
++#endif |
|
| 2997 |
++ |
|
| 2998 |
++static void pfe_check_version_info(const struct firmware *fw) |
|
| 2999 |
++{
|
|
| 3000 |
++ /*static char *version = NULL;*/ |
|
| 3001 |
++ static char *version; |
|
| 3002 |
++ |
|
| 3003 |
++ struct elf32_shdr *shdr = get_elf_section_header(fw, ".version"); |
|
| 3004 |
++ |
|
| 3005 |
++ if (shdr) {
|
|
| 3006 |
++ if (!version) {
|
|
| 3007 |
++ /* |
|
| 3008 |
++ * this is the first fw we load, use its version |
|
| 3009 |
++ * string as reference (whatever it is) |
|
| 3010 |
++ */ |
|
| 3011 |
++ version = (char *)(fw->data + |
|
| 3012 |
++ be32_to_cpu(shdr->sh_offset)); |
|
| 3013 |
++ |
|
| 3014 |
++ pr_info("PFE binary version: %s\n", version);
|
|
| 3015 |
++ } else {
|
|
| 3016 |
++ /* |
|
| 3017 |
++ * already have loaded at least one firmware, check |
|
| 3018 |
++ * sequence can start now |
|
| 3019 |
++ */ |
|
| 3020 |
++ if (strcmp(version, (char *)(fw->data + |
|
| 3021 |
++ be32_to_cpu(shdr->sh_offset)))) {
|
|
| 3022 |
++ pr_info( |
|
| 3023 |
++ "WARNING: PFE firmware binaries from incompatible version\n"); |
|
| 3024 |
++ } |
|
| 3025 |
++ } |
|
| 3026 |
++ } else {
|
|
| 3027 |
++ /* |
|
| 3028 |
++ * version cannot be verified, a potential issue that should |
|
| 3029 |
++ * be reported |
|
| 3030 |
++ */ |
|
| 3031 |
++ pr_info( |
|
| 3032 |
++ "WARNING: PFE firmware binaries from incompatible version\n"); |
|
| 3033 |
++ } |
|
| 3034 |
++} |
|
| 3035 |
++ |
|
| 3036 |
++/* PFE elf firmware loader. |
|
| 3037 |
++ * Loads an elf firmware image into a list of PE's (specified using a bitmask) |
|
| 3038 |
++ * |
|
| 3039 |
++ * @param pe_mask Mask of PE id's to load firmware to |
|
| 3040 |
++ * @param fw Pointer to the firmware image |
|
| 3041 |
++ * |
|
| 3042 |
++ * @return 0 on success, a negative value on error |
|
| 3043 |
++ * |
|
| 3044 |
++ */ |
|
| 3045 |
++int pfe_load_elf(int pe_mask, const struct firmware *fw, struct pfe *pfe) |
|
| 3046 |
++{
|
|
| 3047 |
++ struct elf32_hdr *elf_hdr = (struct elf32_hdr *)fw->data; |
|
| 3048 |
++ Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum); |
|
| 3049 |
++ struct elf32_shdr *shdr = (struct elf32_shdr *)(fw->data + |
|
| 3050 |
++ be32_to_cpu(elf_hdr->e_shoff)); |
|
| 3051 |
++ int id, section; |
|
| 3052 |
++ int rc; |
|
| 3053 |
++ |
|
| 3054 |
++ pr_info("%s\n", __func__);
|
|
| 3055 |
++ |
|
| 3056 |
++ /* Some sanity checks */ |
|
| 3057 |
++ if (strncmp(&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
|
|
| 3058 |
++ pr_err("%s: incorrect elf magic number\n", __func__);
|
|
| 3059 |
++ return -EINVAL; |
|
| 3060 |
++ } |
|
| 3061 |
++ |
|
| 3062 |
++ if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
|
|
| 3063 |
++ pr_err("%s: incorrect elf class(%x)\n", __func__,
|
|
| 3064 |
++ elf_hdr->e_ident[EI_CLASS]); |
|
| 3065 |
++ return -EINVAL; |
|
| 3066 |
++ } |
|
| 3067 |
++ |
|
| 3068 |
++ if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) {
|
|
| 3069 |
++ pr_err("%s: incorrect elf data(%x)\n", __func__,
|
|
| 3070 |
++ elf_hdr->e_ident[EI_DATA]); |
|
| 3071 |
++ return -EINVAL; |
|
| 3072 |
++ } |
|
| 3073 |
++ |
|
| 3074 |
++ if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) {
|
|
| 3075 |
++ pr_err("%s: incorrect elf file type(%x)\n", __func__,
|
|
| 3076 |
++ be16_to_cpu(elf_hdr->e_type)); |
|
| 3077 |
++ return -EINVAL; |
|
| 3078 |
++ } |
|
| 3079 |
++ |
|
| 3080 |
++ for (section = 0; section < sections; section++, shdr++) {
|
|
| 3081 |
++ if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC | |
|
| 3082 |
++ SHF_EXECINSTR))) |
|
| 3083 |
++ continue; |
|
| 3084 |
++ |
|
| 3085 |
++ for (id = 0; id < MAX_PE; id++) |
|
| 3086 |
++ if (pe_mask & (1 << id)) {
|
|
| 3087 |
++ rc = pe_load_elf_section(id, fw->data, shdr, |
|
| 3088 |
++ pfe->dev); |
|
| 3089 |
++ if (rc < 0) |
|
| 3090 |
++ goto err; |
|
| 3091 |
++ } |
|
| 3092 |
++ } |
|
| 3093 |
++ |
|
| 3094 |
++ pfe_check_version_info(fw); |
|
| 3095 |
++ |
|
| 3096 |
++ return 0; |
|
| 3097 |
++ |
|
| 3098 |
++err: |
|
| 3099 |
++ return rc; |
|
| 3100 |
++} |
|
| 3101 |
++ |
|
| 3102 |
++/* PFE firmware initialization. |
|
| 3103 |
++ * Loads different firmware files from filesystem. |
|
| 3104 |
++ * Initializes PE IMEM/DMEM and UTIL-PE DDR |
|
| 3105 |
++ * Initializes control path symbol addresses (by looking them up in the elf |
|
| 3106 |
++ * firmware files |
|
| 3107 |
++ * Takes PE's out of reset |
|
| 3108 |
++ * |
|
| 3109 |
++ * @return 0 on success, a negative value on error |
|
| 3110 |
++ * |
|
| 3111 |
++ */ |
|
| 3112 |
++int pfe_firmware_init(struct pfe *pfe) |
|
| 3113 |
++{
|
|
| 3114 |
++ const struct firmware *class_fw, *tmu_fw; |
|
| 3115 |
++ int rc = 0; |
|
| 3116 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3117 |
++ const char *util_fw_name; |
|
| 3118 |
++ const struct firmware *util_fw; |
|
| 3119 |
++#endif |
|
| 3120 |
++ |
|
| 3121 |
++ pr_info("%s\n", __func__);
|
|
| 3122 |
++ |
|
| 3123 |
++ if (request_firmware(&class_fw, CLASS_FIRMWARE_FILENAME, pfe->dev)) {
|
|
| 3124 |
++ pr_err("%s: request firmware %s failed\n", __func__,
|
|
| 3125 |
++ CLASS_FIRMWARE_FILENAME); |
|
| 3126 |
++ rc = -ETIMEDOUT; |
|
| 3127 |
++ goto err0; |
|
| 3128 |
++ } |
|
| 3129 |
++ |
|
| 3130 |
++ if (request_firmware(&tmu_fw, TMU_FIRMWARE_FILENAME, pfe->dev)) {
|
|
| 3131 |
++ pr_err("%s: request firmware %s failed\n", __func__,
|
|
| 3132 |
++ TMU_FIRMWARE_FILENAME); |
|
| 3133 |
++ rc = -ETIMEDOUT; |
|
| 3134 |
++ goto err1; |
|
| 3135 |
++} |
|
| 3136 |
++ |
|
| 3137 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3138 |
++ util_fw_name = UTIL_FIRMWARE_FILENAME; |
|
| 3139 |
++ |
|
| 3140 |
++ if (request_firmware(&util_fw, util_fw_name, pfe->dev)) {
|
|
| 3141 |
++ pr_err("%s: request firmware %s failed\n", __func__,
|
|
| 3142 |
++ util_fw_name); |
|
| 3143 |
++ rc = -ETIMEDOUT; |
|
| 3144 |
++ goto err2; |
|
| 3145 |
++ } |
|
| 3146 |
++#endif |
|
| 3147 |
++ rc = pfe_load_elf(CLASS_MASK, class_fw, pfe); |
|
| 3148 |
++ if (rc < 0) {
|
|
| 3149 |
++ pr_err("%s: class firmware load failed\n", __func__);
|
|
| 3150 |
++ goto err3; |
|
| 3151 |
++ } |
|
| 3152 |
++ |
|
| 3153 |
++#if defined(CFG_DIAGS) |
|
| 3154 |
++ rc = pfe_get_diags_info(class_fw, &pfe->diags.class_diags_info); |
|
| 3155 |
++ if (rc < 0) {
|
|
| 3156 |
++ pr_warn( |
|
| 3157 |
++ "PFE diags won't be available for class PEs\n"); |
|
| 3158 |
++ rc = 0; |
|
| 3159 |
++ } |
|
| 3160 |
++#endif |
|
| 3161 |
++ |
|
| 3162 |
++ rc = pfe_load_elf(TMU_MASK, tmu_fw, pfe); |
|
| 3163 |
++ if (rc < 0) {
|
|
| 3164 |
++ pr_err("%s: tmu firmware load failed\n", __func__);
|
|
| 3165 |
++ goto err3; |
|
| 3166 |
++ } |
|
| 3167 |
++ |
|
| 3168 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3169 |
++ rc = pfe_load_elf(UTIL_MASK, util_fw, pfe); |
|
| 3170 |
++ if (rc < 0) {
|
|
| 3171 |
++ pr_err("%s: util firmware load failed\n", __func__);
|
|
| 3172 |
++ goto err3; |
|
| 3173 |
++ } |
|
| 3174 |
++ |
|
| 3175 |
++#if defined(CFG_DIAGS) |
|
| 3176 |
++ rc = pfe_get_diags_info(util_fw, &pfe->diags.util_diags_info); |
|
| 3177 |
++ if (rc < 0) {
|
|
| 3178 |
++ pr_warn( |
|
| 3179 |
++ "PFE diags won't be available for util PE\n"); |
|
| 3180 |
++ rc = 0; |
|
| 3181 |
++ } |
|
| 3182 |
++#endif |
|
| 3183 |
++ |
|
| 3184 |
++ util_enable(); |
|
| 3185 |
++#endif |
|
| 3186 |
++ |
|
| 3187 |
++ tmu_enable(0xf); |
|
| 3188 |
++ class_enable(); |
|
| 3189 |
++ |
|
| 3190 |
++err3: |
|
| 3191 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3192 |
++ release_firmware(util_fw); |
|
| 3193 |
++ |
|
| 3194 |
++err2: |
|
| 3195 |
++#endif |
|
| 3196 |
++ release_firmware(tmu_fw); |
|
| 3197 |
++ |
|
| 3198 |
++err1: |
|
| 3199 |
++ release_firmware(class_fw); |
|
| 3200 |
++ |
|
| 3201 |
++err0: |
|
| 3202 |
++ return rc; |
|
| 3203 |
++} |
|
| 3204 |
++ |
|
| 3205 |
++/* PFE firmware cleanup |
|
| 3206 |
++ * Puts PE's in reset |
|
| 3207 |
++ * |
|
| 3208 |
++ * |
|
| 3209 |
++ */ |
|
| 3210 |
++void pfe_firmware_exit(struct pfe *pfe) |
|
| 3211 |
++{
|
|
| 3212 |
++ pr_info("%s\n", __func__);
|
|
| 3213 |
++ |
|
| 3214 |
++ if (pe_reset_all(&pfe->ctrl) != 0) |
|
| 3215 |
++ pr_err("Error: Failed to stop PEs, PFE reload may not work correctly\n");
|
|
| 3216 |
++ |
|
| 3217 |
++ class_disable(); |
|
| 3218 |
++ tmu_disable(0xf); |
|
| 3219 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3220 |
++ util_disable(); |
|
| 3221 |
++#endif |
|
| 3222 |
++} |
|
| 3223 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hal.c b/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 3224 |
+new file mode 100644 |
|
| 3225 |
+index 000000000000..0915034b281b |
|
| 3226 |
+--- /dev/null |
|
| 3227 |
+@@ -0,0 +1,1516 @@ |
|
| 3228 |
++/* |
|
| 3229 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 3230 |
++ * Copyright 2017 NXP |
|
| 3231 |
++ * |
|
| 3232 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 3233 |
++ * it under the terms of the GNU General Public License as published by |
|
| 3234 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 3235 |
++ * (at your option) any later version. |
|
| 3236 |
++ * |
|
| 3237 |
++ * This program is distributed in the hope that it will be useful, |
|
| 3238 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 3239 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 3240 |
++ * GNU General Public License for more details. |
|
| 3241 |
++ * |
|
| 3242 |
++ * You should have received a copy of the GNU General Public License |
|
| 3243 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 3244 |
++ */ |
|
| 3245 |
++ |
|
| 3246 |
++#include "pfe_mod.h" |
|
| 3247 |
++#include "pfe/pfe.h" |
|
| 3248 |
++ |
|
| 3249 |
++void *cbus_base_addr; |
|
| 3250 |
++void *ddr_base_addr; |
|
| 3251 |
++unsigned long ddr_phys_base_addr; |
|
| 3252 |
++unsigned int ddr_size; |
|
| 3253 |
++ |
|
| 3254 |
++static struct pe_info pe[MAX_PE]; |
|
| 3255 |
++ |
|
| 3256 |
++/* Initializes the PFE library. |
|
| 3257 |
++ * Must be called before using any of the library functions. |
|
| 3258 |
++ * |
|
| 3259 |
++ * @param[in] cbus_base CBUS virtual base address (as mapped in |
|
| 3260 |
++ * the host CPU address space) |
|
| 3261 |
++ * @param[in] ddr_base PFE DDR range virtual base address (as |
|
| 3262 |
++ * mapped in the host CPU address space) |
|
| 3263 |
++ * @param[in] ddr_phys_base PFE DDR range physical base address (as |
|
| 3264 |
++ * mapped in platform) |
|
| 3265 |
++ * @param[in] size PFE DDR range size (as defined by the host |
|
| 3266 |
++ * software) |
|
| 3267 |
++ */ |
|
| 3268 |
++void pfe_lib_init(void *cbus_base, void *ddr_base, unsigned long ddr_phys_base, |
|
| 3269 |
++ unsigned int size) |
|
| 3270 |
++{
|
|
| 3271 |
++ cbus_base_addr = cbus_base; |
|
| 3272 |
++ ddr_base_addr = ddr_base; |
|
| 3273 |
++ ddr_phys_base_addr = ddr_phys_base; |
|
| 3274 |
++ ddr_size = size; |
|
| 3275 |
++ |
|
| 3276 |
++ pe[CLASS0_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(0); |
|
| 3277 |
++ pe[CLASS0_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(0); |
|
| 3278 |
++ pe[CLASS0_ID].pmem_size = CLASS_IMEM_SIZE; |
|
| 3279 |
++ pe[CLASS0_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; |
|
| 3280 |
++ pe[CLASS0_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; |
|
| 3281 |
++ pe[CLASS0_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; |
|
| 3282 |
++ |
|
| 3283 |
++ pe[CLASS1_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(1); |
|
| 3284 |
++ pe[CLASS1_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(1); |
|
| 3285 |
++ pe[CLASS1_ID].pmem_size = CLASS_IMEM_SIZE; |
|
| 3286 |
++ pe[CLASS1_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; |
|
| 3287 |
++ pe[CLASS1_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; |
|
| 3288 |
++ pe[CLASS1_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; |
|
| 3289 |
++ |
|
| 3290 |
++ pe[CLASS2_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(2); |
|
| 3291 |
++ pe[CLASS2_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(2); |
|
| 3292 |
++ pe[CLASS2_ID].pmem_size = CLASS_IMEM_SIZE; |
|
| 3293 |
++ pe[CLASS2_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; |
|
| 3294 |
++ pe[CLASS2_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; |
|
| 3295 |
++ pe[CLASS2_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; |
|
| 3296 |
++ |
|
| 3297 |
++ pe[CLASS3_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(3); |
|
| 3298 |
++ pe[CLASS3_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(3); |
|
| 3299 |
++ pe[CLASS3_ID].pmem_size = CLASS_IMEM_SIZE; |
|
| 3300 |
++ pe[CLASS3_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; |
|
| 3301 |
++ pe[CLASS3_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; |
|
| 3302 |
++ pe[CLASS3_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; |
|
| 3303 |
++ |
|
| 3304 |
++ pe[CLASS4_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(4); |
|
| 3305 |
++ pe[CLASS4_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(4); |
|
| 3306 |
++ pe[CLASS4_ID].pmem_size = CLASS_IMEM_SIZE; |
|
| 3307 |
++ pe[CLASS4_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; |
|
| 3308 |
++ pe[CLASS4_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; |
|
| 3309 |
++ pe[CLASS4_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; |
|
| 3310 |
++ |
|
| 3311 |
++ pe[CLASS5_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(5); |
|
| 3312 |
++ pe[CLASS5_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(5); |
|
| 3313 |
++ pe[CLASS5_ID].pmem_size = CLASS_IMEM_SIZE; |
|
| 3314 |
++ pe[CLASS5_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; |
|
| 3315 |
++ pe[CLASS5_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; |
|
| 3316 |
++ pe[CLASS5_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; |
|
| 3317 |
++ |
|
| 3318 |
++ pe[TMU0_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(0); |
|
| 3319 |
++ pe[TMU0_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(0); |
|
| 3320 |
++ pe[TMU0_ID].pmem_size = TMU_IMEM_SIZE; |
|
| 3321 |
++ pe[TMU0_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; |
|
| 3322 |
++ pe[TMU0_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; |
|
| 3323 |
++ pe[TMU0_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; |
|
| 3324 |
++ |
|
| 3325 |
++ pe[TMU1_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(1); |
|
| 3326 |
++ pe[TMU1_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(1); |
|
| 3327 |
++ pe[TMU1_ID].pmem_size = TMU_IMEM_SIZE; |
|
| 3328 |
++ pe[TMU1_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; |
|
| 3329 |
++ pe[TMU1_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; |
|
| 3330 |
++ pe[TMU1_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; |
|
| 3331 |
++ |
|
| 3332 |
++ pe[TMU3_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(3); |
|
| 3333 |
++ pe[TMU3_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(3); |
|
| 3334 |
++ pe[TMU3_ID].pmem_size = TMU_IMEM_SIZE; |
|
| 3335 |
++ pe[TMU3_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; |
|
| 3336 |
++ pe[TMU3_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; |
|
| 3337 |
++ pe[TMU3_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; |
|
| 3338 |
++ |
|
| 3339 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3340 |
++ pe[UTIL_ID].dmem_base_addr = UTIL_DMEM_BASE_ADDR; |
|
| 3341 |
++ pe[UTIL_ID].mem_access_wdata = UTIL_MEM_ACCESS_WDATA; |
|
| 3342 |
++ pe[UTIL_ID].mem_access_addr = UTIL_MEM_ACCESS_ADDR; |
|
| 3343 |
++ pe[UTIL_ID].mem_access_rdata = UTIL_MEM_ACCESS_RDATA; |
|
| 3344 |
++#endif |
|
| 3345 |
++} |
|
| 3346 |
++ |
|
| 3347 |
++/* Writes a buffer to PE internal memory from the host |
|
| 3348 |
++ * through indirect access registers. |
|
| 3349 |
++ * |
|
| 3350 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3351 |
++ * ..., UTIL_ID) |
|
| 3352 |
++ * @param[in] src Buffer source address |
|
| 3353 |
++ * @param[in] mem_access_addr DMEM destination address (must be 32bit |
|
| 3354 |
++ * aligned) |
|
| 3355 |
++ * @param[in] len Number of bytes to copy |
|
| 3356 |
++ */ |
|
| 3357 |
++void pe_mem_memcpy_to32(int id, u32 mem_access_addr, const void *src, unsigned |
|
| 3358 |
++int len) |
|
| 3359 |
++{
|
|
| 3360 |
++ u32 offset = 0, val, addr; |
|
| 3361 |
++ unsigned int len32 = len >> 2; |
|
| 3362 |
++ int i; |
|
| 3363 |
++ |
|
| 3364 |
++ addr = mem_access_addr | PE_MEM_ACCESS_WRITE | |
|
| 3365 |
++ PE_MEM_ACCESS_BYTE_ENABLE(0, 4); |
|
| 3366 |
++ |
|
| 3367 |
++ for (i = 0; i < len32; i++, offset += 4, src += 4) {
|
|
| 3368 |
++ val = *(u32 *)src; |
|
| 3369 |
++ writel(cpu_to_be32(val), pe[id].mem_access_wdata); |
|
| 3370 |
++ writel(addr + offset, pe[id].mem_access_addr); |
|
| 3371 |
++ } |
|
| 3372 |
++ |
|
| 3373 |
++ len = (len & 0x3); |
|
| 3374 |
++ if (len) {
|
|
| 3375 |
++ val = 0; |
|
| 3376 |
++ |
|
| 3377 |
++ addr = (mem_access_addr | PE_MEM_ACCESS_WRITE | |
|
| 3378 |
++ PE_MEM_ACCESS_BYTE_ENABLE(0, len)) + offset; |
|
| 3379 |
++ |
|
| 3380 |
++ for (i = 0; i < len; i++, src++) |
|
| 3381 |
++ val |= (*(u8 *)src) << (8 * i); |
|
| 3382 |
++ |
|
| 3383 |
++ writel(cpu_to_be32(val), pe[id].mem_access_wdata); |
|
| 3384 |
++ writel(addr, pe[id].mem_access_addr); |
|
| 3385 |
++ } |
|
| 3386 |
++} |
|
| 3387 |
++ |
|
| 3388 |
++/* Writes a buffer to PE internal data memory (DMEM) from the host |
|
| 3389 |
++ * through indirect access registers. |
|
| 3390 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3391 |
++ * ..., UTIL_ID) |
|
| 3392 |
++ * @param[in] src Buffer source address |
|
| 3393 |
++ * @param[in] dst DMEM destination address (must be 32bit |
|
| 3394 |
++ * aligned) |
|
| 3395 |
++ * @param[in] len Number of bytes to copy |
|
| 3396 |
++ */ |
|
| 3397 |
++void pe_dmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len) |
|
| 3398 |
++{
|
|
| 3399 |
++ pe_mem_memcpy_to32(id, pe[id].dmem_base_addr | dst | |
|
| 3400 |
++ PE_MEM_ACCESS_DMEM, src, len); |
|
| 3401 |
++} |
|
| 3402 |
++ |
|
| 3403 |
++/* Writes a buffer to PE internal program memory (PMEM) from the host |
|
| 3404 |
++ * through indirect access registers. |
|
| 3405 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3406 |
++ * ..., TMU3_ID) |
|
| 3407 |
++ * @param[in] src Buffer source address |
|
| 3408 |
++ * @param[in] dst PMEM destination address (must be 32bit |
|
| 3409 |
++ * aligned) |
|
| 3410 |
++ * @param[in] len Number of bytes to copy |
|
| 3411 |
++ */ |
|
| 3412 |
++void pe_pmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len) |
|
| 3413 |
++{
|
|
| 3414 |
++ pe_mem_memcpy_to32(id, pe[id].pmem_base_addr | (dst & (pe[id].pmem_size |
|
| 3415 |
++ - 1)) | PE_MEM_ACCESS_IMEM, src, len); |
|
| 3416 |
++} |
|
| 3417 |
++ |
|
| 3418 |
++/* Reads PE internal program memory (IMEM) from the host |
|
| 3419 |
++ * through indirect access registers. |
|
| 3420 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3421 |
++ * ..., TMU3_ID) |
|
| 3422 |
++ * @param[in] addr PMEM read address (must be aligned on size) |
|
| 3423 |
++ * @param[in] size Number of bytes to read (maximum 4, must not |
|
| 3424 |
++ * cross 32bit boundaries) |
|
| 3425 |
++ * @return the data read (in PE endianness, i.e BE). |
|
| 3426 |
++ */ |
|
| 3427 |
++u32 pe_pmem_read(int id, u32 addr, u8 size) |
|
| 3428 |
++{
|
|
| 3429 |
++ u32 offset = addr & 0x3; |
|
| 3430 |
++ u32 mask = 0xffffffff >> ((4 - size) << 3); |
|
| 3431 |
++ u32 val; |
|
| 3432 |
++ |
|
| 3433 |
++ addr = pe[id].pmem_base_addr | ((addr & ~0x3) & (pe[id].pmem_size - 1)) |
|
| 3434 |
++ | PE_MEM_ACCESS_IMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size); |
|
| 3435 |
++ |
|
| 3436 |
++ writel(addr, pe[id].mem_access_addr); |
|
| 3437 |
++ val = be32_to_cpu(readl(pe[id].mem_access_rdata)); |
|
| 3438 |
++ |
|
| 3439 |
++ return (val >> (offset << 3)) & mask; |
|
| 3440 |
++} |
|
| 3441 |
++ |
|
| 3442 |
++/* Writes PE internal data memory (DMEM) from the host |
|
| 3443 |
++ * through indirect access registers. |
|
| 3444 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3445 |
++ * ..., UTIL_ID) |
|
| 3446 |
++ * @param[in] addr DMEM write address (must be aligned on size) |
|
| 3447 |
++ * @param[in] val Value to write (in PE endianness, i.e BE) |
|
| 3448 |
++ * @param[in] size Number of bytes to write (maximum 4, must not |
|
| 3449 |
++ * cross 32bit boundaries) |
|
| 3450 |
++ */ |
|
| 3451 |
++void pe_dmem_write(int id, u32 val, u32 addr, u8 size) |
|
| 3452 |
++{
|
|
| 3453 |
++ u32 offset = addr & 0x3; |
|
| 3454 |
++ |
|
| 3455 |
++ addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_WRITE | |
|
| 3456 |
++ PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size); |
|
| 3457 |
++ |
|
| 3458 |
++ /* Indirect access interface is byte swapping data being written */ |
|
| 3459 |
++ writel(cpu_to_be32(val << (offset << 3)), pe[id].mem_access_wdata); |
|
| 3460 |
++ writel(addr, pe[id].mem_access_addr); |
|
| 3461 |
++} |
|
| 3462 |
++ |
|
| 3463 |
++/* Reads PE internal data memory (DMEM) from the host |
|
| 3464 |
++ * through indirect access registers. |
|
| 3465 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3466 |
++ * ..., UTIL_ID) |
|
| 3467 |
++ * @param[in] addr DMEM read address (must be aligned on size) |
|
| 3468 |
++ * @param[in] size Number of bytes to read (maximum 4, must not |
|
| 3469 |
++ * cross 32bit boundaries) |
|
| 3470 |
++ * @return the data read (in PE endianness, i.e BE). |
|
| 3471 |
++ */ |
|
| 3472 |
++u32 pe_dmem_read(int id, u32 addr, u8 size) |
|
| 3473 |
++{
|
|
| 3474 |
++ u32 offset = addr & 0x3; |
|
| 3475 |
++ u32 mask = 0xffffffff >> ((4 - size) << 3); |
|
| 3476 |
++ u32 val; |
|
| 3477 |
++ |
|
| 3478 |
++ addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_DMEM | |
|
| 3479 |
++ PE_MEM_ACCESS_BYTE_ENABLE(offset, size); |
|
| 3480 |
++ |
|
| 3481 |
++ writel(addr, pe[id].mem_access_addr); |
|
| 3482 |
++ |
|
| 3483 |
++ /* Indirect access interface is byte swapping data being read */ |
|
| 3484 |
++ val = be32_to_cpu(readl(pe[id].mem_access_rdata)); |
|
| 3485 |
++ |
|
| 3486 |
++ return (val >> (offset << 3)) & mask; |
|
| 3487 |
++} |
|
| 3488 |
++ |
|
| 3489 |
++/* This function is used to write to CLASS internal bus peripherals (ccu, |
|
| 3490 |
++ * pe-lem) from the host |
|
| 3491 |
++ * through indirect access registers. |
|
| 3492 |
++ * @param[in] val value to write |
|
| 3493 |
++ * @param[in] addr Address to write to (must be aligned on size) |
|
| 3494 |
++ * @param[in] size Number of bytes to write (1, 2 or 4) |
|
| 3495 |
++ * |
|
| 3496 |
++ */ |
|
| 3497 |
++void class_bus_write(u32 val, u32 addr, u8 size) |
|
| 3498 |
++{
|
|
| 3499 |
++ u32 offset = addr & 0x3; |
|
| 3500 |
++ |
|
| 3501 |
++ writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE); |
|
| 3502 |
++ |
|
| 3503 |
++ addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | PE_MEM_ACCESS_WRITE | |
|
| 3504 |
++ (size << 24); |
|
| 3505 |
++ |
|
| 3506 |
++ writel(cpu_to_be32(val << (offset << 3)), CLASS_BUS_ACCESS_WDATA); |
|
| 3507 |
++ writel(addr, CLASS_BUS_ACCESS_ADDR); |
|
| 3508 |
++} |
|
| 3509 |
++ |
|
| 3510 |
++/* Reads from CLASS internal bus peripherals (ccu, pe-lem) from the host |
|
| 3511 |
++ * through indirect access registers. |
|
| 3512 |
++ * @param[in] addr Address to read from (must be aligned on size) |
|
| 3513 |
++ * @param[in] size Number of bytes to read (1, 2 or 4) |
|
| 3514 |
++ * @return the read data |
|
| 3515 |
++ * |
|
| 3516 |
++ */ |
|
| 3517 |
++u32 class_bus_read(u32 addr, u8 size) |
|
| 3518 |
++{
|
|
| 3519 |
++ u32 offset = addr & 0x3; |
|
| 3520 |
++ u32 mask = 0xffffffff >> ((4 - size) << 3); |
|
| 3521 |
++ u32 val; |
|
| 3522 |
++ |
|
| 3523 |
++ writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE); |
|
| 3524 |
++ |
|
| 3525 |
++ addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | (size << 24); |
|
| 3526 |
++ |
|
| 3527 |
++ writel(addr, CLASS_BUS_ACCESS_ADDR); |
|
| 3528 |
++ val = be32_to_cpu(readl(CLASS_BUS_ACCESS_RDATA)); |
|
| 3529 |
++ |
|
| 3530 |
++ return (val >> (offset << 3)) & mask; |
|
| 3531 |
++} |
|
| 3532 |
++ |
|
| 3533 |
++/* Writes data to the cluster memory (PE_LMEM) |
|
| 3534 |
++ * @param[in] dst PE LMEM destination address (must be 32bit aligned) |
|
| 3535 |
++ * @param[in] src Buffer source address |
|
| 3536 |
++ * @param[in] len Number of bytes to copy |
|
| 3537 |
++ */ |
|
| 3538 |
++void class_pe_lmem_memcpy_to32(u32 dst, const void *src, unsigned int len) |
|
| 3539 |
++{
|
|
| 3540 |
++ u32 len32 = len >> 2; |
|
| 3541 |
++ int i; |
|
| 3542 |
++ |
|
| 3543 |
++ for (i = 0; i < len32; i++, src += 4, dst += 4) |
|
| 3544 |
++ class_bus_write(*(u32 *)src, dst, 4); |
|
| 3545 |
++ |
|
| 3546 |
++ if (len & 0x2) {
|
|
| 3547 |
++ class_bus_write(*(u16 *)src, dst, 2); |
|
| 3548 |
++ src += 2; |
|
| 3549 |
++ dst += 2; |
|
| 3550 |
++ } |
|
| 3551 |
++ |
|
| 3552 |
++ if (len & 0x1) {
|
|
| 3553 |
++ class_bus_write(*(u8 *)src, dst, 1); |
|
| 3554 |
++ src++; |
|
| 3555 |
++ dst++; |
|
| 3556 |
++ } |
|
| 3557 |
++} |
|
| 3558 |
++ |
|
| 3559 |
++/* Writes value to the cluster memory (PE_LMEM) |
|
| 3560 |
++ * @param[in] dst PE LMEM destination address (must be 32bit aligned) |
|
| 3561 |
++ * @param[in] val Value to write |
|
| 3562 |
++ * @param[in] len Number of bytes to write |
|
| 3563 |
++ */ |
|
| 3564 |
++void class_pe_lmem_memset(u32 dst, int val, unsigned int len) |
|
| 3565 |
++{
|
|
| 3566 |
++ u32 len32 = len >> 2; |
|
| 3567 |
++ int i; |
|
| 3568 |
++ |
|
| 3569 |
++ val = val | (val << 8) | (val << 16) | (val << 24); |
|
| 3570 |
++ |
|
| 3571 |
++ for (i = 0; i < len32; i++, dst += 4) |
|
| 3572 |
++ class_bus_write(val, dst, 4); |
|
| 3573 |
++ |
|
| 3574 |
++ if (len & 0x2) {
|
|
| 3575 |
++ class_bus_write(val, dst, 2); |
|
| 3576 |
++ dst += 2; |
|
| 3577 |
++ } |
|
| 3578 |
++ |
|
| 3579 |
++ if (len & 0x1) {
|
|
| 3580 |
++ class_bus_write(val, dst, 1); |
|
| 3581 |
++ dst++; |
|
| 3582 |
++ } |
|
| 3583 |
++} |
|
| 3584 |
++ |
|
| 3585 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3586 |
++ |
|
| 3587 |
++/* Writes UTIL program memory (DDR) from the host. |
|
| 3588 |
++ * |
|
| 3589 |
++ * @param[in] addr Address to write (virtual, must be aligned on size) |
|
| 3590 |
++ * @param[in] val Value to write (in PE endianness, i.e BE) |
|
| 3591 |
++ * @param[in] size Number of bytes to write (2 or 4) |
|
| 3592 |
++ */ |
|
| 3593 |
++static void util_pmem_write(u32 val, void *addr, u8 size) |
|
| 3594 |
++{
|
|
| 3595 |
++ void *addr64 = (void *)((unsigned long)addr & ~0x7); |
|
| 3596 |
++ unsigned long off = 8 - ((unsigned long)addr & 0x7) - size; |
|
| 3597 |
++ |
|
| 3598 |
++ /* |
|
| 3599 |
++ * IMEM should be loaded as a 64bit swapped value in a 64bit aligned |
|
| 3600 |
++ * location |
|
| 3601 |
++ */ |
|
| 3602 |
++ if (size == 4) |
|
| 3603 |
++ writel(be32_to_cpu(val), addr64 + off); |
|
| 3604 |
++ else |
|
| 3605 |
++ writew(be16_to_cpu((u16)val), addr64 + off); |
|
| 3606 |
++} |
|
| 3607 |
++ |
|
| 3608 |
++/* Writes a buffer to UTIL program memory (DDR) from the host. |
|
| 3609 |
++ * |
|
| 3610 |
++ * @param[in] dst Address to write (virtual, must be at least 16bit |
|
| 3611 |
++ * aligned) |
|
| 3612 |
++ * @param[in] src Buffer to write (in PE endianness, i.e BE, must have |
|
| 3613 |
++ * same alignment as dst) |
|
| 3614 |
++ * @param[in] len Number of bytes to write (must be at least 16bit |
|
| 3615 |
++ * aligned) |
|
| 3616 |
++ */ |
|
| 3617 |
++static void util_pmem_memcpy(void *dst, const void *src, unsigned int len) |
|
| 3618 |
++{
|
|
| 3619 |
++ unsigned int len32; |
|
| 3620 |
++ int i; |
|
| 3621 |
++ |
|
| 3622 |
++ if ((unsigned long)src & 0x2) {
|
|
| 3623 |
++ util_pmem_write(*(u16 *)src, dst, 2); |
|
| 3624 |
++ src += 2; |
|
| 3625 |
++ dst += 2; |
|
| 3626 |
++ len -= 2; |
|
| 3627 |
++ } |
|
| 3628 |
++ |
|
| 3629 |
++ len32 = len >> 2; |
|
| 3630 |
++ |
|
| 3631 |
++ for (i = 0; i < len32; i++, dst += 4, src += 4) |
|
| 3632 |
++ util_pmem_write(*(u32 *)src, dst, 4); |
|
| 3633 |
++ |
|
| 3634 |
++ if (len & 0x2) |
|
| 3635 |
++ util_pmem_write(*(u16 *)src, dst, len & 0x2); |
|
| 3636 |
++} |
|
| 3637 |
++#endif |
|
| 3638 |
++ |
|
| 3639 |
++/* Loads an elf section into pmem |
|
| 3640 |
++ * Code needs to be at least 16bit aligned and only PROGBITS sections are |
|
| 3641 |
++ * supported |
|
| 3642 |
++ * |
|
| 3643 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ..., |
|
| 3644 |
++ * TMU3_ID) |
|
| 3645 |
++ * @param[in] data pointer to the elf firmware |
|
| 3646 |
++ * @param[in] shdr pointer to the elf section header |
|
| 3647 |
++ * |
|
| 3648 |
++ */ |
|
| 3649 |
++static int pe_load_pmem_section(int id, const void *data, |
|
| 3650 |
++ struct elf32_shdr *shdr) |
|
| 3651 |
++{
|
|
| 3652 |
++ u32 offset = be32_to_cpu(shdr->sh_offset); |
|
| 3653 |
++ u32 addr = be32_to_cpu(shdr->sh_addr); |
|
| 3654 |
++ u32 size = be32_to_cpu(shdr->sh_size); |
|
| 3655 |
++ u32 type = be32_to_cpu(shdr->sh_type); |
|
| 3656 |
++ |
|
| 3657 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3658 |
++ if (id == UTIL_ID) {
|
|
| 3659 |
++ pr_err("%s: unsupported pmem section for UTIL\n",
|
|
| 3660 |
++ __func__); |
|
| 3661 |
++ return -EINVAL; |
|
| 3662 |
++ } |
|
| 3663 |
++#endif |
|
| 3664 |
++ |
|
| 3665 |
++ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
|
|
| 3666 |
++ pr_err( |
|
| 3667 |
++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" |
|
| 3668 |
++ , __func__, addr, (unsigned long)data + offset); |
|
| 3669 |
++ |
|
| 3670 |
++ return -EINVAL; |
|
| 3671 |
++ } |
|
| 3672 |
++ |
|
| 3673 |
++ if (addr & 0x1) {
|
|
| 3674 |
++ pr_err("%s: load address(%x) is not 16bit aligned\n",
|
|
| 3675 |
++ __func__, addr); |
|
| 3676 |
++ return -EINVAL; |
|
| 3677 |
++ } |
|
| 3678 |
++ |
|
| 3679 |
++ if (size & 0x1) {
|
|
| 3680 |
++ pr_err("%s: load size(%x) is not 16bit aligned\n",
|
|
| 3681 |
++ __func__, size); |
|
| 3682 |
++ return -EINVAL; |
|
| 3683 |
++ } |
|
| 3684 |
++ |
|
| 3685 |
++ switch (type) {
|
|
| 3686 |
++ case SHT_PROGBITS: |
|
| 3687 |
++ pe_pmem_memcpy_to32(id, addr, data + offset, size); |
|
| 3688 |
++ |
|
| 3689 |
++ break; |
|
| 3690 |
++ |
|
| 3691 |
++ default: |
|
| 3692 |
++ pr_err("%s: unsupported section type(%x)\n", __func__,
|
|
| 3693 |
++ type); |
|
| 3694 |
++ return -EINVAL; |
|
| 3695 |
++ } |
|
| 3696 |
++ |
|
| 3697 |
++ return 0; |
|
| 3698 |
++} |
|
| 3699 |
++ |
|
| 3700 |
++/* Loads an elf section into dmem |
|
| 3701 |
++ * Data needs to be at least 32bit aligned, NOBITS sections are correctly |
|
| 3702 |
++ * initialized to 0 |
|
| 3703 |
++ * |
|
| 3704 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3705 |
++ * ..., UTIL_ID) |
|
| 3706 |
++ * @param[in] data pointer to the elf firmware |
|
| 3707 |
++ * @param[in] shdr pointer to the elf section header |
|
| 3708 |
++ * |
|
| 3709 |
++ */ |
|
| 3710 |
++static int pe_load_dmem_section(int id, const void *data, |
|
| 3711 |
++ struct elf32_shdr *shdr) |
|
| 3712 |
++{
|
|
| 3713 |
++ u32 offset = be32_to_cpu(shdr->sh_offset); |
|
| 3714 |
++ u32 addr = be32_to_cpu(shdr->sh_addr); |
|
| 3715 |
++ u32 size = be32_to_cpu(shdr->sh_size); |
|
| 3716 |
++ u32 type = be32_to_cpu(shdr->sh_type); |
|
| 3717 |
++ u32 size32 = size >> 2; |
|
| 3718 |
++ int i; |
|
| 3719 |
++ |
|
| 3720 |
++ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
|
|
| 3721 |
++ pr_err( |
|
| 3722 |
++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", |
|
| 3723 |
++ __func__, addr, (unsigned long)data + offset); |
|
| 3724 |
++ |
|
| 3725 |
++ return -EINVAL; |
|
| 3726 |
++ } |
|
| 3727 |
++ |
|
| 3728 |
++ if (addr & 0x3) {
|
|
| 3729 |
++ pr_err("%s: load address(%x) is not 32bit aligned\n",
|
|
| 3730 |
++ __func__, addr); |
|
| 3731 |
++ return -EINVAL; |
|
| 3732 |
++ } |
|
| 3733 |
++ |
|
| 3734 |
++ switch (type) {
|
|
| 3735 |
++ case SHT_PROGBITS: |
|
| 3736 |
++ pe_dmem_memcpy_to32(id, addr, data + offset, size); |
|
| 3737 |
++ break; |
|
| 3738 |
++ |
|
| 3739 |
++ case SHT_NOBITS: |
|
| 3740 |
++ for (i = 0; i < size32; i++, addr += 4) |
|
| 3741 |
++ pe_dmem_write(id, 0, addr, 4); |
|
| 3742 |
++ |
|
| 3743 |
++ if (size & 0x3) |
|
| 3744 |
++ pe_dmem_write(id, 0, addr, size & 0x3); |
|
| 3745 |
++ |
|
| 3746 |
++ break; |
|
| 3747 |
++ |
|
| 3748 |
++ default: |
|
| 3749 |
++ pr_err("%s: unsupported section type(%x)\n", __func__,
|
|
| 3750 |
++ type); |
|
| 3751 |
++ return -EINVAL; |
|
| 3752 |
++ } |
|
| 3753 |
++ |
|
| 3754 |
++ return 0; |
|
| 3755 |
++} |
|
| 3756 |
++ |
|
| 3757 |
++/* Loads an elf section into DDR |
|
| 3758 |
++ * Data needs to be at least 32bit aligned, NOBITS sections are correctly |
|
| 3759 |
++ * initialized to 0 |
|
| 3760 |
++ * |
|
| 3761 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3762 |
++ * ..., UTIL_ID) |
|
| 3763 |
++ * @param[in] data pointer to the elf firmware |
|
| 3764 |
++ * @param[in] shdr pointer to the elf section header |
|
| 3765 |
++ * |
|
| 3766 |
++ */ |
|
| 3767 |
++static int pe_load_ddr_section(int id, const void *data, |
|
| 3768 |
++ struct elf32_shdr *shdr, |
|
| 3769 |
++ struct device *dev) {
|
|
| 3770 |
++ u32 offset = be32_to_cpu(shdr->sh_offset); |
|
| 3771 |
++ u32 addr = be32_to_cpu(shdr->sh_addr); |
|
| 3772 |
++ u32 size = be32_to_cpu(shdr->sh_size); |
|
| 3773 |
++ u32 type = be32_to_cpu(shdr->sh_type); |
|
| 3774 |
++ u32 flags = be32_to_cpu(shdr->sh_flags); |
|
| 3775 |
++ |
|
| 3776 |
++ switch (type) {
|
|
| 3777 |
++ case SHT_PROGBITS: |
|
| 3778 |
++ if (flags & SHF_EXECINSTR) {
|
|
| 3779 |
++ if (id <= CLASS_MAX_ID) {
|
|
| 3780 |
++ /* DO the loading only once in DDR */ |
|
| 3781 |
++ if (id == CLASS0_ID) {
|
|
| 3782 |
++ pr_err( |
|
| 3783 |
++ "%s: load address(%x) and elf file address(%lx) rcvd\n", |
|
| 3784 |
++ __func__, addr, |
|
| 3785 |
++ (unsigned long)data + offset); |
|
| 3786 |
++ if (((unsigned long)(data + offset) |
|
| 3787 |
++ & 0x3) != (addr & 0x3)) {
|
|
| 3788 |
++ pr_err( |
|
| 3789 |
++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" |
|
| 3790 |
++ , __func__, addr, |
|
| 3791 |
++ (unsigned long)data + offset); |
|
| 3792 |
++ |
|
| 3793 |
++ return -EINVAL; |
|
| 3794 |
++ } |
|
| 3795 |
++ |
|
| 3796 |
++ if (addr & 0x1) {
|
|
| 3797 |
++ pr_err( |
|
| 3798 |
++ "%s: load address(%x) is not 16bit aligned\n" |
|
| 3799 |
++ , __func__, addr); |
|
| 3800 |
++ return -EINVAL; |
|
| 3801 |
++ } |
|
| 3802 |
++ |
|
| 3803 |
++ if (size & 0x1) {
|
|
| 3804 |
++ pr_err( |
|
| 3805 |
++ "%s: load length(%x) is not 16bit aligned\n" |
|
| 3806 |
++ , __func__, size); |
|
| 3807 |
++ return -EINVAL; |
|
| 3808 |
++ } |
|
| 3809 |
++ memcpy(DDR_PHYS_TO_VIRT( |
|
| 3810 |
++ DDR_PFE_TO_PHYS(addr)), |
|
| 3811 |
++ data + offset, size); |
|
| 3812 |
++ } |
|
| 3813 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 3814 |
++ } else if (id == UTIL_ID) {
|
|
| 3815 |
++ if (((unsigned long)(data + offset) & 0x3) |
|
| 3816 |
++ != (addr & 0x3)) {
|
|
| 3817 |
++ pr_err( |
|
| 3818 |
++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" |
|
| 3819 |
++ , __func__, addr, |
|
| 3820 |
++ (unsigned long)data + offset); |
|
| 3821 |
++ |
|
| 3822 |
++ return -EINVAL; |
|
| 3823 |
++ } |
|
| 3824 |
++ |
|
| 3825 |
++ if (addr & 0x1) {
|
|
| 3826 |
++ pr_err( |
|
| 3827 |
++ "%s: load address(%x) is not 16bit aligned\n" |
|
| 3828 |
++ , __func__, addr); |
|
| 3829 |
++ return -EINVAL; |
|
| 3830 |
++ } |
|
| 3831 |
++ |
|
| 3832 |
++ if (size & 0x1) {
|
|
| 3833 |
++ pr_err( |
|
| 3834 |
++ "%s: load length(%x) is not 16bit aligned\n" |
|
| 3835 |
++ , __func__, size); |
|
| 3836 |
++ return -EINVAL; |
|
| 3837 |
++ } |
|
| 3838 |
++ |
|
| 3839 |
++ util_pmem_memcpy(DDR_PHYS_TO_VIRT( |
|
| 3840 |
++ DDR_PFE_TO_PHYS(addr)), |
|
| 3841 |
++ data + offset, size); |
|
| 3842 |
++ } |
|
| 3843 |
++#endif |
|
| 3844 |
++ } else {
|
|
| 3845 |
++ pr_err( |
|
| 3846 |
++ "%s: unsupported ddr section type(%x) for PE(%d)\n" |
|
| 3847 |
++ , __func__, type, id); |
|
| 3848 |
++ return -EINVAL; |
|
| 3849 |
++ } |
|
| 3850 |
++ |
|
| 3851 |
++ } else {
|
|
| 3852 |
++ memcpy(DDR_PHYS_TO_VIRT(DDR_PFE_TO_PHYS(addr)), data |
|
| 3853 |
++ + offset, size); |
|
| 3854 |
++ } |
|
| 3855 |
++ |
|
| 3856 |
++ break; |
|
| 3857 |
++ |
|
| 3858 |
++ case SHT_NOBITS: |
|
| 3859 |
++ memset(DDR_PHYS_TO_VIRT(DDR_PFE_TO_PHYS(addr)), 0, size); |
|
| 3860 |
++ |
|
| 3861 |
++ break; |
|
| 3862 |
++ |
|
| 3863 |
++ default: |
|
| 3864 |
++ pr_err("%s: unsupported section type(%x)\n", __func__,
|
|
| 3865 |
++ type); |
|
| 3866 |
++ return -EINVAL; |
|
| 3867 |
++ } |
|
| 3868 |
++ |
|
| 3869 |
++ return 0; |
|
| 3870 |
++} |
|
| 3871 |
++ |
|
| 3872 |
++/* Loads an elf section into pe lmem |
|
| 3873 |
++ * Data needs to be at least 32bit aligned, NOBITS sections are correctly |
|
| 3874 |
++ * initialized to 0 |
|
| 3875 |
++ * |
|
| 3876 |
++ * @param[in] id PE identification (CLASS0_ID,..., CLASS5_ID) |
|
| 3877 |
++ * @param[in] data pointer to the elf firmware |
|
| 3878 |
++ * @param[in] shdr pointer to the elf section header |
|
| 3879 |
++ * |
|
| 3880 |
++ */ |
|
| 3881 |
++static int pe_load_pe_lmem_section(int id, const void *data, |
|
| 3882 |
++ struct elf32_shdr *shdr) |
|
| 3883 |
++{
|
|
| 3884 |
++ u32 offset = be32_to_cpu(shdr->sh_offset); |
|
| 3885 |
++ u32 addr = be32_to_cpu(shdr->sh_addr); |
|
| 3886 |
++ u32 size = be32_to_cpu(shdr->sh_size); |
|
| 3887 |
++ u32 type = be32_to_cpu(shdr->sh_type); |
|
| 3888 |
++ |
|
| 3889 |
++ if (id > CLASS_MAX_ID) {
|
|
| 3890 |
++ pr_err( |
|
| 3891 |
++ "%s: unsupported pe-lmem section type(%x) for PE(%d)\n", |
|
| 3892 |
++ __func__, type, id); |
|
| 3893 |
++ return -EINVAL; |
|
| 3894 |
++ } |
|
| 3895 |
++ |
|
| 3896 |
++ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
|
|
| 3897 |
++ pr_err( |
|
| 3898 |
++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", |
|
| 3899 |
++ __func__, addr, (unsigned long)data + offset); |
|
| 3900 |
++ |
|
| 3901 |
++ return -EINVAL; |
|
| 3902 |
++ } |
|
| 3903 |
++ |
|
| 3904 |
++ if (addr & 0x3) {
|
|
| 3905 |
++ pr_err("%s: load address(%x) is not 32bit aligned\n",
|
|
| 3906 |
++ __func__, addr); |
|
| 3907 |
++ return -EINVAL; |
|
| 3908 |
++ } |
|
| 3909 |
++ |
|
| 3910 |
++ switch (type) {
|
|
| 3911 |
++ case SHT_PROGBITS: |
|
| 3912 |
++ class_pe_lmem_memcpy_to32(addr, data + offset, size); |
|
| 3913 |
++ break; |
|
| 3914 |
++ |
|
| 3915 |
++ case SHT_NOBITS: |
|
| 3916 |
++ class_pe_lmem_memset(addr, 0, size); |
|
| 3917 |
++ break; |
|
| 3918 |
++ |
|
| 3919 |
++ default: |
|
| 3920 |
++ pr_err("%s: unsupported section type(%x)\n", __func__,
|
|
| 3921 |
++ type); |
|
| 3922 |
++ return -EINVAL; |
|
| 3923 |
++ } |
|
| 3924 |
++ |
|
| 3925 |
++ return 0; |
|
| 3926 |
++} |
|
| 3927 |
++ |
|
| 3928 |
++/* Loads an elf section into a PE |
|
| 3929 |
++ * For now only supports loading a section to dmem (all PE's), pmem (class and |
|
| 3930 |
++ * tmu PE's), |
|
| 3931 |
++ * DDDR (util PE code) |
|
| 3932 |
++ * |
|
| 3933 |
++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, |
|
| 3934 |
++ * ..., UTIL_ID) |
|
| 3935 |
++ * @param[in] data pointer to the elf firmware |
|
| 3936 |
++ * @param[in] shdr pointer to the elf section header |
|
| 3937 |
++ * |
|
| 3938 |
++ */ |
|
| 3939 |
++int pe_load_elf_section(int id, const void *data, struct elf32_shdr *shdr, |
|
| 3940 |
++ struct device *dev) {
|
|
| 3941 |
++ u32 addr = be32_to_cpu(shdr->sh_addr); |
|
| 3942 |
++ u32 size = be32_to_cpu(shdr->sh_size); |
|
| 3943 |
++ |
|
| 3944 |
++ if (IS_DMEM(addr, size)) |
|
| 3945 |
++ return pe_load_dmem_section(id, data, shdr); |
|
| 3946 |
++ else if (IS_PMEM(addr, size)) |
|
| 3947 |
++ return pe_load_pmem_section(id, data, shdr); |
|
| 3948 |
++ else if (IS_PFE_LMEM(addr, size)) |
|
| 3949 |
++ return 0; |
|
| 3950 |
++ else if (IS_PHYS_DDR(addr, size)) |
|
| 3951 |
++ return pe_load_ddr_section(id, data, shdr, dev); |
|
| 3952 |
++ else if (IS_PE_LMEM(addr, size)) |
|
| 3953 |
++ return pe_load_pe_lmem_section(id, data, shdr); |
|
| 3954 |
++ |
|
| 3955 |
++ pr_err("%s: unsupported memory range(%x)\n", __func__,
|
|
| 3956 |
++ addr); |
|
| 3957 |
++ return 0; |
|
| 3958 |
++} |
|
| 3959 |
++ |
|
| 3960 |
++/**************************** BMU ***************************/ |
|
| 3961 |
++ |
|
| 3962 |
++/* Initializes a BMU block. |
|
| 3963 |
++ * @param[in] base BMU block base address |
|
| 3964 |
++ * @param[in] cfg BMU configuration |
|
| 3965 |
++ */ |
|
| 3966 |
++void bmu_init(void *base, struct BMU_CFG *cfg) |
|
| 3967 |
++{
|
|
| 3968 |
++ bmu_disable(base); |
|
| 3969 |
++ |
|
| 3970 |
++ bmu_set_config(base, cfg); |
|
| 3971 |
++ |
|
| 3972 |
++ bmu_reset(base); |
|
| 3973 |
++} |
|
| 3974 |
++ |
|
| 3975 |
++/* Resets a BMU block. |
|
| 3976 |
++ * @param[in] base BMU block base address |
|
| 3977 |
++ */ |
|
| 3978 |
++void bmu_reset(void *base) |
|
| 3979 |
++{
|
|
| 3980 |
++ writel(CORE_SW_RESET, base + BMU_CTRL); |
|
| 3981 |
++ |
|
| 3982 |
++ /* Wait for self clear */ |
|
| 3983 |
++ while (readl(base + BMU_CTRL) & CORE_SW_RESET) |
|
| 3984 |
++ ; |
|
| 3985 |
++} |
|
| 3986 |
++ |
|
| 3987 |
++/* Enabled a BMU block. |
|
| 3988 |
++ * @param[in] base BMU block base address |
|
| 3989 |
++ */ |
|
| 3990 |
++void bmu_enable(void *base) |
|
| 3991 |
++{
|
|
| 3992 |
++ writel(CORE_ENABLE, base + BMU_CTRL); |
|
| 3993 |
++} |
|
| 3994 |
++ |
|
| 3995 |
++/* Disables a BMU block. |
|
| 3996 |
++ * @param[in] base BMU block base address |
|
| 3997 |
++ */ |
|
| 3998 |
++void bmu_disable(void *base) |
|
| 3999 |
++{
|
|
| 4000 |
++ writel(CORE_DISABLE, base + BMU_CTRL); |
|
| 4001 |
++} |
|
| 4002 |
++ |
|
| 4003 |
++/* Sets the configuration of a BMU block. |
|
| 4004 |
++ * @param[in] base BMU block base address |
|
| 4005 |
++ * @param[in] cfg BMU configuration |
|
| 4006 |
++ */ |
|
| 4007 |
++void bmu_set_config(void *base, struct BMU_CFG *cfg) |
|
| 4008 |
++{
|
|
| 4009 |
++ writel(cfg->baseaddr, base + BMU_UCAST_BASE_ADDR); |
|
| 4010 |
++ writel(cfg->count & 0xffff, base + BMU_UCAST_CONFIG); |
|
| 4011 |
++ writel(cfg->size & 0xffff, base + BMU_BUF_SIZE); |
|
| 4012 |
++ |
|
| 4013 |
++ /* Interrupts are never used */ |
|
| 4014 |
++ writel(cfg->low_watermark, base + BMU_LOW_WATERMARK); |
|
| 4015 |
++ writel(cfg->high_watermark, base + BMU_HIGH_WATERMARK); |
|
| 4016 |
++ writel(0x0, base + BMU_INT_ENABLE); |
|
| 4017 |
++} |
|
| 4018 |
++ |
|
| 4019 |
++/**************************** MTIP GEMAC ***************************/ |
|
| 4020 |
++ |
|
| 4021 |
++/* Enable Rx Checksum Engine. With this enabled, Frame with bad IP, |
|
| 4022 |
++ * TCP or UDP checksums are discarded |
|
| 4023 |
++ * |
|
| 4024 |
++ * @param[in] base GEMAC base address. |
|
| 4025 |
++ */ |
|
| 4026 |
++void gemac_enable_rx_checksum_offload(void *base) |
|
| 4027 |
++{
|
|
| 4028 |
++ /*Do not find configuration to do this */ |
|
| 4029 |
++} |
|
| 4030 |
++ |
|
| 4031 |
++/* Disable Rx Checksum Engine. |
|
| 4032 |
++ * |
|
| 4033 |
++ * @param[in] base GEMAC base address. |
|
| 4034 |
++ */ |
|
| 4035 |
++void gemac_disable_rx_checksum_offload(void *base) |
|
| 4036 |
++{
|
|
| 4037 |
++ /*Do not find configuration to do this */ |
|
| 4038 |
++} |
|
| 4039 |
++ |
|
| 4040 |
++/* GEMAC set speed. |
|
| 4041 |
++ * @param[in] base GEMAC base address |
|
| 4042 |
++ * @param[in] speed GEMAC speed (10, 100 or 1000 Mbps) |
|
| 4043 |
++ */ |
|
| 4044 |
++void gemac_set_speed(void *base, enum mac_speed gem_speed) |
|
| 4045 |
++{
|
|
| 4046 |
++ u32 ecr = readl(base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_SPEED; |
|
| 4047 |
++ u32 rcr = readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_RMII_10T; |
|
| 4048 |
++ |
|
| 4049 |
++ switch (gem_speed) {
|
|
| 4050 |
++ case SPEED_10M: |
|
| 4051 |
++ rcr |= EMAC_RCNTRL_RMII_10T; |
|
| 4052 |
++ break; |
|
| 4053 |
++ |
|
| 4054 |
++ case SPEED_1000M: |
|
| 4055 |
++ ecr |= EMAC_ECNTRL_SPEED; |
|
| 4056 |
++ break; |
|
| 4057 |
++ |
|
| 4058 |
++ case SPEED_100M: |
|
| 4059 |
++ default: |
|
| 4060 |
++ /*It is in 100M mode */ |
|
| 4061 |
++ break; |
|
| 4062 |
++ } |
|
| 4063 |
++ writel(ecr, (base + EMAC_ECNTRL_REG)); |
|
| 4064 |
++ writel(rcr, (base + EMAC_RCNTRL_REG)); |
|
| 4065 |
++} |
|
| 4066 |
++ |
|
| 4067 |
++/* GEMAC set duplex. |
|
| 4068 |
++ * @param[in] base GEMAC base address |
|
| 4069 |
++ * @param[in] duplex GEMAC duplex mode (Full, Half) |
|
| 4070 |
++ */ |
|
| 4071 |
++void gemac_set_duplex(void *base, int duplex) |
|
| 4072 |
++{
|
|
| 4073 |
++ if (duplex == DUPLEX_HALF) {
|
|
| 4074 |
++ writel(readl(base + EMAC_TCNTRL_REG) & ~EMAC_TCNTRL_FDEN, base |
|
| 4075 |
++ + EMAC_TCNTRL_REG); |
|
| 4076 |
++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_DRT, (base |
|
| 4077 |
++ + EMAC_RCNTRL_REG)); |
|
| 4078 |
++ } else{
|
|
| 4079 |
++ writel(readl(base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_FDEN, base |
|
| 4080 |
++ + EMAC_TCNTRL_REG); |
|
| 4081 |
++ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_DRT, (base |
|
| 4082 |
++ + EMAC_RCNTRL_REG)); |
|
| 4083 |
++ } |
|
| 4084 |
++} |
|
| 4085 |
++ |
|
| 4086 |
++/* GEMAC set mode. |
|
| 4087 |
++ * @param[in] base GEMAC base address |
|
| 4088 |
++ * @param[in] mode GEMAC operation mode (MII, RMII, RGMII, SGMII) |
|
| 4089 |
++ */ |
|
| 4090 |
++void gemac_set_mode(void *base, int mode) |
|
| 4091 |
++{
|
|
| 4092 |
++ u32 val = readl(base + EMAC_RCNTRL_REG); |
|
| 4093 |
++ |
|
| 4094 |
++ /*Remove loopbank*/ |
|
| 4095 |
++ val &= ~EMAC_RCNTRL_LOOP; |
|
| 4096 |
++ |
|
| 4097 |
++ /*Enable flow control and MII mode*/ |
|
| 4098 |
++ val |= (EMAC_RCNTRL_FCE | EMAC_RCNTRL_MII_MODE); |
|
| 4099 |
++ |
|
| 4100 |
++ writel(val, base + EMAC_RCNTRL_REG); |
|
| 4101 |
++} |
|
| 4102 |
++ |
|
| 4103 |
++/* GEMAC enable function. |
|
| 4104 |
++ * @param[in] base GEMAC base address |
|
| 4105 |
++ */ |
|
| 4106 |
++void gemac_enable(void *base) |
|
| 4107 |
++{
|
|
| 4108 |
++ writel(readl(base + EMAC_ECNTRL_REG) | EMAC_ECNTRL_ETHER_EN, base + |
|
| 4109 |
++ EMAC_ECNTRL_REG); |
|
| 4110 |
++} |
|
| 4111 |
++ |
|
| 4112 |
++/* GEMAC disable function. |
|
| 4113 |
++ * @param[in] base GEMAC base address |
|
| 4114 |
++ */ |
|
| 4115 |
++void gemac_disable(void *base) |
|
| 4116 |
++{
|
|
| 4117 |
++ writel(readl(base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_ETHER_EN, base + |
|
| 4118 |
++ EMAC_ECNTRL_REG); |
|
| 4119 |
++} |
|
| 4120 |
++ |
|
| 4121 |
++/* GEMAC TX disable function. |
|
| 4122 |
++ * @param[in] base GEMAC base address |
|
| 4123 |
++ */ |
|
| 4124 |
++void gemac_tx_disable(void *base) |
|
| 4125 |
++{
|
|
| 4126 |
++ writel(readl(base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_GTS, base + |
|
| 4127 |
++ EMAC_TCNTRL_REG); |
|
| 4128 |
++} |
|
| 4129 |
++ |
|
| 4130 |
++void gemac_tx_enable(void *base) |
|
| 4131 |
++{
|
|
| 4132 |
++ writel(readl(base + EMAC_TCNTRL_REG) & ~EMAC_TCNTRL_GTS, base + |
|
| 4133 |
++ EMAC_TCNTRL_REG); |
|
| 4134 |
++} |
|
| 4135 |
++ |
|
| 4136 |
++/* Sets the hash register of the MAC. |
|
| 4137 |
++ * This register is used for matching unicast and multicast frames. |
|
| 4138 |
++ * |
|
| 4139 |
++ * @param[in] base GEMAC base address. |
|
| 4140 |
++ * @param[in] hash 64-bit hash to be configured. |
|
| 4141 |
++ */ |
|
| 4142 |
++void gemac_set_hash(void *base, struct pfe_mac_addr *hash) |
|
| 4143 |
++{
|
|
| 4144 |
++ writel(hash->bottom, base + EMAC_GALR); |
|
| 4145 |
++ writel(hash->top, base + EMAC_GAUR); |
|
| 4146 |
++} |
|
| 4147 |
++ |
|
| 4148 |
++void gemac_set_laddrN(void *base, struct pfe_mac_addr *address, |
|
| 4149 |
++ unsigned int entry_index) |
|
| 4150 |
++{
|
|
| 4151 |
++ if ((entry_index < 1) || (entry_index > EMAC_SPEC_ADDR_MAX)) |
|
| 4152 |
++ return; |
|
| 4153 |
++ |
|
| 4154 |
++ entry_index = entry_index - 1; |
|
| 4155 |
++ if (entry_index < 1) {
|
|
| 4156 |
++ writel(htonl(address->bottom), base + EMAC_PHY_ADDR_LOW); |
|
| 4157 |
++ writel((htonl(address->top) | 0x8808), base + |
|
| 4158 |
++ EMAC_PHY_ADDR_HIGH); |
|
| 4159 |
++ } else {
|
|
| 4160 |
++ writel(htonl(address->bottom), base + ((entry_index - 1) * 8) |
|
| 4161 |
++ + EMAC_SMAC_0_0); |
|
| 4162 |
++ writel((htonl(address->top) | 0x8808), base + ((entry_index - |
|
| 4163 |
++ 1) * 8) + EMAC_SMAC_0_1); |
|
| 4164 |
++ } |
|
| 4165 |
++} |
|
| 4166 |
++ |
|
| 4167 |
++void gemac_clear_laddrN(void *base, unsigned int entry_index) |
|
| 4168 |
++{
|
|
| 4169 |
++ if ((entry_index < 1) || (entry_index > EMAC_SPEC_ADDR_MAX)) |
|
| 4170 |
++ return; |
|
| 4171 |
++ |
|
| 4172 |
++ entry_index = entry_index - 1; |
|
| 4173 |
++ if (entry_index < 1) {
|
|
| 4174 |
++ writel(0, base + EMAC_PHY_ADDR_LOW); |
|
| 4175 |
++ writel(0, base + EMAC_PHY_ADDR_HIGH); |
|
| 4176 |
++ } else {
|
|
| 4177 |
++ writel(0, base + ((entry_index - 1) * 8) + EMAC_SMAC_0_0); |
|
| 4178 |
++ writel(0, base + ((entry_index - 1) * 8) + EMAC_SMAC_0_1); |
|
| 4179 |
++ } |
|
| 4180 |
++} |
|
| 4181 |
++ |
|
| 4182 |
++/* Set the loopback mode of the MAC. This can be either no loopback for |
|
| 4183 |
++ * normal operation, local loopback through MAC internal loopback module or PHY |
|
| 4184 |
++ * loopback for external loopback through a PHY. This asserts the external |
|
| 4185 |
++ * loop pin. |
|
| 4186 |
++ * |
|
| 4187 |
++ * @param[in] base GEMAC base address. |
|
| 4188 |
++ * @param[in] gem_loop Loopback mode to be enabled. LB_LOCAL - MAC |
|
| 4189 |
++ * Loopback, |
|
| 4190 |
++ * LB_EXT - PHY Loopback. |
|
| 4191 |
++ */ |
|
| 4192 |
++void gemac_set_loop(void *base, enum mac_loop gem_loop) |
|
| 4193 |
++{
|
|
| 4194 |
++ pr_info("%s()\n", __func__);
|
|
| 4195 |
++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_LOOP, (base + |
|
| 4196 |
++ EMAC_RCNTRL_REG)); |
|
| 4197 |
++} |
|
| 4198 |
++ |
|
| 4199 |
++/* GEMAC allow frames |
|
| 4200 |
++ * @param[in] base GEMAC base address |
|
| 4201 |
++ */ |
|
| 4202 |
++void gemac_enable_copy_all(void *base) |
|
| 4203 |
++{
|
|
| 4204 |
++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_PROM, (base + |
|
| 4205 |
++ EMAC_RCNTRL_REG)); |
|
| 4206 |
++} |
|
| 4207 |
++ |
|
| 4208 |
++/* GEMAC do not allow frames |
|
| 4209 |
++ * @param[in] base GEMAC base address |
|
| 4210 |
++ */ |
|
| 4211 |
++void gemac_disable_copy_all(void *base) |
|
| 4212 |
++{
|
|
| 4213 |
++ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_PROM, (base + |
|
| 4214 |
++ EMAC_RCNTRL_REG)); |
|
| 4215 |
++} |
|
| 4216 |
++ |
|
| 4217 |
++/* GEMAC allow broadcast function. |
|
| 4218 |
++ * @param[in] base GEMAC base address |
|
| 4219 |
++ */ |
|
| 4220 |
++void gemac_allow_broadcast(void *base) |
|
| 4221 |
++{
|
|
| 4222 |
++ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_BC_REJ, base + |
|
| 4223 |
++ EMAC_RCNTRL_REG); |
|
| 4224 |
++} |
|
| 4225 |
++ |
|
| 4226 |
++/* GEMAC no broadcast function. |
|
| 4227 |
++ * @param[in] base GEMAC base address |
|
| 4228 |
++ */ |
|
| 4229 |
++void gemac_no_broadcast(void *base) |
|
| 4230 |
++{
|
|
| 4231 |
++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_BC_REJ, base + |
|
| 4232 |
++ EMAC_RCNTRL_REG); |
|
| 4233 |
++} |
|
| 4234 |
++ |
|
| 4235 |
++/* GEMAC enable 1536 rx function. |
|
| 4236 |
++ * @param[in] base GEMAC base address |
|
| 4237 |
++ */ |
|
| 4238 |
++void gemac_enable_1536_rx(void *base) |
|
| 4239 |
++{
|
|
| 4240 |
++ /* Set 1536 as Maximum frame length */ |
|
| 4241 |
++ writel(readl(base + EMAC_RCNTRL_REG) | (1536 << 16), base + |
|
| 4242 |
++ EMAC_RCNTRL_REG); |
|
| 4243 |
++} |
|
| 4244 |
++ |
|
| 4245 |
++/* GEMAC enable jumbo function. |
|
| 4246 |
++ * @param[in] base GEMAC base address |
|
| 4247 |
++ */ |
|
| 4248 |
++void gemac_enable_rx_jmb(void *base) |
|
| 4249 |
++{
|
|
| 4250 |
++ writel(readl(base + EMAC_RCNTRL_REG) | (JUMBO_FRAME_SIZE << 16), base |
|
| 4251 |
++ + EMAC_RCNTRL_REG); |
|
| 4252 |
++} |
|
| 4253 |
++ |
|
| 4254 |
++/* GEMAC enable stacked vlan function. |
|
| 4255 |
++ * @param[in] base GEMAC base address |
|
| 4256 |
++ */ |
|
| 4257 |
++void gemac_enable_stacked_vlan(void *base) |
|
| 4258 |
++{
|
|
| 4259 |
++ /* MTIP doesn't support stacked vlan */ |
|
| 4260 |
++} |
|
| 4261 |
++ |
|
| 4262 |
++/* GEMAC enable pause rx function. |
|
| 4263 |
++ * @param[in] base GEMAC base address |
|
| 4264 |
++ */ |
|
| 4265 |
++void gemac_enable_pause_rx(void *base) |
|
| 4266 |
++{
|
|
| 4267 |
++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_FCE, |
|
| 4268 |
++ base + EMAC_RCNTRL_REG); |
|
| 4269 |
++} |
|
| 4270 |
++ |
|
| 4271 |
++/* GEMAC disable pause rx function. |
|
| 4272 |
++ * @param[in] base GEMAC base address |
|
| 4273 |
++ */ |
|
| 4274 |
++void gemac_disable_pause_rx(void *base) |
|
| 4275 |
++{
|
|
| 4276 |
++ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_FCE, |
|
| 4277 |
++ base + EMAC_RCNTRL_REG); |
|
| 4278 |
++} |
|
| 4279 |
++ |
|
| 4280 |
++/* GEMAC enable pause tx function. |
|
| 4281 |
++ * @param[in] base GEMAC base address |
|
| 4282 |
++ */ |
|
| 4283 |
++void gemac_enable_pause_tx(void *base) |
|
| 4284 |
++{
|
|
| 4285 |
++ writel(EMAC_RX_SECTION_EMPTY_V, base + EMAC_RX_SECTION_EMPTY); |
|
| 4286 |
++} |
|
| 4287 |
++ |
|
| 4288 |
++/* GEMAC disable pause tx function. |
|
| 4289 |
++ * @param[in] base GEMAC base address |
|
| 4290 |
++ */ |
|
| 4291 |
++void gemac_disable_pause_tx(void *base) |
|
| 4292 |
++{
|
|
| 4293 |
++ writel(0x0, base + EMAC_RX_SECTION_EMPTY); |
|
| 4294 |
++} |
|
| 4295 |
++ |
|
| 4296 |
++/* GEMAC wol configuration |
|
| 4297 |
++ * @param[in] base GEMAC base address |
|
| 4298 |
++ * @param[in] wol_conf WoL register configuration |
|
| 4299 |
++ */ |
|
| 4300 |
++void gemac_set_wol(void *base, u32 wol_conf) |
|
| 4301 |
++{
|
|
| 4302 |
++ u32 val = readl(base + EMAC_ECNTRL_REG); |
|
| 4303 |
++ |
|
| 4304 |
++ if (wol_conf) |
|
| 4305 |
++ val |= (EMAC_ECNTRL_MAGIC_ENA | EMAC_ECNTRL_SLEEP); |
|
| 4306 |
++ else |
|
| 4307 |
++ val &= ~(EMAC_ECNTRL_MAGIC_ENA | EMAC_ECNTRL_SLEEP); |
|
| 4308 |
++ writel(val, base + EMAC_ECNTRL_REG); |
|
| 4309 |
++} |
|
| 4310 |
++ |
|
| 4311 |
++/* Sets Gemac bus width to 64bit |
|
| 4312 |
++ * @param[in] base GEMAC base address |
|
| 4313 |
++ * @param[in] width gemac bus width to be set possible values are 32/64/128 |
|
| 4314 |
++ */ |
|
| 4315 |
++void gemac_set_bus_width(void *base, int width) |
|
| 4316 |
++{
|
|
| 4317 |
++} |
|
| 4318 |
++ |
|
| 4319 |
++/* Sets Gemac configuration. |
|
| 4320 |
++ * @param[in] base GEMAC base address |
|
| 4321 |
++ * @param[in] cfg GEMAC configuration |
|
| 4322 |
++ */ |
|
| 4323 |
++void gemac_set_config(void *base, struct gemac_cfg *cfg) |
|
| 4324 |
++{
|
|
| 4325 |
++ /*GEMAC config taken from VLSI */ |
|
| 4326 |
++ writel(0x00000004, base + EMAC_TFWR_STR_FWD); |
|
| 4327 |
++ writel(0x00000005, base + EMAC_RX_SECTION_FULL); |
|
| 4328 |
++ writel(0x00003fff, base + EMAC_TRUNC_FL); |
|
| 4329 |
++ writel(0x00000030, base + EMAC_TX_SECTION_EMPTY); |
|
| 4330 |
++ writel(0x00000000, base + EMAC_MIB_CTRL_STS_REG); |
|
| 4331 |
++ |
|
| 4332 |
++ gemac_set_mode(base, cfg->mode); |
|
| 4333 |
++ |
|
| 4334 |
++ gemac_set_speed(base, cfg->speed); |
|
| 4335 |
++ |
|
| 4336 |
++ gemac_set_duplex(base, cfg->duplex); |
|
| 4337 |
++} |
|
| 4338 |
++ |
|
| 4339 |
++/**************************** GPI ***************************/ |
|
| 4340 |
++ |
|
| 4341 |
++/* Initializes a GPI block. |
|
| 4342 |
++ * @param[in] base GPI base address |
|
| 4343 |
++ * @param[in] cfg GPI configuration |
|
| 4344 |
++ */ |
|
| 4345 |
++void gpi_init(void *base, struct gpi_cfg *cfg) |
|
| 4346 |
++{
|
|
| 4347 |
++ gpi_reset(base); |
|
| 4348 |
++ |
|
| 4349 |
++ gpi_disable(base); |
|
| 4350 |
++ |
|
| 4351 |
++ gpi_set_config(base, cfg); |
|
| 4352 |
++} |
|
| 4353 |
++ |
|
| 4354 |
++/* Resets a GPI block. |
|
| 4355 |
++ * @param[in] base GPI base address |
|
| 4356 |
++ */ |
|
| 4357 |
++void gpi_reset(void *base) |
|
| 4358 |
++{
|
|
| 4359 |
++ writel(CORE_SW_RESET, base + GPI_CTRL); |
|
| 4360 |
++} |
|
| 4361 |
++ |
|
| 4362 |
++/* Enables a GPI block. |
|
| 4363 |
++ * @param[in] base GPI base address |
|
| 4364 |
++ */ |
|
| 4365 |
++void gpi_enable(void *base) |
|
| 4366 |
++{
|
|
| 4367 |
++ writel(CORE_ENABLE, base + GPI_CTRL); |
|
| 4368 |
++} |
|
| 4369 |
++ |
|
| 4370 |
++/* Disables a GPI block. |
|
| 4371 |
++ * @param[in] base GPI base address |
|
| 4372 |
++ */ |
|
| 4373 |
++void gpi_disable(void *base) |
|
| 4374 |
++{
|
|
| 4375 |
++ writel(CORE_DISABLE, base + GPI_CTRL); |
|
| 4376 |
++} |
|
| 4377 |
++ |
|
| 4378 |
++/* Sets the configuration of a GPI block. |
|
| 4379 |
++ * @param[in] base GPI base address |
|
| 4380 |
++ * @param[in] cfg GPI configuration |
|
| 4381 |
++ */ |
|
| 4382 |
++void gpi_set_config(void *base, struct gpi_cfg *cfg) |
|
| 4383 |
++{
|
|
| 4384 |
++ writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_ALLOC_CTRL), base |
|
| 4385 |
++ + GPI_LMEM_ALLOC_ADDR); |
|
| 4386 |
++ writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_FREE_CTRL), base |
|
| 4387 |
++ + GPI_LMEM_FREE_ADDR); |
|
| 4388 |
++ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_ALLOC_CTRL), base |
|
| 4389 |
++ + GPI_DDR_ALLOC_ADDR); |
|
| 4390 |
++ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), base |
|
| 4391 |
++ + GPI_DDR_FREE_ADDR); |
|
| 4392 |
++ writel(CBUS_VIRT_TO_PFE(CLASS_INQ_PKTPTR), base + GPI_CLASS_ADDR); |
|
| 4393 |
++ writel(DDR_HDR_SIZE, base + GPI_DDR_DATA_OFFSET); |
|
| 4394 |
++ writel(LMEM_HDR_SIZE, base + GPI_LMEM_DATA_OFFSET); |
|
| 4395 |
++ writel(0, base + GPI_LMEM_SEC_BUF_DATA_OFFSET); |
|
| 4396 |
++ writel(0, base + GPI_DDR_SEC_BUF_DATA_OFFSET); |
|
| 4397 |
++ writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, base + GPI_HDR_SIZE); |
|
| 4398 |
++ writel((DDR_BUF_SIZE << 16) | LMEM_BUF_SIZE, base + GPI_BUF_SIZE); |
|
| 4399 |
++ |
|
| 4400 |
++ writel(((cfg->lmem_rtry_cnt << 16) | (GPI_DDR_BUF_EN << 1) | |
|
| 4401 |
++ GPI_LMEM_BUF_EN), base + GPI_RX_CONFIG); |
|
| 4402 |
++ writel(cfg->tmlf_txthres, base + GPI_TMLF_TX); |
|
| 4403 |
++ writel(cfg->aseq_len, base + GPI_DTX_ASEQ); |
|
| 4404 |
++ writel(1, base + GPI_TOE_CHKSUM_EN); |
|
| 4405 |
++ |
|
| 4406 |
++ if (cfg->mtip_pause_reg) {
|
|
| 4407 |
++ writel(cfg->mtip_pause_reg, base + GPI_CSR_MTIP_PAUSE_REG); |
|
| 4408 |
++ writel(EGPI_PAUSE_TIME, base + GPI_TX_PAUSE_TIME); |
|
| 4409 |
++ } |
|
| 4410 |
++} |
|
| 4411 |
++ |
|
| 4412 |
++/**************************** CLASSIFIER ***************************/ |
|
| 4413 |
++ |
|
| 4414 |
++/* Initializes CLASSIFIER block. |
|
| 4415 |
++ * @param[in] cfg CLASSIFIER configuration |
|
| 4416 |
++ */ |
|
| 4417 |
++void class_init(struct class_cfg *cfg) |
|
| 4418 |
++{
|
|
| 4419 |
++ class_reset(); |
|
| 4420 |
++ |
|
| 4421 |
++ class_disable(); |
|
| 4422 |
++ |
|
| 4423 |
++ class_set_config(cfg); |
|
| 4424 |
++} |
|
| 4425 |
++ |
|
| 4426 |
++/* Resets CLASSIFIER block. |
|
| 4427 |
++ * |
|
| 4428 |
++ */ |
|
| 4429 |
++void class_reset(void) |
|
| 4430 |
++{
|
|
| 4431 |
++ writel(CORE_SW_RESET, CLASS_TX_CTRL); |
|
| 4432 |
++} |
|
| 4433 |
++ |
|
| 4434 |
++/* Enables all CLASS-PE's cores. |
|
| 4435 |
++ * |
|
| 4436 |
++ */ |
|
| 4437 |
++void class_enable(void) |
|
| 4438 |
++{
|
|
| 4439 |
++ writel(CORE_ENABLE, CLASS_TX_CTRL); |
|
| 4440 |
++} |
|
| 4441 |
++ |
|
| 4442 |
++/* Disables all CLASS-PE's cores. |
|
| 4443 |
++ * |
|
| 4444 |
++ */ |
|
| 4445 |
++void class_disable(void) |
|
| 4446 |
++{
|
|
| 4447 |
++ writel(CORE_DISABLE, CLASS_TX_CTRL); |
|
| 4448 |
++} |
|
| 4449 |
++ |
|
| 4450 |
++/* |
|
| 4451 |
++ * Sets the configuration of the CLASSIFIER block. |
|
| 4452 |
++ * @param[in] cfg CLASSIFIER configuration |
|
| 4453 |
++ */ |
|
| 4454 |
++void class_set_config(struct class_cfg *cfg) |
|
| 4455 |
++{
|
|
| 4456 |
++ u32 val; |
|
| 4457 |
++ |
|
| 4458 |
++ /* Initialize route table */ |
|
| 4459 |
++ if (!cfg->resume) |
|
| 4460 |
++ memset(DDR_PHYS_TO_VIRT(cfg->route_table_baseaddr), 0, (1 << |
|
| 4461 |
++ cfg->route_table_hash_bits) * CLASS_ROUTE_SIZE); |
|
| 4462 |
++ |
|
| 4463 |
++#if !defined(LS1012A_PFE_RESET_WA) |
|
| 4464 |
++ writel(cfg->pe_sys_clk_ratio, CLASS_PE_SYS_CLK_RATIO); |
|
| 4465 |
++#endif |
|
| 4466 |
++ |
|
| 4467 |
++ writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, CLASS_HDR_SIZE); |
|
| 4468 |
++ writel(LMEM_BUF_SIZE, CLASS_LMEM_BUF_SIZE); |
|
| 4469 |
++ writel(CLASS_ROUTE_ENTRY_SIZE(CLASS_ROUTE_SIZE) | |
|
| 4470 |
++ CLASS_ROUTE_HASH_SIZE(cfg->route_table_hash_bits), |
|
| 4471 |
++ CLASS_ROUTE_HASH_ENTRY_SIZE); |
|
| 4472 |
++ writel(HIF_PKT_CLASS_EN | HIF_PKT_OFFSET(sizeof(struct hif_hdr)), |
|
| 4473 |
++ CLASS_HIF_PARSE); |
|
| 4474 |
++ |
|
| 4475 |
++ val = HASH_CRC_PORT_IP | QB2BUS_LE; |
|
| 4476 |
++ |
|
| 4477 |
++#if defined(CONFIG_IP_ALIGNED) |
|
| 4478 |
++ val |= IP_ALIGNED; |
|
| 4479 |
++#endif |
|
| 4480 |
++ |
|
| 4481 |
++ /* |
|
| 4482 |
++ * Class PE packet steering will only work if TOE mode, bridge fetch or |
|
| 4483 |
++ * route fetch are enabled (see class/qb_fet.v). Route fetch would |
|
| 4484 |
++ * trigger additional memory copies (likely from DDR because of hash |
|
| 4485 |
++ * table size, which cannot be reduced because PE software still |
|
| 4486 |
++ * relies on hash value computed in HW), so when not in TOE mode we |
|
| 4487 |
++ * simply enable HW bridge fetch even though we don't use it. |
|
| 4488 |
++ */ |
|
| 4489 |
++ if (cfg->toe_mode) |
|
| 4490 |
++ val |= CLASS_TOE; |
|
| 4491 |
++ else |
|
| 4492 |
++ val |= HW_BRIDGE_FETCH; |
|
| 4493 |
++ |
|
| 4494 |
++ writel(val, CLASS_ROUTE_MULTI); |
|
| 4495 |
++ |
|
| 4496 |
++ writel(DDR_PHYS_TO_PFE(cfg->route_table_baseaddr), |
|
| 4497 |
++ CLASS_ROUTE_TABLE_BASE); |
|
| 4498 |
++ writel(CLASS_PE0_RO_DM_ADDR0_VAL, CLASS_PE0_RO_DM_ADDR0); |
|
| 4499 |
++ writel(CLASS_PE0_RO_DM_ADDR1_VAL, CLASS_PE0_RO_DM_ADDR1); |
|
| 4500 |
++ writel(CLASS_PE0_QB_DM_ADDR0_VAL, CLASS_PE0_QB_DM_ADDR0); |
|
| 4501 |
++ writel(CLASS_PE0_QB_DM_ADDR1_VAL, CLASS_PE0_QB_DM_ADDR1); |
|
| 4502 |
++ writel(CBUS_VIRT_TO_PFE(TMU_PHY_INQ_PKTPTR), CLASS_TM_INQ_ADDR); |
|
| 4503 |
++ |
|
| 4504 |
++ writel(23, CLASS_AFULL_THRES); |
|
| 4505 |
++ writel(23, CLASS_TSQ_FIFO_THRES); |
|
| 4506 |
++ |
|
| 4507 |
++ writel(24, CLASS_MAX_BUF_CNT); |
|
| 4508 |
++ writel(24, CLASS_TSQ_MAX_CNT); |
|
| 4509 |
++} |
|
| 4510 |
++ |
|
| 4511 |
++/**************************** TMU ***************************/ |
|
| 4512 |
++ |
|
| 4513 |
++void tmu_reset(void) |
|
| 4514 |
++{
|
|
| 4515 |
++ writel(SW_RESET, TMU_CTRL); |
|
| 4516 |
++} |
|
| 4517 |
++ |
|
| 4518 |
++/* Initializes TMU block. |
|
| 4519 |
++ * @param[in] cfg TMU configuration |
|
| 4520 |
++ */ |
|
| 4521 |
++void tmu_init(struct tmu_cfg *cfg) |
|
| 4522 |
++{
|
|
| 4523 |
++ int q, phyno; |
|
| 4524 |
++ |
|
| 4525 |
++ tmu_disable(0xF); |
|
| 4526 |
++ mdelay(10); |
|
| 4527 |
++ |
|
| 4528 |
++#if !defined(LS1012A_PFE_RESET_WA) |
|
| 4529 |
++ /* keep in soft reset */ |
|
| 4530 |
++ writel(SW_RESET, TMU_CTRL); |
|
| 4531 |
++#endif |
|
| 4532 |
++ writel(0x3, TMU_SYS_GENERIC_CONTROL); |
|
| 4533 |
++ writel(750, TMU_INQ_WATERMARK); |
|
| 4534 |
++ writel(CBUS_VIRT_TO_PFE(EGPI1_BASE_ADDR + |
|
| 4535 |
++ GPI_INQ_PKTPTR), TMU_PHY0_INQ_ADDR); |
|
| 4536 |
++ writel(CBUS_VIRT_TO_PFE(EGPI2_BASE_ADDR + |
|
| 4537 |
++ GPI_INQ_PKTPTR), TMU_PHY1_INQ_ADDR); |
|
| 4538 |
++ writel(CBUS_VIRT_TO_PFE(HGPI_BASE_ADDR + |
|
| 4539 |
++ GPI_INQ_PKTPTR), TMU_PHY3_INQ_ADDR); |
|
| 4540 |
++ writel(CBUS_VIRT_TO_PFE(HIF_NOCPY_RX_INQ0_PKTPTR), TMU_PHY4_INQ_ADDR); |
|
| 4541 |
++ writel(CBUS_VIRT_TO_PFE(UTIL_INQ_PKTPTR), TMU_PHY5_INQ_ADDR); |
|
| 4542 |
++ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), |
|
| 4543 |
++ TMU_BMU_INQ_ADDR); |
|
| 4544 |
++ |
|
| 4545 |
++ writel(0x3FF, TMU_TDQ0_SCH_CTRL); /* |
|
| 4546 |
++ * enabling all 10 |
|
| 4547 |
++ * schedulers [9:0] of each TDQ |
|
| 4548 |
++ */ |
|
| 4549 |
++ writel(0x3FF, TMU_TDQ1_SCH_CTRL); |
|
| 4550 |
++ writel(0x3FF, TMU_TDQ3_SCH_CTRL); |
|
| 4551 |
++ |
|
| 4552 |
++#if !defined(LS1012A_PFE_RESET_WA) |
|
| 4553 |
++ writel(cfg->pe_sys_clk_ratio, TMU_PE_SYS_CLK_RATIO); |
|
| 4554 |
++#endif |
|
| 4555 |
++ |
|
| 4556 |
++#if !defined(LS1012A_PFE_RESET_WA) |
|
| 4557 |
++ writel(DDR_PHYS_TO_PFE(cfg->llm_base_addr), TMU_LLM_BASE_ADDR); |
|
| 4558 |
++ /* Extra packet pointers will be stored from this address onwards */ |
|
| 4559 |
++ |
|
| 4560 |
++ writel(cfg->llm_queue_len, TMU_LLM_QUE_LEN); |
|
| 4561 |
++ writel(5, TMU_TDQ_IIFG_CFG); |
|
| 4562 |
++ writel(DDR_BUF_SIZE, TMU_BMU_BUF_SIZE); |
|
| 4563 |
++ |
|
| 4564 |
++ writel(0x0, TMU_CTRL); |
|
| 4565 |
++ |
|
| 4566 |
++ /* MEM init */ |
|
| 4567 |
++ pr_info("%s: mem init\n", __func__);
|
|
| 4568 |
++ writel(MEM_INIT, TMU_CTRL); |
|
| 4569 |
++ |
|
| 4570 |
++ while (!(readl(TMU_CTRL) & MEM_INIT_DONE)) |
|
| 4571 |
++ ; |
|
| 4572 |
++ |
|
| 4573 |
++ /* LLM init */ |
|
| 4574 |
++ pr_info("%s: lmem init\n", __func__);
|
|
| 4575 |
++ writel(LLM_INIT, TMU_CTRL); |
|
| 4576 |
++ |
|
| 4577 |
++ while (!(readl(TMU_CTRL) & LLM_INIT_DONE)) |
|
| 4578 |
++ ; |
|
| 4579 |
++#endif |
|
| 4580 |
++ /* set up each queue for tail drop */ |
|
| 4581 |
++ for (phyno = 0; phyno < 4; phyno++) {
|
|
| 4582 |
++ if (phyno == 2) |
|
| 4583 |
++ continue; |
|
| 4584 |
++ for (q = 0; q < 16; q++) {
|
|
| 4585 |
++ u32 qdepth; |
|
| 4586 |
++ |
|
| 4587 |
++ writel((phyno << 8) | q, TMU_TEQ_CTRL); |
|
| 4588 |
++ writel(1 << 22, TMU_TEQ_QCFG); /*Enable tail drop */ |
|
| 4589 |
++ |
|
| 4590 |
++ if (phyno == 3) |
|
| 4591 |
++ qdepth = DEFAULT_TMU3_QDEPTH; |
|
| 4592 |
++ else |
|
| 4593 |
++ qdepth = (q == 0) ? DEFAULT_Q0_QDEPTH : |
|
| 4594 |
++ DEFAULT_MAX_QDEPTH; |
|
| 4595 |
++ |
|
| 4596 |
++ /* LOG: 68855 */ |
|
| 4597 |
++ /* |
|
| 4598 |
++ * The following is a workaround for the reordered |
|
| 4599 |
++ * packet and BMU2 buffer leakage issue. |
|
| 4600 |
++ */ |
|
| 4601 |
++ if (CHIP_REVISION() == 0) |
|
| 4602 |
++ qdepth = 31; |
|
| 4603 |
++ |
|
| 4604 |
++ writel(qdepth << 18, TMU_TEQ_HW_PROB_CFG2); |
|
| 4605 |
++ writel(qdepth >> 14, TMU_TEQ_HW_PROB_CFG3); |
|
| 4606 |
++ } |
|
| 4607 |
++ } |
|
| 4608 |
++ |
|
| 4609 |
++#ifdef CFG_LRO |
|
| 4610 |
++ /* Set TMU-3 queue 5 (LRO) in no-drop mode */ |
|
| 4611 |
++ writel((3 << 8) | TMU_QUEUE_LRO, TMU_TEQ_CTRL); |
|
| 4612 |
++ writel(0, TMU_TEQ_QCFG); |
|
| 4613 |
++#endif |
|
| 4614 |
++ |
|
| 4615 |
++ writel(0x05, TMU_TEQ_DISABLE_DROPCHK); |
|
| 4616 |
++ |
|
| 4617 |
++ writel(0x0, TMU_CTRL); |
|
| 4618 |
++} |
|
| 4619 |
++ |
|
| 4620 |
++/* Enables TMU-PE cores. |
|
| 4621 |
++ * @param[in] pe_mask TMU PE mask |
|
| 4622 |
++ */ |
|
| 4623 |
++void tmu_enable(u32 pe_mask) |
|
| 4624 |
++{
|
|
| 4625 |
++ writel(readl(TMU_TX_CTRL) | (pe_mask & 0xF), TMU_TX_CTRL); |
|
| 4626 |
++} |
|
| 4627 |
++ |
|
| 4628 |
++/* Disables TMU cores. |
|
| 4629 |
++ * @param[in] pe_mask TMU PE mask |
|
| 4630 |
++ */ |
|
| 4631 |
++void tmu_disable(u32 pe_mask) |
|
| 4632 |
++{
|
|
| 4633 |
++ writel(readl(TMU_TX_CTRL) & ~(pe_mask & 0xF), TMU_TX_CTRL); |
|
| 4634 |
++} |
|
| 4635 |
++ |
|
| 4636 |
++/* This will return the tmu queue status |
|
| 4637 |
++ * @param[in] if_id gem interface id or TMU index |
|
| 4638 |
++ * @return returns the bit mask of busy queues, zero means all |
|
| 4639 |
++ * queues are empty |
|
| 4640 |
++ */ |
|
| 4641 |
++u32 tmu_qstatus(u32 if_id) |
|
| 4642 |
++{
|
|
| 4643 |
++ return cpu_to_be32(pe_dmem_read(TMU0_ID + if_id, TMU_DM_PESTATUS + |
|
| 4644 |
++ offsetof(struct pe_status, tmu_qstatus), 4)); |
|
| 4645 |
++} |
|
| 4646 |
++ |
|
| 4647 |
++u32 tmu_pkts_processed(u32 if_id) |
|
| 4648 |
++{
|
|
| 4649 |
++ return cpu_to_be32(pe_dmem_read(TMU0_ID + if_id, TMU_DM_PESTATUS + |
|
| 4650 |
++ offsetof(struct pe_status, rx), 4)); |
|
| 4651 |
++} |
|
| 4652 |
++ |
|
| 4653 |
++/**************************** UTIL ***************************/ |
|
| 4654 |
++ |
|
| 4655 |
++/* Resets UTIL block. |
|
| 4656 |
++ */ |
|
| 4657 |
++void util_reset(void) |
|
| 4658 |
++{
|
|
| 4659 |
++ writel(CORE_SW_RESET, UTIL_TX_CTRL); |
|
| 4660 |
++} |
|
| 4661 |
++ |
|
| 4662 |
++/* Initializes UTIL block. |
|
| 4663 |
++ * @param[in] cfg UTIL configuration |
|
| 4664 |
++ */ |
|
| 4665 |
++void util_init(struct util_cfg *cfg) |
|
| 4666 |
++{
|
|
| 4667 |
++ writel(cfg->pe_sys_clk_ratio, UTIL_PE_SYS_CLK_RATIO); |
|
| 4668 |
++} |
|
| 4669 |
++ |
|
| 4670 |
++/* Enables UTIL-PE core. |
|
| 4671 |
++ * |
|
| 4672 |
++ */ |
|
| 4673 |
++void util_enable(void) |
|
| 4674 |
++{
|
|
| 4675 |
++ writel(CORE_ENABLE, UTIL_TX_CTRL); |
|
| 4676 |
++} |
|
| 4677 |
++ |
|
| 4678 |
++/* Disables UTIL-PE core. |
|
| 4679 |
++ * |
|
| 4680 |
++ */ |
|
| 4681 |
++void util_disable(void) |
|
| 4682 |
++{
|
|
| 4683 |
++ writel(CORE_DISABLE, UTIL_TX_CTRL); |
|
| 4684 |
++} |
|
| 4685 |
++ |
|
| 4686 |
++/**************************** HIF ***************************/ |
|
| 4687 |
++/* Initializes HIF copy block. |
|
| 4688 |
++ * |
|
| 4689 |
++ */ |
|
| 4690 |
++void hif_init(void) |
|
| 4691 |
++{
|
|
| 4692 |
++ /*Initialize HIF registers*/ |
|
| 4693 |
++ writel((HIF_RX_POLL_CTRL_CYCLE << 16) | HIF_TX_POLL_CTRL_CYCLE, |
|
| 4694 |
++ HIF_POLL_CTRL); |
|
| 4695 |
++} |
|
| 4696 |
++ |
|
| 4697 |
++/* Enable hif tx DMA and interrupt |
|
| 4698 |
++ * |
|
| 4699 |
++ */ |
|
| 4700 |
++void hif_tx_enable(void) |
|
| 4701 |
++{
|
|
| 4702 |
++ writel(HIF_CTRL_DMA_EN, HIF_TX_CTRL); |
|
| 4703 |
++ writel((readl(HIF_INT_ENABLE) | HIF_INT_EN | HIF_TXPKT_INT_EN), |
|
| 4704 |
++ HIF_INT_ENABLE); |
|
| 4705 |
++} |
|
| 4706 |
++ |
|
| 4707 |
++/* Disable hif tx DMA and interrupt |
|
| 4708 |
++ * |
|
| 4709 |
++ */ |
|
| 4710 |
++void hif_tx_disable(void) |
|
| 4711 |
++{
|
|
| 4712 |
++ u32 hif_int; |
|
| 4713 |
++ |
|
| 4714 |
++ writel(0, HIF_TX_CTRL); |
|
| 4715 |
++ |
|
| 4716 |
++ hif_int = readl(HIF_INT_ENABLE); |
|
| 4717 |
++ hif_int &= HIF_TXPKT_INT_EN; |
|
| 4718 |
++ writel(hif_int, HIF_INT_ENABLE); |
|
| 4719 |
++} |
|
| 4720 |
++ |
|
| 4721 |
++/* Enable hif rx DMA and interrupt |
|
| 4722 |
++ * |
|
| 4723 |
++ */ |
|
| 4724 |
++void hif_rx_enable(void) |
|
| 4725 |
++{
|
|
| 4726 |
++ hif_rx_dma_start(); |
|
| 4727 |
++ writel((readl(HIF_INT_ENABLE) | HIF_INT_EN | HIF_RXPKT_INT_EN), |
|
| 4728 |
++ HIF_INT_ENABLE); |
|
| 4729 |
++} |
|
| 4730 |
++ |
|
| 4731 |
++/* Disable hif rx DMA and interrupt |
|
| 4732 |
++ * |
|
| 4733 |
++ */ |
|
| 4734 |
++void hif_rx_disable(void) |
|
| 4735 |
++{
|
|
| 4736 |
++ u32 hif_int; |
|
| 4737 |
++ |
|
| 4738 |
++ writel(0, HIF_RX_CTRL); |
|
| 4739 |
++ |
|
| 4740 |
++ hif_int = readl(HIF_INT_ENABLE); |
|
| 4741 |
++ hif_int &= HIF_RXPKT_INT_EN; |
|
| 4742 |
++ writel(hif_int, HIF_INT_ENABLE); |
|
| 4743 |
++} |
|
| 4744 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif.c b/drivers/staging/fsl_ppfe/pfe_hif.c |
|
| 4745 |
+new file mode 100644 |
|
| 4746 |
+index 000000000000..6844595da9f1 |
|
| 4747 |
+--- /dev/null |
|
| 4748 |
+@@ -0,0 +1,1094 @@ |
|
| 4749 |
++/* |
|
| 4750 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 4751 |
++ * Copyright 2017 NXP |
|
| 4752 |
++ * |
|
| 4753 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 4754 |
++ * it under the terms of the GNU General Public License as published by |
|
| 4755 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 4756 |
++ * (at your option) any later version. |
|
| 4757 |
++ * |
|
| 4758 |
++ * This program is distributed in the hope that it will be useful, |
|
| 4759 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 4760 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 4761 |
++ * GNU General Public License for more details. |
|
| 4762 |
++ * |
|
| 4763 |
++ * You should have received a copy of the GNU General Public License |
|
| 4764 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 4765 |
++ */ |
|
| 4766 |
++ |
|
| 4767 |
++#include <linux/kernel.h> |
|
| 4768 |
++#include <linux/interrupt.h> |
|
| 4769 |
++#include <linux/dma-mapping.h> |
|
| 4770 |
++#include <linux/dmapool.h> |
|
| 4771 |
++#include <linux/sched.h> |
|
| 4772 |
++#include <linux/module.h> |
|
| 4773 |
++#include <linux/list.h> |
|
| 4774 |
++#include <linux/kthread.h> |
|
| 4775 |
++#include <linux/slab.h> |
|
| 4776 |
++ |
|
| 4777 |
++#include <linux/io.h> |
|
| 4778 |
++#include <asm/irq.h> |
|
| 4779 |
++ |
|
| 4780 |
++#include "pfe_mod.h" |
|
| 4781 |
++ |
|
| 4782 |
++#define HIF_INT_MASK (HIF_INT | HIF_RXPKT_INT | HIF_TXPKT_INT) |
|
| 4783 |
++ |
|
| 4784 |
++unsigned char napi_first_batch; |
|
| 4785 |
++ |
|
| 4786 |
++static void pfe_tx_do_cleanup(unsigned long data); |
|
| 4787 |
++ |
|
| 4788 |
++static int pfe_hif_alloc_descr(struct pfe_hif *hif) |
|
| 4789 |
++{
|
|
| 4790 |
++ void *addr; |
|
| 4791 |
++ dma_addr_t dma_addr; |
|
| 4792 |
++ int err = 0; |
|
| 4793 |
++ |
|
| 4794 |
++ pr_info("%s\n", __func__);
|
|
| 4795 |
++ addr = dma_alloc_coherent(pfe->dev, |
|
| 4796 |
++ HIF_RX_DESC_NT * sizeof(struct hif_desc) + |
|
| 4797 |
++ HIF_TX_DESC_NT * sizeof(struct hif_desc), |
|
| 4798 |
++ &dma_addr, GFP_KERNEL); |
|
| 4799 |
++ |
|
| 4800 |
++ if (!addr) {
|
|
| 4801 |
++ pr_err("%s: Could not allocate buffer descriptors!\n"
|
|
| 4802 |
++ , __func__); |
|
| 4803 |
++ err = -ENOMEM; |
|
| 4804 |
++ goto err0; |
|
| 4805 |
++ } |
|
| 4806 |
++ |
|
| 4807 |
++ hif->descr_baseaddr_p = dma_addr; |
|
| 4808 |
++ hif->descr_baseaddr_v = addr; |
|
| 4809 |
++ hif->rx_ring_size = HIF_RX_DESC_NT; |
|
| 4810 |
++ hif->tx_ring_size = HIF_TX_DESC_NT; |
|
| 4811 |
++ |
|
| 4812 |
++ return 0; |
|
| 4813 |
++ |
|
| 4814 |
++err0: |
|
| 4815 |
++ return err; |
|
| 4816 |
++} |
|
| 4817 |
++ |
|
| 4818 |
++#if defined(LS1012A_PFE_RESET_WA) |
|
| 4819 |
++static void pfe_hif_disable_rx_desc(struct pfe_hif *hif) |
|
| 4820 |
++{
|
|
| 4821 |
++ int ii; |
|
| 4822 |
++ struct hif_desc *desc = hif->rx_base; |
|
| 4823 |
++ |
|
| 4824 |
++ /*Mark all descriptors as LAST_BD */ |
|
| 4825 |
++ for (ii = 0; ii < hif->rx_ring_size; ii++) {
|
|
| 4826 |
++ desc->ctrl |= BD_CTRL_LAST_BD; |
|
| 4827 |
++ desc++; |
|
| 4828 |
++ } |
|
| 4829 |
++} |
|
| 4830 |
++ |
|
| 4831 |
++struct class_rx_hdr_t {
|
|
| 4832 |
++ u32 next_ptr; /* ptr to the start of the first DDR buffer */ |
|
| 4833 |
++ u16 length; /* total packet length */ |
|
| 4834 |
++ u16 phyno; /* input physical port number */ |
|
| 4835 |
++ u32 status; /* gemac status bits */ |
|
| 4836 |
++ u32 status2; /* reserved for software usage */ |
|
| 4837 |
++}; |
|
| 4838 |
++ |
|
| 4839 |
++/* STATUS_BAD_FRAME_ERR is set for all errors (including checksums if enabled) |
|
| 4840 |
++ * except overflow |
|
| 4841 |
++ */ |
|
| 4842 |
++#define STATUS_BAD_FRAME_ERR BIT(16) |
|
| 4843 |
++#define STATUS_LENGTH_ERR BIT(17) |
|
| 4844 |
++#define STATUS_CRC_ERR BIT(18) |
|
| 4845 |
++#define STATUS_TOO_SHORT_ERR BIT(19) |
|
| 4846 |
++#define STATUS_TOO_LONG_ERR BIT(20) |
|
| 4847 |
++#define STATUS_CODE_ERR BIT(21) |
|
| 4848 |
++#define STATUS_MC_HASH_MATCH BIT(22) |
|
| 4849 |
++#define STATUS_CUMULATIVE_ARC_HIT BIT(23) |
|
| 4850 |
++#define STATUS_UNICAST_HASH_MATCH BIT(24) |
|
| 4851 |
++#define STATUS_IP_CHECKSUM_CORRECT BIT(25) |
|
| 4852 |
++#define STATUS_TCP_CHECKSUM_CORRECT BIT(26) |
|
| 4853 |
++#define STATUS_UDP_CHECKSUM_CORRECT BIT(27) |
|
| 4854 |
++#define STATUS_OVERFLOW_ERR BIT(28) /* GPI error */ |
|
| 4855 |
++#define MIN_PKT_SIZE 64 |
|
| 4856 |
++ |
|
| 4857 |
++static inline void copy_to_lmem(u32 *dst, u32 *src, int len) |
|
| 4858 |
++{
|
|
| 4859 |
++ int i; |
|
| 4860 |
++ |
|
| 4861 |
++ for (i = 0; i < len; i += sizeof(u32)) {
|
|
| 4862 |
++ *dst = htonl(*src); |
|
| 4863 |
++ dst++; src++; |
|
| 4864 |
++ } |
|
| 4865 |
++} |
|
| 4866 |
++ |
|
| 4867 |
++static void send_dummy_pkt_to_hif(void) |
|
| 4868 |
++{
|
|
| 4869 |
++ void *lmem_ptr, *ddr_ptr, *lmem_virt_addr; |
|
| 4870 |
++ u32 physaddr; |
|
| 4871 |
++ struct class_rx_hdr_t local_hdr; |
|
| 4872 |
++ static u32 dummy_pkt[] = {
|
|
| 4873 |
++ 0x33221100, 0x2b785544, 0xd73093cb, 0x01000608, |
|
| 4874 |
++ 0x04060008, 0x2b780200, 0xd73093cb, 0x0a01a8c0, |
|
| 4875 |
++ 0x33221100, 0xa8c05544, 0x00000301, 0x00000000, |
|
| 4876 |
++ 0x00000000, 0x00000000, 0x00000000, 0xbe86c51f }; |
|
| 4877 |
++ |
|
| 4878 |
++ ddr_ptr = (void *)((u64)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); |
|
| 4879 |
++ if (!ddr_ptr) |
|
| 4880 |
++ return; |
|
| 4881 |
++ |
|
| 4882 |
++ lmem_ptr = (void *)((u64)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); |
|
| 4883 |
++ if (!lmem_ptr) |
|
| 4884 |
++ return; |
|
| 4885 |
++ |
|
| 4886 |
++ pr_info("Sending a dummy pkt to HIF %p %p\n", ddr_ptr, lmem_ptr);
|
|
| 4887 |
++ physaddr = (u32)DDR_VIRT_TO_PFE(ddr_ptr); |
|
| 4888 |
++ |
|
| 4889 |
++ lmem_virt_addr = (void *)CBUS_PFE_TO_VIRT((unsigned long int)lmem_ptr); |
|
| 4890 |
++ |
|
| 4891 |
++ local_hdr.phyno = htons(0); /* RX_PHY_0 */ |
|
| 4892 |
++ local_hdr.length = htons(MIN_PKT_SIZE); |
|
| 4893 |
++ |
|
| 4894 |
++ local_hdr.next_ptr = htonl((u32)physaddr); |
|
| 4895 |
++ /*Mark checksum is correct */ |
|
| 4896 |
++ local_hdr.status = htonl((STATUS_IP_CHECKSUM_CORRECT | |
|
| 4897 |
++ STATUS_UDP_CHECKSUM_CORRECT | |
|
| 4898 |
++ STATUS_TCP_CHECKSUM_CORRECT | |
|
| 4899 |
++ STATUS_UNICAST_HASH_MATCH | |
|
| 4900 |
++ STATUS_CUMULATIVE_ARC_HIT)); |
|
| 4901 |
++ copy_to_lmem((u32 *)lmem_virt_addr, (u32 *)&local_hdr, |
|
| 4902 |
++ sizeof(local_hdr)); |
|
| 4903 |
++ |
|
| 4904 |
++ copy_to_lmem((u32 *)(lmem_virt_addr + LMEM_HDR_SIZE), (u32 *)dummy_pkt, |
|
| 4905 |
++ 0x40); |
|
| 4906 |
++ |
|
| 4907 |
++ writel((unsigned long int)lmem_ptr, CLASS_INQ_PKTPTR); |
|
| 4908 |
++} |
|
| 4909 |
++ |
|
| 4910 |
++void pfe_hif_rx_idle(struct pfe_hif *hif) |
|
| 4911 |
++{
|
|
| 4912 |
++ int hif_stop_loop = 10; |
|
| 4913 |
++ u32 rx_status; |
|
| 4914 |
++ |
|
| 4915 |
++ pfe_hif_disable_rx_desc(hif); |
|
| 4916 |
++ pr_info("Bringing hif to idle state...");
|
|
| 4917 |
++ writel(0, HIF_INT_ENABLE); |
|
| 4918 |
++ /*If HIF Rx BDP is busy send a dummy packet */ |
|
| 4919 |
++ do {
|
|
| 4920 |
++ rx_status = readl(HIF_RX_STATUS); |
|
| 4921 |
++ if (rx_status & BDP_CSR_RX_DMA_ACTV) |
|
| 4922 |
++ send_dummy_pkt_to_hif(); |
|
| 4923 |
++ |
|
| 4924 |
++ usleep_range(100, 150); |
|
| 4925 |
++ } while (--hif_stop_loop); |
|
| 4926 |
++ |
|
| 4927 |
++ if (readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV) |
|
| 4928 |
++ pr_info("Failed\n");
|
|
| 4929 |
++ else |
|
| 4930 |
++ pr_info("Done\n");
|
|
| 4931 |
++} |
|
| 4932 |
++#endif |
|
| 4933 |
++ |
|
| 4934 |
++static void pfe_hif_free_descr(struct pfe_hif *hif) |
|
| 4935 |
++{
|
|
| 4936 |
++ pr_info("%s\n", __func__);
|
|
| 4937 |
++ |
|
| 4938 |
++ dma_free_coherent(pfe->dev, |
|
| 4939 |
++ hif->rx_ring_size * sizeof(struct hif_desc) + |
|
| 4940 |
++ hif->tx_ring_size * sizeof(struct hif_desc), |
|
| 4941 |
++ hif->descr_baseaddr_v, hif->descr_baseaddr_p); |
|
| 4942 |
++} |
|
| 4943 |
++ |
|
| 4944 |
++void pfe_hif_desc_dump(struct pfe_hif *hif) |
|
| 4945 |
++{
|
|
| 4946 |
++ struct hif_desc *desc; |
|
| 4947 |
++ unsigned long desc_p; |
|
| 4948 |
++ int ii = 0; |
|
| 4949 |
++ |
|
| 4950 |
++ pr_info("%s\n", __func__);
|
|
| 4951 |
++ |
|
| 4952 |
++ desc = hif->rx_base; |
|
| 4953 |
++ desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + |
|
| 4954 |
++ hif->descr_baseaddr_p); |
|
| 4955 |
++ |
|
| 4956 |
++ pr_info("HIF Rx desc base %p physical %x\n", desc, (u32)desc_p);
|
|
| 4957 |
++ for (ii = 0; ii < hif->rx_ring_size; ii++) {
|
|
| 4958 |
++ pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n",
|
|
| 4959 |
++ readl(&desc->status), readl(&desc->ctrl), |
|
| 4960 |
++ readl(&desc->data), readl(&desc->next)); |
|
| 4961 |
++ desc++; |
|
| 4962 |
++ } |
|
| 4963 |
++ |
|
| 4964 |
++ desc = hif->tx_base; |
|
| 4965 |
++ desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + |
|
| 4966 |
++ hif->descr_baseaddr_p); |
|
| 4967 |
++ |
|
| 4968 |
++ pr_info("HIF Tx desc base %p physical %x\n", desc, (u32)desc_p);
|
|
| 4969 |
++ for (ii = 0; ii < hif->tx_ring_size; ii++) {
|
|
| 4970 |
++ pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n",
|
|
| 4971 |
++ readl(&desc->status), readl(&desc->ctrl), |
|
| 4972 |
++ readl(&desc->data), readl(&desc->next)); |
|
| 4973 |
++ desc++; |
|
| 4974 |
++ } |
|
| 4975 |
++} |
|
| 4976 |
++ |
|
| 4977 |
++/* pfe_hif_release_buffers */ |
|
| 4978 |
++static void pfe_hif_release_buffers(struct pfe_hif *hif) |
|
| 4979 |
++{
|
|
| 4980 |
++ struct hif_desc *desc; |
|
| 4981 |
++ int i = 0; |
|
| 4982 |
++ |
|
| 4983 |
++ hif->rx_base = hif->descr_baseaddr_v; |
|
| 4984 |
++ |
|
| 4985 |
++ pr_info("%s\n", __func__);
|
|
| 4986 |
++ |
|
| 4987 |
++ /*Free Rx buffers */ |
|
| 4988 |
++ desc = hif->rx_base; |
|
| 4989 |
++ for (i = 0; i < hif->rx_ring_size; i++) {
|
|
| 4990 |
++ if (readl(&desc->data)) {
|
|
| 4991 |
++ if ((i < hif->shm->rx_buf_pool_cnt) && |
|
| 4992 |
++ (!hif->shm->rx_buf_pool[i])) {
|
|
| 4993 |
++ /* |
|
| 4994 |
++ * dma_unmap_single(hif->dev, desc->data, |
|
| 4995 |
++ * hif->rx_buf_len[i], DMA_FROM_DEVICE); |
|
| 4996 |
++ */ |
|
| 4997 |
++ dma_unmap_single(hif->dev, |
|
| 4998 |
++ DDR_PFE_TO_PHYS( |
|
| 4999 |
++ readl(&desc->data)), |
|
| 5000 |
++ hif->rx_buf_len[i], |
|
| 5001 |
++ DMA_FROM_DEVICE); |
|
| 5002 |
++ hif->shm->rx_buf_pool[i] = hif->rx_buf_addr[i]; |
|
| 5003 |
++ } else {
|
|
| 5004 |
++ pr_err("%s: buffer pool already full\n"
|
|
| 5005 |
++ , __func__); |
|
| 5006 |
++ } |
|
| 5007 |
++ } |
|
| 5008 |
++ |
|
| 5009 |
++ writel(0, &desc->data); |
|
| 5010 |
++ writel(0, &desc->status); |
|
| 5011 |
++ writel(0, &desc->ctrl); |
|
| 5012 |
++ desc++; |
|
| 5013 |
++ } |
|
| 5014 |
++} |
|
| 5015 |
++ |
|
| 5016 |
++/* |
|
| 5017 |
++ * pfe_hif_init_buffers |
|
| 5018 |
++ * This function initializes the HIF Rx/Tx ring descriptors and |
|
| 5019 |
++ * initialize Rx queue with buffers. |
|
| 5020 |
++ */ |
|
| 5021 |
++static int pfe_hif_init_buffers(struct pfe_hif *hif) |
|
| 5022 |
++{
|
|
| 5023 |
++ struct hif_desc *desc, *first_desc_p; |
|
| 5024 |
++ u32 data; |
|
| 5025 |
++ int i = 0; |
|
| 5026 |
++ |
|
| 5027 |
++ pr_info("%s\n", __func__);
|
|
| 5028 |
++ |
|
| 5029 |
++ /* Check enough Rx buffers available in the shared memory */ |
|
| 5030 |
++ if (hif->shm->rx_buf_pool_cnt < hif->rx_ring_size) |
|
| 5031 |
++ return -ENOMEM; |
|
| 5032 |
++ |
|
| 5033 |
++ hif->rx_base = hif->descr_baseaddr_v; |
|
| 5034 |
++ memset(hif->rx_base, 0, hif->rx_ring_size * sizeof(struct hif_desc)); |
|
| 5035 |
++ |
|
| 5036 |
++ /*Initialize Rx descriptors */ |
|
| 5037 |
++ desc = hif->rx_base; |
|
| 5038 |
++ first_desc_p = (struct hif_desc *)hif->descr_baseaddr_p; |
|
| 5039 |
++ |
|
| 5040 |
++ for (i = 0; i < hif->rx_ring_size; i++) {
|
|
| 5041 |
++ /* Initialize Rx buffers from the shared memory */ |
|
| 5042 |
++ |
|
| 5043 |
++ data = (u32)dma_map_single(hif->dev, hif->shm->rx_buf_pool[i], |
|
| 5044 |
++ pfe_pkt_size, DMA_FROM_DEVICE); |
|
| 5045 |
++ hif->rx_buf_addr[i] = hif->shm->rx_buf_pool[i]; |
|
| 5046 |
++ hif->rx_buf_len[i] = pfe_pkt_size; |
|
| 5047 |
++ hif->shm->rx_buf_pool[i] = NULL; |
|
| 5048 |
++ |
|
| 5049 |
++ if (likely(dma_mapping_error(hif->dev, data) == 0)) {
|
|
| 5050 |
++ writel(DDR_PHYS_TO_PFE(data), &desc->data); |
|
| 5051 |
++ } else {
|
|
| 5052 |
++ pr_err("%s : low on mem\n", __func__);
|
|
| 5053 |
++ |
|
| 5054 |
++ goto err; |
|
| 5055 |
++ } |
|
| 5056 |
++ |
|
| 5057 |
++ writel(0, &desc->status); |
|
| 5058 |
++ |
|
| 5059 |
++ /* |
|
| 5060 |
++ * Ensure everything else is written to DDR before |
|
| 5061 |
++ * writing bd->ctrl |
|
| 5062 |
++ */ |
|
| 5063 |
++ wmb(); |
|
| 5064 |
++ |
|
| 5065 |
++ writel((BD_CTRL_PKT_INT_EN | BD_CTRL_LIFM |
|
| 5066 |
++ | BD_CTRL_DIR | BD_CTRL_DESC_EN |
|
| 5067 |
++ | BD_BUF_LEN(pfe_pkt_size)), &desc->ctrl); |
|
| 5068 |
++ |
|
| 5069 |
++ /* Chain descriptors */ |
|
| 5070 |
++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p + i + 1), &desc->next); |
|
| 5071 |
++ desc++; |
|
| 5072 |
++ } |
|
| 5073 |
++ |
|
| 5074 |
++ /* Overwrite last descriptor to chain it to first one*/ |
|
| 5075 |
++ desc--; |
|
| 5076 |
++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), &desc->next); |
|
| 5077 |
++ |
|
| 5078 |
++ hif->rxtoclean_index = 0; |
|
| 5079 |
++ |
|
| 5080 |
++ /*Initialize Rx buffer descriptor ring base address */ |
|
| 5081 |
++ writel(DDR_PHYS_TO_PFE(hif->descr_baseaddr_p), HIF_RX_BDP_ADDR); |
|
| 5082 |
++ |
|
| 5083 |
++ hif->tx_base = hif->rx_base + hif->rx_ring_size; |
|
| 5084 |
++ first_desc_p = (struct hif_desc *)hif->descr_baseaddr_p + |
|
| 5085 |
++ hif->rx_ring_size; |
|
| 5086 |
++ memset(hif->tx_base, 0, hif->tx_ring_size * sizeof(struct hif_desc)); |
|
| 5087 |
++ |
|
| 5088 |
++ /*Initialize tx descriptors */ |
|
| 5089 |
++ desc = hif->tx_base; |
|
| 5090 |
++ |
|
| 5091 |
++ for (i = 0; i < hif->tx_ring_size; i++) {
|
|
| 5092 |
++ /* Chain descriptors */ |
|
| 5093 |
++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p + i + 1), &desc->next); |
|
| 5094 |
++ writel(0, &desc->ctrl); |
|
| 5095 |
++ desc++; |
|
| 5096 |
++ } |
|
| 5097 |
++ |
|
| 5098 |
++ /* Overwrite last descriptor to chain it to first one */ |
|
| 5099 |
++ desc--; |
|
| 5100 |
++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), &desc->next); |
|
| 5101 |
++ hif->txavail = hif->tx_ring_size; |
|
| 5102 |
++ hif->txtosend = 0; |
|
| 5103 |
++ hif->txtoclean = 0; |
|
| 5104 |
++ hif->txtoflush = 0; |
|
| 5105 |
++ |
|
| 5106 |
++ /*Initialize Tx buffer descriptor ring base address */ |
|
| 5107 |
++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), HIF_TX_BDP_ADDR); |
|
| 5108 |
++ |
|
| 5109 |
++ return 0; |
|
| 5110 |
++ |
|
| 5111 |
++err: |
|
| 5112 |
++ pfe_hif_release_buffers(hif); |
|
| 5113 |
++ return -ENOMEM; |
|
| 5114 |
++} |
|
| 5115 |
++ |
|
| 5116 |
++/* |
|
| 5117 |
++ * pfe_hif_client_register |
|
| 5118 |
++ * |
|
| 5119 |
++ * This function used to register a client driver with the HIF driver. |
|
| 5120 |
++ * |
|
| 5121 |
++ * Return value: |
|
| 5122 |
++ * 0 - on Successful registration |
|
| 5123 |
++ */ |
|
| 5124 |
++static int pfe_hif_client_register(struct pfe_hif *hif, u32 client_id, |
|
| 5125 |
++ struct hif_client_shm *client_shm) |
|
| 5126 |
++{
|
|
| 5127 |
++ struct hif_client *client = &hif->client[client_id]; |
|
| 5128 |
++ u32 i, cnt; |
|
| 5129 |
++ struct rx_queue_desc *rx_qbase; |
|
| 5130 |
++ struct tx_queue_desc *tx_qbase; |
|
| 5131 |
++ struct hif_rx_queue *rx_queue; |
|
| 5132 |
++ struct hif_tx_queue *tx_queue; |
|
| 5133 |
++ int err = 0; |
|
| 5134 |
++ |
|
| 5135 |
++ pr_info("%s\n", __func__);
|
|
| 5136 |
++ |
|
| 5137 |
++ spin_lock_bh(&hif->tx_lock); |
|
| 5138 |
++ |
|
| 5139 |
++ if (test_bit(client_id, &hif->shm->g_client_status[0])) {
|
|
| 5140 |
++ pr_err("%s: client %d already registered\n",
|
|
| 5141 |
++ __func__, client_id); |
|
| 5142 |
++ err = -1; |
|
| 5143 |
++ goto unlock; |
|
| 5144 |
++ } |
|
| 5145 |
++ |
|
| 5146 |
++ memset(client, 0, sizeof(struct hif_client)); |
|
| 5147 |
++ |
|
| 5148 |
++ /* Initialize client Rx queues baseaddr, size */ |
|
| 5149 |
++ |
|
| 5150 |
++ cnt = CLIENT_CTRL_RX_Q_CNT(client_shm->ctrl); |
|
| 5151 |
++ /* Check if client is requesting for more queues than supported */ |
|
| 5152 |
++ if (cnt > HIF_CLIENT_QUEUES_MAX) |
|
| 5153 |
++ cnt = HIF_CLIENT_QUEUES_MAX; |
|
| 5154 |
++ |
|
| 5155 |
++ client->rx_qn = cnt; |
|
| 5156 |
++ rx_qbase = (struct rx_queue_desc *)client_shm->rx_qbase; |
|
| 5157 |
++ for (i = 0; i < cnt; i++) {
|
|
| 5158 |
++ rx_queue = &client->rx_q[i]; |
|
| 5159 |
++ rx_queue->base = rx_qbase + i * client_shm->rx_qsize; |
|
| 5160 |
++ rx_queue->size = client_shm->rx_qsize; |
|
| 5161 |
++ rx_queue->write_idx = 0; |
|
| 5162 |
++ } |
|
| 5163 |
++ |
|
| 5164 |
++ /* Initialize client Tx queues baseaddr, size */ |
|
| 5165 |
++ cnt = CLIENT_CTRL_TX_Q_CNT(client_shm->ctrl); |
|
| 5166 |
++ |
|
| 5167 |
++ /* Check if client is requesting for more queues than supported */ |
|
| 5168 |
++ if (cnt > HIF_CLIENT_QUEUES_MAX) |
|
| 5169 |
++ cnt = HIF_CLIENT_QUEUES_MAX; |
|
| 5170 |
++ |
|
| 5171 |
++ client->tx_qn = cnt; |
|
| 5172 |
++ tx_qbase = (struct tx_queue_desc *)client_shm->tx_qbase; |
|
| 5173 |
++ for (i = 0; i < cnt; i++) {
|
|
| 5174 |
++ tx_queue = &client->tx_q[i]; |
|
| 5175 |
++ tx_queue->base = tx_qbase + i * client_shm->tx_qsize; |
|
| 5176 |
++ tx_queue->size = client_shm->tx_qsize; |
|
| 5177 |
++ tx_queue->ack_idx = 0; |
|
| 5178 |
++ } |
|
| 5179 |
++ |
|
| 5180 |
++ set_bit(client_id, &hif->shm->g_client_status[0]); |
|
| 5181 |
++ |
|
| 5182 |
++unlock: |
|
| 5183 |
++ spin_unlock_bh(&hif->tx_lock); |
|
| 5184 |
++ |
|
| 5185 |
++ return err; |
|
| 5186 |
++} |
|
| 5187 |
++ |
|
| 5188 |
++/* |
|
| 5189 |
++ * pfe_hif_client_unregister |
|
| 5190 |
++ * |
|
| 5191 |
++ * This function used to unregister a client from the HIF driver. |
|
| 5192 |
++ * |
|
| 5193 |
++ */ |
|
| 5194 |
++static void pfe_hif_client_unregister(struct pfe_hif *hif, u32 client_id) |
|
| 5195 |
++{
|
|
| 5196 |
++ pr_info("%s\n", __func__);
|
|
| 5197 |
++ |
|
| 5198 |
++ /* |
|
| 5199 |
++ * Mark client as no longer available (which prevents further packet |
|
| 5200 |
++ * receive for this client) |
|
| 5201 |
++ */ |
|
| 5202 |
++ spin_lock_bh(&hif->tx_lock); |
|
| 5203 |
++ |
|
| 5204 |
++ if (!test_bit(client_id, &hif->shm->g_client_status[0])) {
|
|
| 5205 |
++ pr_err("%s: client %d not registered\n", __func__,
|
|
| 5206 |
++ client_id); |
|
| 5207 |
++ |
|
| 5208 |
++ spin_unlock_bh(&hif->tx_lock); |
|
| 5209 |
++ return; |
|
| 5210 |
++ } |
|
| 5211 |
++ |
|
| 5212 |
++ clear_bit(client_id, &hif->shm->g_client_status[0]); |
|
| 5213 |
++ |
|
| 5214 |
++ spin_unlock_bh(&hif->tx_lock); |
|
| 5215 |
++} |
|
| 5216 |
++ |
|
| 5217 |
++/* |
|
| 5218 |
++ * client_put_rxpacket- |
|
| 5219 |
++ * This functions puts the Rx pkt in the given client Rx queue. |
|
| 5220 |
++ * It actually swap the Rx pkt in the client Rx descriptor buffer |
|
| 5221 |
++ * and returns the free buffer from it. |
|
| 5222 |
++ * |
|
| 5223 |
++ * If the function returns NULL means client Rx queue is full and |
|
| 5224 |
++ * packet couldn't send to client queue. |
|
| 5225 |
++ */ |
|
| 5226 |
++static void *client_put_rxpacket(struct hif_rx_queue *queue, void *pkt, u32 len, |
|
| 5227 |
++ u32 flags, u32 client_ctrl, u32 *rem_len) |
|
| 5228 |
++{
|
|
| 5229 |
++ void *free_pkt = NULL; |
|
| 5230 |
++ struct rx_queue_desc *desc = queue->base + queue->write_idx; |
|
| 5231 |
++ |
|
| 5232 |
++ if (readl(&desc->ctrl) & CL_DESC_OWN) {
|
|
| 5233 |
++ if (page_mode) {
|
|
| 5234 |
++ int rem_page_size = PAGE_SIZE - |
|
| 5235 |
++ PRESENT_OFST_IN_PAGE(pkt); |
|
| 5236 |
++ int cur_pkt_size = ROUND_MIN_RX_SIZE(len + |
|
| 5237 |
++ pfe_pkt_headroom); |
|
| 5238 |
++ *rem_len = (rem_page_size - cur_pkt_size); |
|
| 5239 |
++ if (*rem_len) {
|
|
| 5240 |
++ free_pkt = pkt + cur_pkt_size; |
|
| 5241 |
++ get_page(virt_to_page(free_pkt)); |
|
| 5242 |
++ } else {
|
|
| 5243 |
++ free_pkt = (void |
|
| 5244 |
++ *)__get_free_page(GFP_ATOMIC | GFP_DMA_PFE); |
|
| 5245 |
++ *rem_len = pfe_pkt_size; |
|
| 5246 |
++ } |
|
| 5247 |
++ } else {
|
|
| 5248 |
++ free_pkt = kmalloc(PFE_BUF_SIZE, GFP_ATOMIC | |
|
| 5249 |
++ GFP_DMA_PFE); |
|
| 5250 |
++ *rem_len = PFE_BUF_SIZE - pfe_pkt_headroom; |
|
| 5251 |
++ } |
|
| 5252 |
++ |
|
| 5253 |
++ if (free_pkt) {
|
|
| 5254 |
++ desc->data = pkt; |
|
| 5255 |
++ desc->client_ctrl = client_ctrl; |
|
| 5256 |
++ /* |
|
| 5257 |
++ * Ensure everything else is written to DDR before |
|
| 5258 |
++ * writing bd->ctrl |
|
| 5259 |
++ */ |
|
| 5260 |
++ smp_wmb(); |
|
| 5261 |
++ writel(CL_DESC_BUF_LEN(len) | flags, &desc->ctrl); |
|
| 5262 |
++ /* queue->write_idx = (queue->write_idx + 1) |
|
| 5263 |
++ * & (queue->size - 1); |
|
| 5264 |
++ */ |
|
| 5265 |
++ free_pkt += pfe_pkt_headroom; |
|
| 5266 |
++ } |
|
| 5267 |
++ } |
|
| 5268 |
++ |
|
| 5269 |
++ return free_pkt; |
|
| 5270 |
++} |
|
| 5271 |
++ |
|
| 5272 |
++/* |
|
| 5273 |
++ * pfe_hif_rx_process- |
|
| 5274 |
++ * This function does pfe hif rx queue processing. |
|
| 5275 |
++ * Dequeue packet from Rx queue and send it to corresponding client queue |
|
| 5276 |
++ */ |
|
| 5277 |
++static int pfe_hif_rx_process(struct pfe_hif *hif, int budget) |
|
| 5278 |
++{
|
|
| 5279 |
++ struct hif_desc *desc; |
|
| 5280 |
++ struct hif_hdr *pkt_hdr; |
|
| 5281 |
++ struct __hif_hdr hif_hdr; |
|
| 5282 |
++ void *free_buf; |
|
| 5283 |
++ int rtc, len, rx_processed = 0; |
|
| 5284 |
++ struct __hif_desc local_desc; |
|
| 5285 |
++ int flags; |
|
| 5286 |
++ unsigned int desc_p; |
|
| 5287 |
++ unsigned int buf_size = 0; |
|
| 5288 |
++ |
|
| 5289 |
++ spin_lock_bh(&hif->lock); |
|
| 5290 |
++ |
|
| 5291 |
++ rtc = hif->rxtoclean_index; |
|
| 5292 |
++ |
|
| 5293 |
++ while (rx_processed < budget) {
|
|
| 5294 |
++ desc = hif->rx_base + rtc; |
|
| 5295 |
++ |
|
| 5296 |
++ __memcpy12(&local_desc, desc); |
|
| 5297 |
++ |
|
| 5298 |
++ /* ACK pending Rx interrupt */ |
|
| 5299 |
++ if (local_desc.ctrl & BD_CTRL_DESC_EN) {
|
|
| 5300 |
++ writel(HIF_INT | HIF_RXPKT_INT, HIF_INT_SRC); |
|
| 5301 |
++ |
|
| 5302 |
++ if (rx_processed == 0) {
|
|
| 5303 |
++ if (napi_first_batch == 1) {
|
|
| 5304 |
++ desc_p = hif->descr_baseaddr_p + |
|
| 5305 |
++ ((unsigned long int)(desc) - |
|
| 5306 |
++ (unsigned long |
|
| 5307 |
++ int)hif->descr_baseaddr_v); |
|
| 5308 |
++ napi_first_batch = 0; |
|
| 5309 |
++ } |
|
| 5310 |
++ } |
|
| 5311 |
++ |
|
| 5312 |
++ __memcpy12(&local_desc, desc); |
|
| 5313 |
++ |
|
| 5314 |
++ if (local_desc.ctrl & BD_CTRL_DESC_EN) |
|
| 5315 |
++ break; |
|
| 5316 |
++ } |
|
| 5317 |
++ |
|
| 5318 |
++ napi_first_batch = 0; |
|
| 5319 |
++ |
|
| 5320 |
++#ifdef HIF_NAPI_STATS |
|
| 5321 |
++ hif->napi_counters[NAPI_DESC_COUNT]++; |
|
| 5322 |
++#endif |
|
| 5323 |
++ len = BD_BUF_LEN(local_desc.ctrl); |
|
| 5324 |
++ /* |
|
| 5325 |
++ * dma_unmap_single(hif->dev, DDR_PFE_TO_PHYS(local_desc.data), |
|
| 5326 |
++ * hif->rx_buf_len[rtc], DMA_FROM_DEVICE); |
|
| 5327 |
++ */ |
|
| 5328 |
++ dma_unmap_single(hif->dev, DDR_PFE_TO_PHYS(local_desc.data), |
|
| 5329 |
++ hif->rx_buf_len[rtc], DMA_FROM_DEVICE); |
|
| 5330 |
++ |
|
| 5331 |
++ pkt_hdr = (struct hif_hdr *)hif->rx_buf_addr[rtc]; |
|
| 5332 |
++ |
|
| 5333 |
++ /* Track last HIF header received */ |
|
| 5334 |
++ if (!hif->started) {
|
|
| 5335 |
++ hif->started = 1; |
|
| 5336 |
++ |
|
| 5337 |
++ __memcpy8(&hif_hdr, pkt_hdr); |
|
| 5338 |
++ |
|
| 5339 |
++ hif->qno = hif_hdr.hdr.q_num; |
|
| 5340 |
++ hif->client_id = hif_hdr.hdr.client_id; |
|
| 5341 |
++ hif->client_ctrl = (hif_hdr.hdr.client_ctrl1 << 16) | |
|
| 5342 |
++ hif_hdr.hdr.client_ctrl; |
|
| 5343 |
++ flags = CL_DESC_FIRST; |
|
| 5344 |
++ |
|
| 5345 |
++ } else {
|
|
| 5346 |
++ flags = 0; |
|
| 5347 |
++ } |
|
| 5348 |
++ |
|
| 5349 |
++ if (local_desc.ctrl & BD_CTRL_LIFM) |
|
| 5350 |
++ flags |= CL_DESC_LAST; |
|
| 5351 |
++ |
|
| 5352 |
++ /* Check for valid client id and still registered */ |
|
| 5353 |
++ if ((hif->client_id >= HIF_CLIENTS_MAX) || |
|
| 5354 |
++ !(test_bit(hif->client_id, |
|
| 5355 |
++ &hif->shm->g_client_status[0]))) {
|
|
| 5356 |
++ printk_ratelimited("%s: packet with invalid client id %d q_num %d\n",
|
|
| 5357 |
++ __func__, |
|
| 5358 |
++ hif->client_id, |
|
| 5359 |
++ hif->qno); |
|
| 5360 |
++ |
|
| 5361 |
++ free_buf = pkt_hdr; |
|
| 5362 |
++ |
|
| 5363 |
++ goto pkt_drop; |
|
| 5364 |
++ } |
|
| 5365 |
++ |
|
| 5366 |
++ /* Check to valid queue number */ |
|
| 5367 |
++ if (hif->client[hif->client_id].rx_qn <= hif->qno) {
|
|
| 5368 |
++ pr_info("%s: packet with invalid queue: %d\n"
|
|
| 5369 |
++ , __func__, hif->qno); |
|
| 5370 |
++ hif->qno = 0; |
|
| 5371 |
++ } |
|
| 5372 |
++ |
|
| 5373 |
++ free_buf = |
|
| 5374 |
++ client_put_rxpacket(&hif->client[hif->client_id].rx_q[hif->qno], |
|
| 5375 |
++ (void *)pkt_hdr, len, flags, |
|
| 5376 |
++ hif->client_ctrl, &buf_size); |
|
| 5377 |
++ |
|
| 5378 |
++ hif_lib_indicate_client(hif->client_id, EVENT_RX_PKT_IND, |
|
| 5379 |
++ hif->qno); |
|
| 5380 |
++ |
|
| 5381 |
++ if (unlikely(!free_buf)) {
|
|
| 5382 |
++#ifdef HIF_NAPI_STATS |
|
| 5383 |
++ hif->napi_counters[NAPI_CLIENT_FULL_COUNT]++; |
|
| 5384 |
++#endif |
|
| 5385 |
++ /* |
|
| 5386 |
++ * If we want to keep in polling mode to retry later, |
|
| 5387 |
++ * we need to tell napi that we consumed |
|
| 5388 |
++ * the full budget or we will hit a livelock scenario. |
|
| 5389 |
++ * The core code keeps this napi instance |
|
| 5390 |
++ * at the head of the list and none of the other |
|
| 5391 |
++ * instances get to run |
|
| 5392 |
++ */ |
|
| 5393 |
++ rx_processed = budget; |
|
| 5394 |
++ |
|
| 5395 |
++ if (flags & CL_DESC_FIRST) |
|
| 5396 |
++ hif->started = 0; |
|
| 5397 |
++ |
|
| 5398 |
++ break; |
|
| 5399 |
++ } |
|
| 5400 |
++ |
|
| 5401 |
++pkt_drop: |
|
| 5402 |
++ /*Fill free buffer in the descriptor */ |
|
| 5403 |
++ hif->rx_buf_addr[rtc] = free_buf; |
|
| 5404 |
++ hif->rx_buf_len[rtc] = min(pfe_pkt_size, buf_size); |
|
| 5405 |
++ writel((DDR_PHYS_TO_PFE |
|
| 5406 |
++ ((u32)dma_map_single(hif->dev, |
|
| 5407 |
++ free_buf, hif->rx_buf_len[rtc], DMA_FROM_DEVICE))), |
|
| 5408 |
++ &desc->data); |
|
| 5409 |
++ /* |
|
| 5410 |
++ * Ensure everything else is written to DDR before |
|
| 5411 |
++ * writing bd->ctrl |
|
| 5412 |
++ */ |
|
| 5413 |
++ wmb(); |
|
| 5414 |
++ writel((BD_CTRL_PKT_INT_EN | BD_CTRL_LIFM | BD_CTRL_DIR | |
|
| 5415 |
++ BD_CTRL_DESC_EN | BD_BUF_LEN(hif->rx_buf_len[rtc])), |
|
| 5416 |
++ &desc->ctrl); |
|
| 5417 |
++ |
|
| 5418 |
++ rtc = (rtc + 1) & (hif->rx_ring_size - 1); |
|
| 5419 |
++ |
|
| 5420 |
++ if (local_desc.ctrl & BD_CTRL_LIFM) {
|
|
| 5421 |
++ if (!(hif->client_ctrl & HIF_CTRL_RX_CONTINUED)) {
|
|
| 5422 |
++ rx_processed++; |
|
| 5423 |
++ |
|
| 5424 |
++#ifdef HIF_NAPI_STATS |
|
| 5425 |
++ hif->napi_counters[NAPI_PACKET_COUNT]++; |
|
| 5426 |
++#endif |
|
| 5427 |
++ } |
|
| 5428 |
++ hif->started = 0; |
|
| 5429 |
++ } |
|
| 5430 |
++ } |
|
| 5431 |
++ |
|
| 5432 |
++ hif->rxtoclean_index = rtc; |
|
| 5433 |
++ spin_unlock_bh(&hif->lock); |
|
| 5434 |
++ |
|
| 5435 |
++ /* we made some progress, re-start rx dma in case it stopped */ |
|
| 5436 |
++ hif_rx_dma_start(); |
|
| 5437 |
++ |
|
| 5438 |
++ return rx_processed; |
|
| 5439 |
++} |
|
| 5440 |
++ |
|
| 5441 |
++/* |
|
| 5442 |
++ * client_ack_txpacket- |
|
| 5443 |
++ * This function ack the Tx packet in the give client Tx queue by resetting |
|
| 5444 |
++ * ownership bit in the descriptor. |
|
| 5445 |
++ */ |
|
| 5446 |
++static int client_ack_txpacket(struct pfe_hif *hif, unsigned int client_id, |
|
| 5447 |
++ unsigned int q_no) |
|
| 5448 |
++{
|
|
| 5449 |
++ struct hif_tx_queue *queue = &hif->client[client_id].tx_q[q_no]; |
|
| 5450 |
++ struct tx_queue_desc *desc = queue->base + queue->ack_idx; |
|
| 5451 |
++ |
|
| 5452 |
++ if (readl(&desc->ctrl) & CL_DESC_OWN) {
|
|
| 5453 |
++ writel((readl(&desc->ctrl) & ~CL_DESC_OWN), &desc->ctrl); |
|
| 5454 |
++ /* queue->ack_idx = (queue->ack_idx + 1) & (queue->size - 1); */ |
|
| 5455 |
++ |
|
| 5456 |
++ return 0; |
|
| 5457 |
++ |
|
| 5458 |
++ } else {
|
|
| 5459 |
++ /*This should not happen */ |
|
| 5460 |
++ pr_err("%s: %d %d %d %d %d %p %d\n", __func__,
|
|
| 5461 |
++ hif->txtosend, hif->txtoclean, hif->txavail, |
|
| 5462 |
++ client_id, q_no, queue, queue->ack_idx); |
|
| 5463 |
++ WARN(1, "%s: doesn't own this descriptor", __func__); |
|
| 5464 |
++ return 1; |
|
| 5465 |
++ } |
|
| 5466 |
++} |
|
| 5467 |
++ |
|
| 5468 |
++void __hif_tx_done_process(struct pfe_hif *hif, int count) |
|
| 5469 |
++{
|
|
| 5470 |
++ struct hif_desc *desc; |
|
| 5471 |
++ struct hif_desc_sw *desc_sw; |
|
| 5472 |
++ int ttc, tx_avl; |
|
| 5473 |
++ int pkts_done[HIF_CLIENTS_MAX] = {0, 0};
|
|
| 5474 |
++ |
|
| 5475 |
++ ttc = hif->txtoclean; |
|
| 5476 |
++ tx_avl = hif->txavail; |
|
| 5477 |
++ |
|
| 5478 |
++ while ((tx_avl < hif->tx_ring_size) && count--) {
|
|
| 5479 |
++ desc = hif->tx_base + ttc; |
|
| 5480 |
++ |
|
| 5481 |
++ if (readl(&desc->ctrl) & BD_CTRL_DESC_EN) |
|
| 5482 |
++ break; |
|
| 5483 |
++ |
|
| 5484 |
++ desc_sw = &hif->tx_sw_queue[ttc]; |
|
| 5485 |
++ |
|
| 5486 |
++ if (desc_sw->data) {
|
|
| 5487 |
++ /* |
|
| 5488 |
++ * dmap_unmap_single(hif->dev, desc_sw->data, |
|
| 5489 |
++ * desc_sw->len, DMA_TO_DEVICE); |
|
| 5490 |
++ */ |
|
| 5491 |
++ dma_unmap_single(hif->dev, desc_sw->data, |
|
| 5492 |
++ desc_sw->len, DMA_TO_DEVICE); |
|
| 5493 |
++ } |
|
| 5494 |
++ |
|
| 5495 |
++ if (desc_sw->client_id > HIF_CLIENTS_MAX) |
|
| 5496 |
++ pr_err("Invalid cl id %d\n", desc_sw->client_id);
|
|
| 5497 |
++ |
|
| 5498 |
++ pkts_done[desc_sw->client_id]++; |
|
| 5499 |
++ |
|
| 5500 |
++ client_ack_txpacket(hif, desc_sw->client_id, desc_sw->q_no); |
|
| 5501 |
++ |
|
| 5502 |
++ ttc = (ttc + 1) & (hif->tx_ring_size - 1); |
|
| 5503 |
++ tx_avl++; |
|
| 5504 |
++ } |
|
| 5505 |
++ |
|
| 5506 |
++ if (pkts_done[0]) |
|
| 5507 |
++ hif_lib_indicate_client(0, EVENT_TXDONE_IND, 0); |
|
| 5508 |
++ if (pkts_done[1]) |
|
| 5509 |
++ hif_lib_indicate_client(1, EVENT_TXDONE_IND, 0); |
|
| 5510 |
++ |
|
| 5511 |
++ hif->txtoclean = ttc; |
|
| 5512 |
++ hif->txavail = tx_avl; |
|
| 5513 |
++ |
|
| 5514 |
++ if (!count) {
|
|
| 5515 |
++ tasklet_schedule(&hif->tx_cleanup_tasklet); |
|
| 5516 |
++ } else {
|
|
| 5517 |
++ /*Enable Tx done interrupt */ |
|
| 5518 |
++ writel(readl_relaxed(HIF_INT_ENABLE) | HIF_TXPKT_INT, |
|
| 5519 |
++ HIF_INT_ENABLE); |
|
| 5520 |
++ } |
|
| 5521 |
++} |
|
| 5522 |
++ |
|
| 5523 |
++static void pfe_tx_do_cleanup(unsigned long data) |
|
| 5524 |
++{
|
|
| 5525 |
++ struct pfe_hif *hif = (struct pfe_hif *)data; |
|
| 5526 |
++ |
|
| 5527 |
++ writel(HIF_INT | HIF_TXPKT_INT, HIF_INT_SRC); |
|
| 5528 |
++ |
|
| 5529 |
++ hif_tx_done_process(hif, 64); |
|
| 5530 |
++} |
|
| 5531 |
++ |
|
| 5532 |
++/* |
|
| 5533 |
++ * __hif_xmit_pkt - |
|
| 5534 |
++ * This function puts one packet in the HIF Tx queue |
|
| 5535 |
++ */ |
|
| 5536 |
++void __hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int |
|
| 5537 |
++ q_no, void *data, u32 len, unsigned int flags) |
|
| 5538 |
++{
|
|
| 5539 |
++ struct hif_desc *desc; |
|
| 5540 |
++ struct hif_desc_sw *desc_sw; |
|
| 5541 |
++ |
|
| 5542 |
++ desc = hif->tx_base + hif->txtosend; |
|
| 5543 |
++ desc_sw = &hif->tx_sw_queue[hif->txtosend]; |
|
| 5544 |
++ |
|
| 5545 |
++ desc_sw->len = len; |
|
| 5546 |
++ desc_sw->client_id = client_id; |
|
| 5547 |
++ desc_sw->q_no = q_no; |
|
| 5548 |
++ desc_sw->flags = flags; |
|
| 5549 |
++ |
|
| 5550 |
++ if (flags & HIF_DONT_DMA_MAP) {
|
|
| 5551 |
++ desc_sw->data = 0; |
|
| 5552 |
++ writel((u32)DDR_PHYS_TO_PFE(data), &desc->data); |
|
| 5553 |
++ } else {
|
|
| 5554 |
++ desc_sw->data = dma_map_single(hif->dev, data, len, |
|
| 5555 |
++ DMA_TO_DEVICE); |
|
| 5556 |
++ writel((u32)DDR_PHYS_TO_PFE(desc_sw->data), &desc->data); |
|
| 5557 |
++ } |
|
| 5558 |
++ |
|
| 5559 |
++ hif->txtosend = (hif->txtosend + 1) & (hif->tx_ring_size - 1); |
|
| 5560 |
++ hif->txavail--; |
|
| 5561 |
++ |
|
| 5562 |
++ if ((!((flags & HIF_DATA_VALID) && (flags & |
|
| 5563 |
++ HIF_LAST_BUFFER)))) |
|
| 5564 |
++ goto skip_tx; |
|
| 5565 |
++ |
|
| 5566 |
++ /* |
|
| 5567 |
++ * Ensure everything else is written to DDR before |
|
| 5568 |
++ * writing bd->ctrl |
|
| 5569 |
++ */ |
|
| 5570 |
++ wmb(); |
|
| 5571 |
++ |
|
| 5572 |
++ do {
|
|
| 5573 |
++ desc_sw = &hif->tx_sw_queue[hif->txtoflush]; |
|
| 5574 |
++ desc = hif->tx_base + hif->txtoflush; |
|
| 5575 |
++ |
|
| 5576 |
++ if (desc_sw->flags & HIF_LAST_BUFFER) {
|
|
| 5577 |
++ writel((BD_CTRL_LIFM | |
|
| 5578 |
++ BD_CTRL_BRFETCH_DISABLE | BD_CTRL_RTFETCH_DISABLE |
|
| 5579 |
++ | BD_CTRL_PARSE_DISABLE | BD_CTRL_DESC_EN | |
|
| 5580 |
++ BD_CTRL_PKT_INT_EN | BD_BUF_LEN(desc_sw->len)), |
|
| 5581 |
++ &desc->ctrl); |
|
| 5582 |
++ } else {
|
|
| 5583 |
++ writel((BD_CTRL_DESC_EN | |
|
| 5584 |
++ BD_BUF_LEN(desc_sw->len)), &desc->ctrl); |
|
| 5585 |
++ } |
|
| 5586 |
++ hif->txtoflush = (hif->txtoflush + 1) & (hif->tx_ring_size - 1); |
|
| 5587 |
++ } |
|
| 5588 |
++ while (hif->txtoflush != hif->txtosend) |
|
| 5589 |
++ ; |
|
| 5590 |
++ |
|
| 5591 |
++skip_tx: |
|
| 5592 |
++ return; |
|
| 5593 |
++} |
|
| 5594 |
++ |
|
| 5595 |
++int hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int q_no, |
|
| 5596 |
++ void *data, unsigned int len) |
|
| 5597 |
++{
|
|
| 5598 |
++ int rc = 0; |
|
| 5599 |
++ |
|
| 5600 |
++ spin_lock_bh(&hif->tx_lock); |
|
| 5601 |
++ |
|
| 5602 |
++ if (!hif->txavail) {
|
|
| 5603 |
++ rc = 1; |
|
| 5604 |
++ } else {
|
|
| 5605 |
++ __hif_xmit_pkt(hif, client_id, q_no, data, len, |
|
| 5606 |
++ HIF_FIRST_BUFFER | HIF_LAST_BUFFER); |
|
| 5607 |
++ hif_tx_dma_start(); |
|
| 5608 |
++ } |
|
| 5609 |
++ |
|
| 5610 |
++ if (hif->txavail < (hif->tx_ring_size >> 1)) |
|
| 5611 |
++ __hif_tx_done_process(hif, TX_FREE_MAX_COUNT); |
|
| 5612 |
++ |
|
| 5613 |
++ spin_unlock_bh(&hif->tx_lock); |
|
| 5614 |
++ |
|
| 5615 |
++ return rc; |
|
| 5616 |
++} |
|
| 5617 |
++ |
|
| 5618 |
++static irqreturn_t wol_isr(int irq, void *dev_id) |
|
| 5619 |
++{
|
|
| 5620 |
++ pr_info("WoL\n");
|
|
| 5621 |
++ gemac_set_wol(EMAC1_BASE_ADDR, 0); |
|
| 5622 |
++ gemac_set_wol(EMAC2_BASE_ADDR, 0); |
|
| 5623 |
++ return IRQ_HANDLED; |
|
| 5624 |
++} |
|
| 5625 |
++ |
|
| 5626 |
++/* |
|
| 5627 |
++ * hif_isr- |
|
| 5628 |
++ * This ISR routine processes Rx/Tx done interrupts from the HIF hardware block |
|
| 5629 |
++ */ |
|
| 5630 |
++static irqreturn_t hif_isr(int irq, void *dev_id) |
|
| 5631 |
++{
|
|
| 5632 |
++ struct pfe_hif *hif = (struct pfe_hif *)dev_id; |
|
| 5633 |
++ int int_status; |
|
| 5634 |
++ int int_enable_mask; |
|
| 5635 |
++ |
|
| 5636 |
++ /*Read hif interrupt source register */ |
|
| 5637 |
++ int_status = readl_relaxed(HIF_INT_SRC); |
|
| 5638 |
++ int_enable_mask = readl_relaxed(HIF_INT_ENABLE); |
|
| 5639 |
++ |
|
| 5640 |
++ if ((int_status & HIF_INT) == 0) |
|
| 5641 |
++ return IRQ_NONE; |
|
| 5642 |
++ |
|
| 5643 |
++ int_status &= ~(HIF_INT); |
|
| 5644 |
++ |
|
| 5645 |
++ if (int_status & HIF_RXPKT_INT) {
|
|
| 5646 |
++ int_status &= ~(HIF_RXPKT_INT); |
|
| 5647 |
++ int_enable_mask &= ~(HIF_RXPKT_INT); |
|
| 5648 |
++ |
|
| 5649 |
++ napi_first_batch = 1; |
|
| 5650 |
++ |
|
| 5651 |
++ if (napi_schedule_prep(&hif->napi)) {
|
|
| 5652 |
++#ifdef HIF_NAPI_STATS |
|
| 5653 |
++ hif->napi_counters[NAPI_SCHED_COUNT]++; |
|
| 5654 |
++#endif |
|
| 5655 |
++ __napi_schedule(&hif->napi); |
|
| 5656 |
++ } |
|
| 5657 |
++ } |
|
| 5658 |
++ if (int_status & HIF_TXPKT_INT) {
|
|
| 5659 |
++ int_status &= ~(HIF_TXPKT_INT); |
|
| 5660 |
++ int_enable_mask &= ~(HIF_TXPKT_INT); |
|
| 5661 |
++ /*Schedule tx cleanup tassklet */ |
|
| 5662 |
++ tasklet_schedule(&hif->tx_cleanup_tasklet); |
|
| 5663 |
++ } |
|
| 5664 |
++ |
|
| 5665 |
++ /*Disable interrupts, they will be enabled after they are serviced */ |
|
| 5666 |
++ writel_relaxed(int_enable_mask, HIF_INT_ENABLE); |
|
| 5667 |
++ |
|
| 5668 |
++ if (int_status) {
|
|
| 5669 |
++ pr_info("%s : Invalid interrupt : %d\n", __func__,
|
|
| 5670 |
++ int_status); |
|
| 5671 |
++ writel(int_status, HIF_INT_SRC); |
|
| 5672 |
++ } |
|
| 5673 |
++ |
|
| 5674 |
++ return IRQ_HANDLED; |
|
| 5675 |
++} |
|
| 5676 |
++ |
|
| 5677 |
++void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int data2) |
|
| 5678 |
++{
|
|
| 5679 |
++ unsigned int client_id = data1; |
|
| 5680 |
++ |
|
| 5681 |
++ if (client_id >= HIF_CLIENTS_MAX) {
|
|
| 5682 |
++ pr_err("%s: client id %d out of bounds\n", __func__,
|
|
| 5683 |
++ client_id); |
|
| 5684 |
++ return; |
|
| 5685 |
++ } |
|
| 5686 |
++ |
|
| 5687 |
++ switch (req) {
|
|
| 5688 |
++ case REQUEST_CL_REGISTER: |
|
| 5689 |
++ /* Request for register a client */ |
|
| 5690 |
++ pr_info("%s: register client_id %d\n",
|
|
| 5691 |
++ __func__, client_id); |
|
| 5692 |
++ pfe_hif_client_register(hif, client_id, (struct |
|
| 5693 |
++ hif_client_shm *)&hif->shm->client[client_id]); |
|
| 5694 |
++ break; |
|
| 5695 |
++ |
|
| 5696 |
++ case REQUEST_CL_UNREGISTER: |
|
| 5697 |
++ pr_info("%s: unregister client_id %d\n",
|
|
| 5698 |
++ __func__, client_id); |
|
| 5699 |
++ |
|
| 5700 |
++ /* Request for unregister a client */ |
|
| 5701 |
++ pfe_hif_client_unregister(hif, client_id); |
|
| 5702 |
++ |
|
| 5703 |
++ break; |
|
| 5704 |
++ |
|
| 5705 |
++ default: |
|
| 5706 |
++ pr_err("%s: unsupported request %d\n",
|
|
| 5707 |
++ __func__, req); |
|
| 5708 |
++ break; |
|
| 5709 |
++ } |
|
| 5710 |
++ |
|
| 5711 |
++ /* |
|
| 5712 |
++ * Process client Tx queues |
|
| 5713 |
++ * Currently we don't have checking for tx pending |
|
| 5714 |
++ */ |
|
| 5715 |
++} |
|
| 5716 |
++ |
|
| 5717 |
++/* |
|
| 5718 |
++ * pfe_hif_rx_poll |
|
| 5719 |
++ * This function is NAPI poll function to process HIF Rx queue. |
|
| 5720 |
++ */ |
|
| 5721 |
++static int pfe_hif_rx_poll(struct napi_struct *napi, int budget) |
|
| 5722 |
++{
|
|
| 5723 |
++ struct pfe_hif *hif = container_of(napi, struct pfe_hif, napi); |
|
| 5724 |
++ int work_done; |
|
| 5725 |
++ |
|
| 5726 |
++#ifdef HIF_NAPI_STATS |
|
| 5727 |
++ hif->napi_counters[NAPI_POLL_COUNT]++; |
|
| 5728 |
++#endif |
|
| 5729 |
++ |
|
| 5730 |
++ work_done = pfe_hif_rx_process(hif, budget); |
|
| 5731 |
++ |
|
| 5732 |
++ if (work_done < budget) {
|
|
| 5733 |
++ napi_complete(napi); |
|
| 5734 |
++ writel(readl_relaxed(HIF_INT_ENABLE) | HIF_RXPKT_INT, |
|
| 5735 |
++ HIF_INT_ENABLE); |
|
| 5736 |
++ } |
|
| 5737 |
++#ifdef HIF_NAPI_STATS |
|
| 5738 |
++ else |
|
| 5739 |
++ hif->napi_counters[NAPI_FULL_BUDGET_COUNT]++; |
|
| 5740 |
++#endif |
|
| 5741 |
++ |
|
| 5742 |
++ return work_done; |
|
| 5743 |
++} |
|
| 5744 |
++ |
|
| 5745 |
++/* |
|
| 5746 |
++ * pfe_hif_init |
|
| 5747 |
++ * This function initializes the baseaddresses and irq, etc. |
|
| 5748 |
++ */ |
|
| 5749 |
++int pfe_hif_init(struct pfe *pfe) |
|
| 5750 |
++{
|
|
| 5751 |
++ struct pfe_hif *hif = &pfe->hif; |
|
| 5752 |
++ int err; |
|
| 5753 |
++ |
|
| 5754 |
++ pr_info("%s\n", __func__);
|
|
| 5755 |
++ |
|
| 5756 |
++ hif->dev = pfe->dev; |
|
| 5757 |
++ hif->irq = pfe->hif_irq; |
|
| 5758 |
++ |
|
| 5759 |
++ err = pfe_hif_alloc_descr(hif); |
|
| 5760 |
++ if (err) |
|
| 5761 |
++ goto err0; |
|
| 5762 |
++ |
|
| 5763 |
++ if (pfe_hif_init_buffers(hif)) {
|
|
| 5764 |
++ pr_err("%s: Could not initialize buffer descriptors\n"
|
|
| 5765 |
++ , __func__); |
|
| 5766 |
++ err = -ENOMEM; |
|
| 5767 |
++ goto err1; |
|
| 5768 |
++ } |
|
| 5769 |
++ |
|
| 5770 |
++ /* Initialize NAPI for Rx processing */ |
|
| 5771 |
++ init_dummy_netdev(&hif->dummy_dev); |
|
| 5772 |
++ netif_napi_add(&hif->dummy_dev, &hif->napi, pfe_hif_rx_poll, |
|
| 5773 |
++ HIF_RX_POLL_WEIGHT); |
|
| 5774 |
++ napi_enable(&hif->napi); |
|
| 5775 |
++ |
|
| 5776 |
++ spin_lock_init(&hif->tx_lock); |
|
| 5777 |
++ spin_lock_init(&hif->lock); |
|
| 5778 |
++ |
|
| 5779 |
++ hif_init(); |
|
| 5780 |
++ hif_rx_enable(); |
|
| 5781 |
++ hif_tx_enable(); |
|
| 5782 |
++ |
|
| 5783 |
++ /* Disable tx done interrupt */ |
|
| 5784 |
++ writel(HIF_INT_MASK, HIF_INT_ENABLE); |
|
| 5785 |
++ |
|
| 5786 |
++ gpi_enable(HGPI_BASE_ADDR); |
|
| 5787 |
++ |
|
| 5788 |
++ err = request_irq(hif->irq, hif_isr, 0, "pfe_hif", hif); |
|
| 5789 |
++ if (err) {
|
|
| 5790 |
++ pr_err("%s: failed to get the hif IRQ = %d\n",
|
|
| 5791 |
++ __func__, hif->irq); |
|
| 5792 |
++ goto err1; |
|
| 5793 |
++ } |
|
| 5794 |
++ |
|
| 5795 |
++ err = request_irq(pfe->wol_irq, wol_isr, 0, "pfe_wol", pfe); |
|
| 5796 |
++ if (err) {
|
|
| 5797 |
++ pr_err("%s: failed to get the wol IRQ = %d\n",
|
|
| 5798 |
++ __func__, pfe->wol_irq); |
|
| 5799 |
++ goto err1; |
|
| 5800 |
++ } |
|
| 5801 |
++ |
|
| 5802 |
++ tasklet_init(&hif->tx_cleanup_tasklet, |
|
| 5803 |
++ (void(*)(unsigned long))pfe_tx_do_cleanup, |
|
| 5804 |
++ (unsigned long)hif); |
|
| 5805 |
++ |
|
| 5806 |
++ return 0; |
|
| 5807 |
++err1: |
|
| 5808 |
++ pfe_hif_free_descr(hif); |
|
| 5809 |
++err0: |
|
| 5810 |
++ return err; |
|
| 5811 |
++} |
|
| 5812 |
++ |
|
| 5813 |
++/* pfe_hif_exit- */ |
|
| 5814 |
++void pfe_hif_exit(struct pfe *pfe) |
|
| 5815 |
++{
|
|
| 5816 |
++ struct pfe_hif *hif = &pfe->hif; |
|
| 5817 |
++ |
|
| 5818 |
++ pr_info("%s\n", __func__);
|
|
| 5819 |
++ |
|
| 5820 |
++ tasklet_kill(&hif->tx_cleanup_tasklet); |
|
| 5821 |
++ |
|
| 5822 |
++ spin_lock_bh(&hif->lock); |
|
| 5823 |
++ hif->shm->g_client_status[0] = 0; |
|
| 5824 |
++ /* Make sure all clients are disabled*/ |
|
| 5825 |
++ hif->shm->g_client_status[1] = 0; |
|
| 5826 |
++ |
|
| 5827 |
++ spin_unlock_bh(&hif->lock); |
|
| 5828 |
++ |
|
| 5829 |
++ /*Disable Rx/Tx */ |
|
| 5830 |
++ gpi_disable(HGPI_BASE_ADDR); |
|
| 5831 |
++ hif_rx_disable(); |
|
| 5832 |
++ hif_tx_disable(); |
|
| 5833 |
++ |
|
| 5834 |
++ napi_disable(&hif->napi); |
|
| 5835 |
++ netif_napi_del(&hif->napi); |
|
| 5836 |
++ |
|
| 5837 |
++ free_irq(pfe->wol_irq, pfe); |
|
| 5838 |
++ free_irq(hif->irq, hif); |
|
| 5839 |
++ |
|
| 5840 |
++ pfe_hif_release_buffers(hif); |
|
| 5841 |
++ pfe_hif_free_descr(hif); |
|
| 5842 |
++} |
|
| 5843 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.c b/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 5844 |
+new file mode 100644 |
|
| 5845 |
+index 000000000000..4274a59257fe |
|
| 5846 |
+--- /dev/null |
|
| 5847 |
+@@ -0,0 +1,638 @@ |
|
| 5848 |
++/* |
|
| 5849 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 5850 |
++ * Copyright 2017 NXP |
|
| 5851 |
++ * |
|
| 5852 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 5853 |
++ * it under the terms of the GNU General Public License as published by |
|
| 5854 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 5855 |
++ * (at your option) any later version. |
|
| 5856 |
++ * |
|
| 5857 |
++ * This program is distributed in the hope that it will be useful, |
|
| 5858 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 5859 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 5860 |
++ * GNU General Public License for more details. |
|
| 5861 |
++ * |
|
| 5862 |
++ * You should have received a copy of the GNU General Public License |
|
| 5863 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 5864 |
++ */ |
|
| 5865 |
++ |
|
| 5866 |
++#include <linux/version.h> |
|
| 5867 |
++#include <linux/kernel.h> |
|
| 5868 |
++#include <linux/slab.h> |
|
| 5869 |
++#include <linux/interrupt.h> |
|
| 5870 |
++#include <linux/workqueue.h> |
|
| 5871 |
++#include <linux/dma-mapping.h> |
|
| 5872 |
++#include <linux/dmapool.h> |
|
| 5873 |
++#include <linux/sched.h> |
|
| 5874 |
++#include <linux/skbuff.h> |
|
| 5875 |
++#include <linux/moduleparam.h> |
|
| 5876 |
++#include <linux/cpu.h> |
|
| 5877 |
++ |
|
| 5878 |
++#include "pfe_mod.h" |
|
| 5879 |
++#include "pfe_hif.h" |
|
| 5880 |
++#include "pfe_hif_lib.h" |
|
| 5881 |
++ |
|
| 5882 |
++unsigned int lro_mode; |
|
| 5883 |
++unsigned int page_mode; |
|
| 5884 |
++unsigned int tx_qos; |
|
| 5885 |
++unsigned int pfe_pkt_size; |
|
| 5886 |
++unsigned int pfe_pkt_headroom; |
|
| 5887 |
++unsigned int emac_txq_cnt; |
|
| 5888 |
++ |
|
| 5889 |
++/* |
|
| 5890 |
++ * @pfe_hal_lib.c. |
|
| 5891 |
++ * Common functions used by HIF client drivers |
|
| 5892 |
++ */ |
|
| 5893 |
++ |
|
| 5894 |
++/*HIF shared memory Global variable */ |
|
| 5895 |
++struct hif_shm ghif_shm; |
|
| 5896 |
++ |
|
| 5897 |
++/* Cleanup the HIF shared memory, release HIF rx_buffer_pool. |
|
| 5898 |
++ * This function should be called after pfe_hif_exit |
|
| 5899 |
++ * |
|
| 5900 |
++ * @param[in] hif_shm Shared memory address location in DDR |
|
| 5901 |
++ */ |
|
| 5902 |
++static void pfe_hif_shm_clean(struct hif_shm *hif_shm) |
|
| 5903 |
++{
|
|
| 5904 |
++ int i; |
|
| 5905 |
++ void *pkt; |
|
| 5906 |
++ |
|
| 5907 |
++ for (i = 0; i < hif_shm->rx_buf_pool_cnt; i++) {
|
|
| 5908 |
++ pkt = hif_shm->rx_buf_pool[i]; |
|
| 5909 |
++ if (pkt) {
|
|
| 5910 |
++ hif_shm->rx_buf_pool[i] = NULL; |
|
| 5911 |
++ pkt -= pfe_pkt_headroom; |
|
| 5912 |
++ |
|
| 5913 |
++ if (page_mode) |
|
| 5914 |
++ put_page(virt_to_page(pkt)); |
|
| 5915 |
++ else |
|
| 5916 |
++ kfree(pkt); |
|
| 5917 |
++ } |
|
| 5918 |
++ } |
|
| 5919 |
++} |
|
| 5920 |
++ |
|
| 5921 |
++/* Initialize shared memory used between HIF driver and clients, |
|
| 5922 |
++ * allocate rx_buffer_pool required for HIF Rx descriptors. |
|
| 5923 |
++ * This function should be called before initializing HIF driver. |
|
| 5924 |
++ * |
|
| 5925 |
++ * @param[in] hif_shm Shared memory address location in DDR |
|
| 5926 |
++ * @rerurn 0 - on succes, <0 on fail to initialize |
|
| 5927 |
++ */ |
|
| 5928 |
++static int pfe_hif_shm_init(struct hif_shm *hif_shm) |
|
| 5929 |
++{
|
|
| 5930 |
++ int i; |
|
| 5931 |
++ void *pkt; |
|
| 5932 |
++ |
|
| 5933 |
++ memset(hif_shm, 0, sizeof(struct hif_shm)); |
|
| 5934 |
++ hif_shm->rx_buf_pool_cnt = HIF_RX_DESC_NT; |
|
| 5935 |
++ |
|
| 5936 |
++ for (i = 0; i < hif_shm->rx_buf_pool_cnt; i++) {
|
|
| 5937 |
++ if (page_mode) {
|
|
| 5938 |
++ pkt = (void *)__get_free_page(GFP_KERNEL | |
|
| 5939 |
++ GFP_DMA_PFE); |
|
| 5940 |
++ } else {
|
|
| 5941 |
++ pkt = kmalloc(PFE_BUF_SIZE, GFP_KERNEL | GFP_DMA_PFE); |
|
| 5942 |
++ } |
|
| 5943 |
++ |
|
| 5944 |
++ if (pkt) |
|
| 5945 |
++ hif_shm->rx_buf_pool[i] = pkt + pfe_pkt_headroom; |
|
| 5946 |
++ else |
|
| 5947 |
++ goto err0; |
|
| 5948 |
++ } |
|
| 5949 |
++ |
|
| 5950 |
++ return 0; |
|
| 5951 |
++ |
|
| 5952 |
++err0: |
|
| 5953 |
++ pr_err("%s Low memory\n", __func__);
|
|
| 5954 |
++ pfe_hif_shm_clean(hif_shm); |
|
| 5955 |
++ return -ENOMEM; |
|
| 5956 |
++} |
|
| 5957 |
++ |
|
| 5958 |
++/*This function sends indication to HIF driver |
|
| 5959 |
++ * |
|
| 5960 |
++ * @param[in] hif hif context |
|
| 5961 |
++ */ |
|
| 5962 |
++static void hif_lib_indicate_hif(struct pfe_hif *hif, int req, int data1, int |
|
| 5963 |
++ data2) |
|
| 5964 |
++{
|
|
| 5965 |
++ hif_process_client_req(hif, req, data1, data2); |
|
| 5966 |
++} |
|
| 5967 |
++ |
|
| 5968 |
++void hif_lib_indicate_client(int client_id, int event_type, int qno) |
|
| 5969 |
++{
|
|
| 5970 |
++ struct hif_client_s *client = pfe->hif_client[client_id]; |
|
| 5971 |
++ |
|
| 5972 |
++ if (!client || (event_type >= HIF_EVENT_MAX) || (qno >= |
|
| 5973 |
++ HIF_CLIENT_QUEUES_MAX)) |
|
| 5974 |
++ return; |
|
| 5975 |
++ |
|
| 5976 |
++ if (!test_and_set_bit(qno, &client->queue_mask[event_type])) |
|
| 5977 |
++ client->event_handler(client->priv, event_type, qno); |
|
| 5978 |
++} |
|
| 5979 |
++ |
|
| 5980 |
++/*This function releases Rx queue descriptors memory and pre-filled buffers |
|
| 5981 |
++ * |
|
| 5982 |
++ * @param[in] client hif_client context |
|
| 5983 |
++ */ |
|
| 5984 |
++static void hif_lib_client_release_rx_buffers(struct hif_client_s *client) |
|
| 5985 |
++{
|
|
| 5986 |
++ struct rx_queue_desc *desc; |
|
| 5987 |
++ int qno, ii; |
|
| 5988 |
++ void *buf; |
|
| 5989 |
++ |
|
| 5990 |
++ for (qno = 0; qno < client->rx_qn; qno++) {
|
|
| 5991 |
++ desc = client->rx_q[qno].base; |
|
| 5992 |
++ |
|
| 5993 |
++ for (ii = 0; ii < client->rx_q[qno].size; ii++) {
|
|
| 5994 |
++ buf = (void *)desc->data; |
|
| 5995 |
++ if (buf) {
|
|
| 5996 |
++ buf -= pfe_pkt_headroom; |
|
| 5997 |
++ |
|
| 5998 |
++ if (page_mode) |
|
| 5999 |
++ free_page((unsigned long)buf); |
|
| 6000 |
++ else |
|
| 6001 |
++ kfree(buf); |
|
| 6002 |
++ |
|
| 6003 |
++ desc->ctrl = 0; |
|
| 6004 |
++ } |
|
| 6005 |
++ |
|
| 6006 |
++ desc++; |
|
| 6007 |
++ } |
|
| 6008 |
++ } |
|
| 6009 |
++ |
|
| 6010 |
++ kfree(client->rx_qbase); |
|
| 6011 |
++} |
|
| 6012 |
++ |
|
| 6013 |
++/*This function allocates memory for the rxq descriptors and pre-fill rx queues |
|
| 6014 |
++ * with buffers. |
|
| 6015 |
++ * @param[in] client client context |
|
| 6016 |
++ * @param[in] q_size size of the rxQ, all queues are of same size |
|
| 6017 |
++ */ |
|
| 6018 |
++static int hif_lib_client_init_rx_buffers(struct hif_client_s *client, int |
|
| 6019 |
++ q_size) |
|
| 6020 |
++{
|
|
| 6021 |
++ struct rx_queue_desc *desc; |
|
| 6022 |
++ struct hif_client_rx_queue *queue; |
|
| 6023 |
++ int ii, qno; |
|
| 6024 |
++ |
|
| 6025 |
++ /*Allocate memory for the client queues */ |
|
| 6026 |
++ client->rx_qbase = kzalloc(client->rx_qn * q_size * sizeof(struct |
|
| 6027 |
++ rx_queue_desc), GFP_KERNEL); |
|
| 6028 |
++ if (!client->rx_qbase) |
|
| 6029 |
++ goto err; |
|
| 6030 |
++ |
|
| 6031 |
++ for (qno = 0; qno < client->rx_qn; qno++) {
|
|
| 6032 |
++ queue = &client->rx_q[qno]; |
|
| 6033 |
++ |
|
| 6034 |
++ queue->base = client->rx_qbase + qno * q_size * sizeof(struct |
|
| 6035 |
++ rx_queue_desc); |
|
| 6036 |
++ queue->size = q_size; |
|
| 6037 |
++ queue->read_idx = 0; |
|
| 6038 |
++ queue->write_idx = 0; |
|
| 6039 |
++ |
|
| 6040 |
++ pr_debug("rx queue: %d, base: %p, size: %d\n", qno,
|
|
| 6041 |
++ queue->base, queue->size); |
|
| 6042 |
++ } |
|
| 6043 |
++ |
|
| 6044 |
++ for (qno = 0; qno < client->rx_qn; qno++) {
|
|
| 6045 |
++ queue = &client->rx_q[qno]; |
|
| 6046 |
++ desc = queue->base; |
|
| 6047 |
++ |
|
| 6048 |
++ for (ii = 0; ii < queue->size; ii++) {
|
|
| 6049 |
++ desc->ctrl = CL_DESC_BUF_LEN(pfe_pkt_size) | |
|
| 6050 |
++ CL_DESC_OWN; |
|
| 6051 |
++ desc++; |
|
| 6052 |
++ } |
|
| 6053 |
++ } |
|
| 6054 |
++ |
|
| 6055 |
++ return 0; |
|
| 6056 |
++ |
|
| 6057 |
++err: |
|
| 6058 |
++ return 1; |
|
| 6059 |
++} |
|
| 6060 |
++ |
|
| 6061 |
++#define inc_cl_idx(idxname) \ |
|
| 6062 |
++ ({ typeof(idxname) idxname_ = (idxname); \
|
|
| 6063 |
++ ((idxname_) = (idxname_ + 1) & (queue->size - 1)); }) |
|
| 6064 |
++ |
|
| 6065 |
++static void hif_lib_client_cleanup_tx_queue(struct hif_client_tx_queue *queue) |
|
| 6066 |
++{
|
|
| 6067 |
++ pr_debug("%s\n", __func__);
|
|
| 6068 |
++ |
|
| 6069 |
++ /* |
|
| 6070 |
++ * Check if there are any pending packets. Client must flush the tx |
|
| 6071 |
++ * queues before unregistering, by calling by calling |
|
| 6072 |
++ * hif_lib_tx_get_next_complete() |
|
| 6073 |
++ * |
|
| 6074 |
++ * Hif no longer calls since we are no longer registered |
|
| 6075 |
++ */ |
|
| 6076 |
++ if (queue->tx_pending) |
|
| 6077 |
++ pr_err("%s: pending transmit packets\n", __func__);
|
|
| 6078 |
++} |
|
| 6079 |
++ |
|
| 6080 |
++static void hif_lib_client_release_tx_buffers(struct hif_client_s *client) |
|
| 6081 |
++{
|
|
| 6082 |
++ int qno; |
|
| 6083 |
++ |
|
| 6084 |
++ pr_debug("%s\n", __func__);
|
|
| 6085 |
++ |
|
| 6086 |
++ for (qno = 0; qno < client->tx_qn; qno++) |
|
| 6087 |
++ hif_lib_client_cleanup_tx_queue(&client->tx_q[qno]); |
|
| 6088 |
++ |
|
| 6089 |
++ kfree(client->tx_qbase); |
|
| 6090 |
++} |
|
| 6091 |
++ |
|
| 6092 |
++static int hif_lib_client_init_tx_buffers(struct hif_client_s *client, int |
|
| 6093 |
++ q_size) |
|
| 6094 |
++{
|
|
| 6095 |
++ struct hif_client_tx_queue *queue; |
|
| 6096 |
++ int qno; |
|
| 6097 |
++ |
|
| 6098 |
++ client->tx_qbase = kzalloc(client->tx_qn * q_size * sizeof(struct |
|
| 6099 |
++ tx_queue_desc), GFP_KERNEL); |
|
| 6100 |
++ if (!client->tx_qbase) |
|
| 6101 |
++ return 1; |
|
| 6102 |
++ |
|
| 6103 |
++ for (qno = 0; qno < client->tx_qn; qno++) {
|
|
| 6104 |
++ queue = &client->tx_q[qno]; |
|
| 6105 |
++ |
|
| 6106 |
++ queue->base = client->tx_qbase + qno * q_size * sizeof(struct |
|
| 6107 |
++ tx_queue_desc); |
|
| 6108 |
++ queue->size = q_size; |
|
| 6109 |
++ queue->read_idx = 0; |
|
| 6110 |
++ queue->write_idx = 0; |
|
| 6111 |
++ queue->tx_pending = 0; |
|
| 6112 |
++ queue->nocpy_flag = 0; |
|
| 6113 |
++ queue->prev_tmu_tx_pkts = 0; |
|
| 6114 |
++ queue->done_tmu_tx_pkts = 0; |
|
| 6115 |
++ |
|
| 6116 |
++ pr_debug("tx queue: %d, base: %p, size: %d\n", qno,
|
|
| 6117 |
++ queue->base, queue->size); |
|
| 6118 |
++ } |
|
| 6119 |
++ |
|
| 6120 |
++ return 0; |
|
| 6121 |
++} |
|
| 6122 |
++ |
|
| 6123 |
++static int hif_lib_event_dummy(void *priv, int event_type, int qno) |
|
| 6124 |
++{
|
|
| 6125 |
++ return 0; |
|
| 6126 |
++} |
|
| 6127 |
++ |
|
| 6128 |
++int hif_lib_client_register(struct hif_client_s *client) |
|
| 6129 |
++{
|
|
| 6130 |
++ struct hif_shm *hif_shm; |
|
| 6131 |
++ struct hif_client_shm *client_shm; |
|
| 6132 |
++ int err, i; |
|
| 6133 |
++ /* int loop_cnt = 0; */ |
|
| 6134 |
++ |
|
| 6135 |
++ pr_debug("%s\n", __func__);
|
|
| 6136 |
++ |
|
| 6137 |
++ /*Allocate memory before spin_lock*/ |
|
| 6138 |
++ if (hif_lib_client_init_rx_buffers(client, client->rx_qsize)) {
|
|
| 6139 |
++ err = -ENOMEM; |
|
| 6140 |
++ goto err_rx; |
|
| 6141 |
++ } |
|
| 6142 |
++ |
|
| 6143 |
++ if (hif_lib_client_init_tx_buffers(client, client->tx_qsize)) {
|
|
| 6144 |
++ err = -ENOMEM; |
|
| 6145 |
++ goto err_tx; |
|
| 6146 |
++ } |
|
| 6147 |
++ |
|
| 6148 |
++ spin_lock_bh(&pfe->hif.lock); |
|
| 6149 |
++ if (!(client->pfe) || (client->id >= HIF_CLIENTS_MAX) || |
|
| 6150 |
++ (pfe->hif_client[client->id])) {
|
|
| 6151 |
++ err = -EINVAL; |
|
| 6152 |
++ goto err; |
|
| 6153 |
++ } |
|
| 6154 |
++ |
|
| 6155 |
++ hif_shm = client->pfe->hif.shm; |
|
| 6156 |
++ |
|
| 6157 |
++ if (!client->event_handler) |
|
| 6158 |
++ client->event_handler = hif_lib_event_dummy; |
|
| 6159 |
++ |
|
| 6160 |
++ /*Initialize client specific shared memory */ |
|
| 6161 |
++ client_shm = (struct hif_client_shm *)&hif_shm->client[client->id]; |
|
| 6162 |
++ client_shm->rx_qbase = (unsigned long int)client->rx_qbase; |
|
| 6163 |
++ client_shm->rx_qsize = client->rx_qsize; |
|
| 6164 |
++ client_shm->tx_qbase = (unsigned long int)client->tx_qbase; |
|
| 6165 |
++ client_shm->tx_qsize = client->tx_qsize; |
|
| 6166 |
++ client_shm->ctrl = (client->tx_qn << CLIENT_CTRL_TX_Q_CNT_OFST) | |
|
| 6167 |
++ (client->rx_qn << CLIENT_CTRL_RX_Q_CNT_OFST); |
|
| 6168 |
++ /* spin_lock_init(&client->rx_lock); */ |
|
| 6169 |
++ |
|
| 6170 |
++ for (i = 0; i < HIF_EVENT_MAX; i++) {
|
|
| 6171 |
++ client->queue_mask[i] = 0; /* |
|
| 6172 |
++ * By default all events are |
|
| 6173 |
++ * unmasked |
|
| 6174 |
++ */ |
|
| 6175 |
++ } |
|
| 6176 |
++ |
|
| 6177 |
++ /*Indicate to HIF driver*/ |
|
| 6178 |
++ hif_lib_indicate_hif(&pfe->hif, REQUEST_CL_REGISTER, client->id, 0); |
|
| 6179 |
++ |
|
| 6180 |
++ pr_debug("%s: client: %p, client_id: %d, tx_qsize: %d, rx_qsize: %d\n",
|
|
| 6181 |
++ __func__, client, client->id, client->tx_qsize, |
|
| 6182 |
++ client->rx_qsize); |
|
| 6183 |
++ |
|
| 6184 |
++ client->cpu_id = -1; |
|
| 6185 |
++ |
|
| 6186 |
++ pfe->hif_client[client->id] = client; |
|
| 6187 |
++ spin_unlock_bh(&pfe->hif.lock); |
|
| 6188 |
++ |
|
| 6189 |
++ return 0; |
|
| 6190 |
++ |
|
| 6191 |
++err: |
|
| 6192 |
++ spin_unlock_bh(&pfe->hif.lock); |
|
| 6193 |
++ hif_lib_client_release_tx_buffers(client); |
|
| 6194 |
++ |
|
| 6195 |
++err_tx: |
|
| 6196 |
++ hif_lib_client_release_rx_buffers(client); |
|
| 6197 |
++ |
|
| 6198 |
++err_rx: |
|
| 6199 |
++ return err; |
|
| 6200 |
++} |
|
| 6201 |
++ |
|
| 6202 |
++int hif_lib_client_unregister(struct hif_client_s *client) |
|
| 6203 |
++{
|
|
| 6204 |
++ struct pfe *pfe = client->pfe; |
|
| 6205 |
++ u32 client_id = client->id; |
|
| 6206 |
++ |
|
| 6207 |
++ pr_info( |
|
| 6208 |
++ "%s : client: %p, client_id: %d, txQ_depth: %d, rxQ_depth: %d\n" |
|
| 6209 |
++ , __func__, client, client->id, client->tx_qsize, |
|
| 6210 |
++ client->rx_qsize); |
|
| 6211 |
++ |
|
| 6212 |
++ spin_lock_bh(&pfe->hif.lock); |
|
| 6213 |
++ hif_lib_indicate_hif(&pfe->hif, REQUEST_CL_UNREGISTER, client->id, 0); |
|
| 6214 |
++ |
|
| 6215 |
++ hif_lib_client_release_tx_buffers(client); |
|
| 6216 |
++ hif_lib_client_release_rx_buffers(client); |
|
| 6217 |
++ pfe->hif_client[client_id] = NULL; |
|
| 6218 |
++ spin_unlock_bh(&pfe->hif.lock); |
|
| 6219 |
++ |
|
| 6220 |
++ return 0; |
|
| 6221 |
++} |
|
| 6222 |
++ |
|
| 6223 |
++int hif_lib_event_handler_start(struct hif_client_s *client, int event, |
|
| 6224 |
++ int qno) |
|
| 6225 |
++{
|
|
| 6226 |
++ struct hif_client_rx_queue *queue = &client->rx_q[qno]; |
|
| 6227 |
++ struct rx_queue_desc *desc = queue->base + queue->read_idx; |
|
| 6228 |
++ |
|
| 6229 |
++ if ((event >= HIF_EVENT_MAX) || (qno >= HIF_CLIENT_QUEUES_MAX)) {
|
|
| 6230 |
++ pr_debug("%s: Unsupported event : %d queue number : %d\n",
|
|
| 6231 |
++ __func__, event, qno); |
|
| 6232 |
++ return -1; |
|
| 6233 |
++ } |
|
| 6234 |
++ |
|
| 6235 |
++ test_and_clear_bit(qno, &client->queue_mask[event]); |
|
| 6236 |
++ |
|
| 6237 |
++ switch (event) {
|
|
| 6238 |
++ case EVENT_RX_PKT_IND: |
|
| 6239 |
++ if (!(desc->ctrl & CL_DESC_OWN)) |
|
| 6240 |
++ hif_lib_indicate_client(client->id, |
|
| 6241 |
++ EVENT_RX_PKT_IND, qno); |
|
| 6242 |
++ break; |
|
| 6243 |
++ |
|
| 6244 |
++ case EVENT_HIGH_RX_WM: |
|
| 6245 |
++ case EVENT_TXDONE_IND: |
|
| 6246 |
++ default: |
|
| 6247 |
++ break; |
|
| 6248 |
++ } |
|
| 6249 |
++ |
|
| 6250 |
++ return 0; |
|
| 6251 |
++} |
|
| 6252 |
++ |
|
| 6253 |
++/* |
|
| 6254 |
++ * This function gets one packet from the specified client queue |
|
| 6255 |
++ * It also refill the rx buffer |
|
| 6256 |
++ */ |
|
| 6257 |
++void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int |
|
| 6258 |
++ *ofst, unsigned int *rx_ctrl, |
|
| 6259 |
++ unsigned int *desc_ctrl, void **priv_data) |
|
| 6260 |
++{
|
|
| 6261 |
++ struct hif_client_rx_queue *queue = &client->rx_q[qno]; |
|
| 6262 |
++ struct rx_queue_desc *desc; |
|
| 6263 |
++ void *pkt = NULL; |
|
| 6264 |
++ |
|
| 6265 |
++ /* |
|
| 6266 |
++ * Following lock is to protect rx queue access from, |
|
| 6267 |
++ * hif_lib_event_handler_start. |
|
| 6268 |
++ * In general below lock is not required, because hif_lib_xmit_pkt and |
|
| 6269 |
++ * hif_lib_event_handler_start are called from napi poll and which is |
|
| 6270 |
++ * not re-entrant. But if some client use in different way this lock is |
|
| 6271 |
++ * required. |
|
| 6272 |
++ */ |
|
| 6273 |
++ /*spin_lock_irqsave(&client->rx_lock, flags); */ |
|
| 6274 |
++ desc = queue->base + queue->read_idx; |
|
| 6275 |
++ if (!(desc->ctrl & CL_DESC_OWN)) {
|
|
| 6276 |
++ pkt = desc->data - pfe_pkt_headroom; |
|
| 6277 |
++ |
|
| 6278 |
++ *rx_ctrl = desc->client_ctrl; |
|
| 6279 |
++ *desc_ctrl = desc->ctrl; |
|
| 6280 |
++ |
|
| 6281 |
++ if (desc->ctrl & CL_DESC_FIRST) {
|
|
| 6282 |
++ u16 size = *rx_ctrl >> HIF_CTRL_RX_OFFSET_OFST; |
|
| 6283 |
++ |
|
| 6284 |
++ if (size) {
|
|
| 6285 |
++ *len = CL_DESC_BUF_LEN(desc->ctrl) - |
|
| 6286 |
++ PFE_PKT_HEADER_SZ - size; |
|
| 6287 |
++ *ofst = pfe_pkt_headroom + PFE_PKT_HEADER_SZ |
|
| 6288 |
++ + size; |
|
| 6289 |
++ *priv_data = desc->data + PFE_PKT_HEADER_SZ; |
|
| 6290 |
++ } else {
|
|
| 6291 |
++ *len = CL_DESC_BUF_LEN(desc->ctrl) - |
|
| 6292 |
++ PFE_PKT_HEADER_SZ; |
|
| 6293 |
++ *ofst = pfe_pkt_headroom + PFE_PKT_HEADER_SZ; |
|
| 6294 |
++ *priv_data = NULL; |
|
| 6295 |
++ } |
|
| 6296 |
++ |
|
| 6297 |
++ } else {
|
|
| 6298 |
++ *len = CL_DESC_BUF_LEN(desc->ctrl); |
|
| 6299 |
++ *ofst = pfe_pkt_headroom; |
|
| 6300 |
++ } |
|
| 6301 |
++ |
|
| 6302 |
++ /* |
|
| 6303 |
++ * Needed so we don't free a buffer/page |
|
| 6304 |
++ * twice on module_exit |
|
| 6305 |
++ */ |
|
| 6306 |
++ desc->data = NULL; |
|
| 6307 |
++ |
|
| 6308 |
++ /* |
|
| 6309 |
++ * Ensure everything else is written to DDR before |
|
| 6310 |
++ * writing bd->ctrl |
|
| 6311 |
++ */ |
|
| 6312 |
++ smp_wmb(); |
|
| 6313 |
++ |
|
| 6314 |
++ desc->ctrl = CL_DESC_BUF_LEN(pfe_pkt_size) | CL_DESC_OWN; |
|
| 6315 |
++ inc_cl_idx(queue->read_idx); |
|
| 6316 |
++ } |
|
| 6317 |
++ |
|
| 6318 |
++ /*spin_unlock_irqrestore(&client->rx_lock, flags); */ |
|
| 6319 |
++ return pkt; |
|
| 6320 |
++} |
|
| 6321 |
++ |
|
| 6322 |
++static inline void hif_hdr_write(struct hif_hdr *pkt_hdr, unsigned int |
|
| 6323 |
++ client_id, unsigned int qno, |
|
| 6324 |
++ u32 client_ctrl) |
|
| 6325 |
++{
|
|
| 6326 |
++ /* Optimize the write since the destinaton may be non-cacheable */ |
|
| 6327 |
++ if (!((unsigned long)pkt_hdr & 0x3)) {
|
|
| 6328 |
++ ((u32 *)pkt_hdr)[0] = (client_ctrl << 16) | (qno << 8) | |
|
| 6329 |
++ client_id; |
|
| 6330 |
++ } else {
|
|
| 6331 |
++ ((u16 *)pkt_hdr)[0] = (qno << 8) | (client_id & 0xFF); |
|
| 6332 |
++ ((u16 *)pkt_hdr)[1] = (client_ctrl & 0xFFFF); |
|
| 6333 |
++ } |
|
| 6334 |
++} |
|
| 6335 |
++ |
|
| 6336 |
++/*This function puts the given packet in the specific client queue */ |
|
| 6337 |
++void __hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void |
|
| 6338 |
++ *data, unsigned int len, u32 client_ctrl, |
|
| 6339 |
++ unsigned int flags, void *client_data) |
|
| 6340 |
++{
|
|
| 6341 |
++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; |
|
| 6342 |
++ struct tx_queue_desc *desc = queue->base + queue->write_idx; |
|
| 6343 |
++ |
|
| 6344 |
++ /* First buffer */ |
|
| 6345 |
++ if (flags & HIF_FIRST_BUFFER) {
|
|
| 6346 |
++ data -= sizeof(struct hif_hdr); |
|
| 6347 |
++ len += sizeof(struct hif_hdr); |
|
| 6348 |
++ |
|
| 6349 |
++ hif_hdr_write(data, client->id, qno, client_ctrl); |
|
| 6350 |
++ } |
|
| 6351 |
++ |
|
| 6352 |
++ desc->data = client_data; |
|
| 6353 |
++ desc->ctrl = CL_DESC_OWN | CL_DESC_FLAGS(flags); |
|
| 6354 |
++ |
|
| 6355 |
++ __hif_xmit_pkt(&pfe->hif, client->id, qno, data, len, flags); |
|
| 6356 |
++ |
|
| 6357 |
++ inc_cl_idx(queue->write_idx); |
|
| 6358 |
++ queue->tx_pending++; |
|
| 6359 |
++ queue->jiffies_last_packet = jiffies; |
|
| 6360 |
++} |
|
| 6361 |
++ |
|
| 6362 |
++/*This function puts the given packet in the specific client queue */ |
|
| 6363 |
++int hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void *data, |
|
| 6364 |
++ unsigned int len, u32 client_ctrl, void *client_data) |
|
| 6365 |
++{
|
|
| 6366 |
++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; |
|
| 6367 |
++ struct tx_queue_desc *desc = queue->base + queue->write_idx; |
|
| 6368 |
++ |
|
| 6369 |
++ if (queue->tx_pending < queue->size) {
|
|
| 6370 |
++ /*Construct pkt header */ |
|
| 6371 |
++ |
|
| 6372 |
++ data -= sizeof(struct hif_hdr); |
|
| 6373 |
++ len += sizeof(struct hif_hdr); |
|
| 6374 |
++ |
|
| 6375 |
++ hif_hdr_write(data, client->id, qno, client_ctrl); |
|
| 6376 |
++ |
|
| 6377 |
++ desc->data = client_data; |
|
| 6378 |
++ desc->ctrl = CL_DESC_OWN | CL_DESC_FLAGS(HIF_FIRST_BUFFER | |
|
| 6379 |
++ HIF_LAST_BUFFER | HIF_DATA_VALID); |
|
| 6380 |
++ |
|
| 6381 |
++ if (hif_xmit_pkt(&pfe->hif, client->id, qno, data, len)) |
|
| 6382 |
++ return 1; |
|
| 6383 |
++ |
|
| 6384 |
++ inc_cl_idx(queue->write_idx); |
|
| 6385 |
++ queue->tx_pending++; |
|
| 6386 |
++ queue->jiffies_last_packet = jiffies; |
|
| 6387 |
++ |
|
| 6388 |
++ return 0; |
|
| 6389 |
++ } |
|
| 6390 |
++ |
|
| 6391 |
++ pr_debug("%s Tx client %d qno %d is full\n", __func__, client->id,
|
|
| 6392 |
++ qno); |
|
| 6393 |
++ return 1; |
|
| 6394 |
++} |
|
| 6395 |
++ |
|
| 6396 |
++void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, |
|
| 6397 |
++ unsigned int *flags, int count) |
|
| 6398 |
++{
|
|
| 6399 |
++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; |
|
| 6400 |
++ struct tx_queue_desc *desc = queue->base + queue->read_idx; |
|
| 6401 |
++ |
|
| 6402 |
++ pr_debug("%s: qno : %d rd_indx: %d pending:%d\n", __func__, qno,
|
|
| 6403 |
++ queue->read_idx, queue->tx_pending); |
|
| 6404 |
++ |
|
| 6405 |
++ if (!queue->tx_pending) |
|
| 6406 |
++ return NULL; |
|
| 6407 |
++ |
|
| 6408 |
++ if (queue->nocpy_flag && !queue->done_tmu_tx_pkts) {
|
|
| 6409 |
++ u32 tmu_tx_pkts = be32_to_cpu(pe_dmem_read(TMU0_ID + |
|
| 6410 |
++ client->id, TMU_DM_TX_TRANS, 4)); |
|
| 6411 |
++ |
|
| 6412 |
++ if (queue->prev_tmu_tx_pkts > tmu_tx_pkts) |
|
| 6413 |
++ queue->done_tmu_tx_pkts = UINT_MAX - |
|
| 6414 |
++ queue->prev_tmu_tx_pkts + tmu_tx_pkts; |
|
| 6415 |
++ else |
|
| 6416 |
++ queue->done_tmu_tx_pkts = tmu_tx_pkts - |
|
| 6417 |
++ queue->prev_tmu_tx_pkts; |
|
| 6418 |
++ |
|
| 6419 |
++ queue->prev_tmu_tx_pkts = tmu_tx_pkts; |
|
| 6420 |
++ |
|
| 6421 |
++ if (!queue->done_tmu_tx_pkts) |
|
| 6422 |
++ return NULL; |
|
| 6423 |
++ } |
|
| 6424 |
++ |
|
| 6425 |
++ if (desc->ctrl & CL_DESC_OWN) |
|
| 6426 |
++ return NULL; |
|
| 6427 |
++ |
|
| 6428 |
++ inc_cl_idx(queue->read_idx); |
|
| 6429 |
++ queue->tx_pending--; |
|
| 6430 |
++ |
|
| 6431 |
++ *flags = CL_DESC_GET_FLAGS(desc->ctrl); |
|
| 6432 |
++ |
|
| 6433 |
++ if (queue->done_tmu_tx_pkts && (*flags & HIF_LAST_BUFFER)) |
|
| 6434 |
++ queue->done_tmu_tx_pkts--; |
|
| 6435 |
++ |
|
| 6436 |
++ return desc->data; |
|
| 6437 |
++} |
|
| 6438 |
++ |
|
| 6439 |
++static void hif_lib_tmu_credit_init(struct pfe *pfe) |
|
| 6440 |
++{
|
|
| 6441 |
++ int i, q; |
|
| 6442 |
++ |
|
| 6443 |
++ for (i = 0; i < NUM_GEMAC_SUPPORT; i++) |
|
| 6444 |
++ for (q = 0; q < emac_txq_cnt; q++) {
|
|
| 6445 |
++ pfe->tmu_credit.tx_credit_max[i][q] = (q == 0) ? |
|
| 6446 |
++ DEFAULT_Q0_QDEPTH : DEFAULT_MAX_QDEPTH; |
|
| 6447 |
++ pfe->tmu_credit.tx_credit[i][q] = |
|
| 6448 |
++ pfe->tmu_credit.tx_credit_max[i][q]; |
|
| 6449 |
++ } |
|
| 6450 |
++} |
|
| 6451 |
++ |
|
| 6452 |
++int pfe_hif_lib_init(struct pfe *pfe) |
|
| 6453 |
++{
|
|
| 6454 |
++ int rc; |
|
| 6455 |
++ |
|
| 6456 |
++ pr_info("%s\n", __func__);
|
|
| 6457 |
++ |
|
| 6458 |
++ if (lro_mode) {
|
|
| 6459 |
++ page_mode = 1; |
|
| 6460 |
++ pfe_pkt_size = min(PAGE_SIZE, MAX_PFE_PKT_SIZE); |
|
| 6461 |
++ pfe_pkt_headroom = 0; |
|
| 6462 |
++ } else {
|
|
| 6463 |
++ page_mode = 0; |
|
| 6464 |
++ pfe_pkt_size = PFE_PKT_SIZE; |
|
| 6465 |
++ pfe_pkt_headroom = PFE_PKT_HEADROOM; |
|
| 6466 |
++ } |
|
| 6467 |
++ |
|
| 6468 |
++ if (tx_qos) |
|
| 6469 |
++ emac_txq_cnt = EMAC_TXQ_CNT / 2; |
|
| 6470 |
++ else |
|
| 6471 |
++ emac_txq_cnt = EMAC_TXQ_CNT; |
|
| 6472 |
++ |
|
| 6473 |
++ hif_lib_tmu_credit_init(pfe); |
|
| 6474 |
++ pfe->hif.shm = &ghif_shm; |
|
| 6475 |
++ rc = pfe_hif_shm_init(pfe->hif.shm); |
|
| 6476 |
++ |
|
| 6477 |
++ return rc; |
|
| 6478 |
++} |
|
| 6479 |
++ |
|
| 6480 |
++void pfe_hif_lib_exit(struct pfe *pfe) |
|
| 6481 |
++{
|
|
| 6482 |
++ pr_info("%s\n", __func__);
|
|
| 6483 |
++ |
|
| 6484 |
++ pfe_hif_shm_clean(pfe->hif.shm); |
|
| 6485 |
++} |
|
| 6486 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hw.c b/drivers/staging/fsl_ppfe/pfe_hw.c |
|
| 6487 |
+new file mode 100644 |
|
| 6488 |
+index 000000000000..16ea2c658257 |
|
| 6489 |
+--- /dev/null |
|
| 6490 |
+@@ -0,0 +1,176 @@ |
|
| 6491 |
++/* |
|
| 6492 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 6493 |
++ * Copyright 2017 NXP |
|
| 6494 |
++ * |
|
| 6495 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 6496 |
++ * it under the terms of the GNU General Public License as published by |
|
| 6497 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 6498 |
++ * (at your option) any later version. |
|
| 6499 |
++ * |
|
| 6500 |
++ * This program is distributed in the hope that it will be useful, |
|
| 6501 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 6502 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 6503 |
++ * GNU General Public License for more details. |
|
| 6504 |
++ * |
|
| 6505 |
++ * You should have received a copy of the GNU General Public License |
|
| 6506 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 6507 |
++ */ |
|
| 6508 |
++ |
|
| 6509 |
++#include "pfe_mod.h" |
|
| 6510 |
++#include "pfe_hw.h" |
|
| 6511 |
++ |
|
| 6512 |
++/* Functions to handle most of pfe hw register initialization */ |
|
| 6513 |
++int pfe_hw_init(struct pfe *pfe, int resume) |
|
| 6514 |
++{
|
|
| 6515 |
++ struct class_cfg class_cfg = {
|
|
| 6516 |
++ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, |
|
| 6517 |
++ .route_table_baseaddr = pfe->ddr_phys_baseaddr + |
|
| 6518 |
++ ROUTE_TABLE_BASEADDR, |
|
| 6519 |
++ .route_table_hash_bits = ROUTE_TABLE_HASH_BITS, |
|
| 6520 |
++ }; |
|
| 6521 |
++ |
|
| 6522 |
++ struct tmu_cfg tmu_cfg = {
|
|
| 6523 |
++ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, |
|
| 6524 |
++ .llm_base_addr = pfe->ddr_phys_baseaddr + TMU_LLM_BASEADDR, |
|
| 6525 |
++ .llm_queue_len = TMU_LLM_QUEUE_LEN, |
|
| 6526 |
++ }; |
|
| 6527 |
++ |
|
| 6528 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 6529 |
++ struct util_cfg util_cfg = {
|
|
| 6530 |
++ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, |
|
| 6531 |
++ }; |
|
| 6532 |
++#endif |
|
| 6533 |
++ |
|
| 6534 |
++ struct BMU_CFG bmu1_cfg = {
|
|
| 6535 |
++ .baseaddr = CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR + |
|
| 6536 |
++ BMU1_LMEM_BASEADDR), |
|
| 6537 |
++ .count = BMU1_BUF_COUNT, |
|
| 6538 |
++ .size = BMU1_BUF_SIZE, |
|
| 6539 |
++ .low_watermark = 10, |
|
| 6540 |
++ .high_watermark = 15, |
|
| 6541 |
++ }; |
|
| 6542 |
++ |
|
| 6543 |
++ struct BMU_CFG bmu2_cfg = {
|
|
| 6544 |
++ .baseaddr = DDR_PHYS_TO_PFE(pfe->ddr_phys_baseaddr + |
|
| 6545 |
++ BMU2_DDR_BASEADDR), |
|
| 6546 |
++ .count = BMU2_BUF_COUNT, |
|
| 6547 |
++ .size = BMU2_BUF_SIZE, |
|
| 6548 |
++ .low_watermark = 250, |
|
| 6549 |
++ .high_watermark = 253, |
|
| 6550 |
++ }; |
|
| 6551 |
++ |
|
| 6552 |
++ struct gpi_cfg egpi1_cfg = {
|
|
| 6553 |
++ .lmem_rtry_cnt = EGPI1_LMEM_RTRY_CNT, |
|
| 6554 |
++ .tmlf_txthres = EGPI1_TMLF_TXTHRES, |
|
| 6555 |
++ .aseq_len = EGPI1_ASEQ_LEN, |
|
| 6556 |
++ .mtip_pause_reg = CBUS_VIRT_TO_PFE(EMAC1_BASE_ADDR + |
|
| 6557 |
++ EMAC_TCNTRL_REG), |
|
| 6558 |
++ }; |
|
| 6559 |
++ |
|
| 6560 |
++ struct gpi_cfg egpi2_cfg = {
|
|
| 6561 |
++ .lmem_rtry_cnt = EGPI2_LMEM_RTRY_CNT, |
|
| 6562 |
++ .tmlf_txthres = EGPI2_TMLF_TXTHRES, |
|
| 6563 |
++ .aseq_len = EGPI2_ASEQ_LEN, |
|
| 6564 |
++ .mtip_pause_reg = CBUS_VIRT_TO_PFE(EMAC2_BASE_ADDR + |
|
| 6565 |
++ EMAC_TCNTRL_REG), |
|
| 6566 |
++ }; |
|
| 6567 |
++ |
|
| 6568 |
++ struct gpi_cfg hgpi_cfg = {
|
|
| 6569 |
++ .lmem_rtry_cnt = HGPI_LMEM_RTRY_CNT, |
|
| 6570 |
++ .tmlf_txthres = HGPI_TMLF_TXTHRES, |
|
| 6571 |
++ .aseq_len = HGPI_ASEQ_LEN, |
|
| 6572 |
++ .mtip_pause_reg = 0, |
|
| 6573 |
++ }; |
|
| 6574 |
++ |
|
| 6575 |
++ pr_info("%s\n", __func__);
|
|
| 6576 |
++ |
|
| 6577 |
++#if !defined(LS1012A_PFE_RESET_WA) |
|
| 6578 |
++ /* LS1012A needs this to make PE work correctly */ |
|
| 6579 |
++ writel(0x3, CLASS_PE_SYS_CLK_RATIO); |
|
| 6580 |
++ writel(0x3, TMU_PE_SYS_CLK_RATIO); |
|
| 6581 |
++ writel(0x3, UTIL_PE_SYS_CLK_RATIO); |
|
| 6582 |
++ usleep_range(10, 20); |
|
| 6583 |
++#endif |
|
| 6584 |
++ |
|
| 6585 |
++ pr_info("CLASS version: %x\n", readl(CLASS_VERSION));
|
|
| 6586 |
++ pr_info("TMU version: %x\n", readl(TMU_VERSION));
|
|
| 6587 |
++ |
|
| 6588 |
++ pr_info("BMU1 version: %x\n", readl(BMU1_BASE_ADDR +
|
|
| 6589 |
++ BMU_VERSION)); |
|
| 6590 |
++ pr_info("BMU2 version: %x\n", readl(BMU2_BASE_ADDR +
|
|
| 6591 |
++ BMU_VERSION)); |
|
| 6592 |
++ |
|
| 6593 |
++ pr_info("EGPI1 version: %x\n", readl(EGPI1_BASE_ADDR +
|
|
| 6594 |
++ GPI_VERSION)); |
|
| 6595 |
++ pr_info("EGPI2 version: %x\n", readl(EGPI2_BASE_ADDR +
|
|
| 6596 |
++ GPI_VERSION)); |
|
| 6597 |
++ pr_info("HGPI version: %x\n", readl(HGPI_BASE_ADDR +
|
|
| 6598 |
++ GPI_VERSION)); |
|
| 6599 |
++ |
|
| 6600 |
++ pr_info("HIF version: %x\n", readl(HIF_VERSION));
|
|
| 6601 |
++ pr_info("HIF NOPCY version: %x\n", readl(HIF_NOCPY_VERSION));
|
|
| 6602 |
++ |
|
| 6603 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 6604 |
++ pr_info("UTIL version: %x\n", readl(UTIL_VERSION));
|
|
| 6605 |
++#endif |
|
| 6606 |
++ while (!(readl(TMU_CTRL) & ECC_MEM_INIT_DONE)) |
|
| 6607 |
++ ; |
|
| 6608 |
++ |
|
| 6609 |
++ hif_rx_disable(); |
|
| 6610 |
++ hif_tx_disable(); |
|
| 6611 |
++ |
|
| 6612 |
++ bmu_init(BMU1_BASE_ADDR, &bmu1_cfg); |
|
| 6613 |
++ |
|
| 6614 |
++ pr_info("bmu_init(1) done\n");
|
|
| 6615 |
++ |
|
| 6616 |
++ bmu_init(BMU2_BASE_ADDR, &bmu2_cfg); |
|
| 6617 |
++ |
|
| 6618 |
++ pr_info("bmu_init(2) done\n");
|
|
| 6619 |
++ |
|
| 6620 |
++ class_cfg.resume = resume ? 1 : 0; |
|
| 6621 |
++ |
|
| 6622 |
++ class_init(&class_cfg); |
|
| 6623 |
++ |
|
| 6624 |
++ pr_info("class_init() done\n");
|
|
| 6625 |
++ |
|
| 6626 |
++ tmu_init(&tmu_cfg); |
|
| 6627 |
++ |
|
| 6628 |
++ pr_info("tmu_init() done\n");
|
|
| 6629 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 6630 |
++ util_init(&util_cfg); |
|
| 6631 |
++ |
|
| 6632 |
++ pr_info("util_init() done\n");
|
|
| 6633 |
++#endif |
|
| 6634 |
++ gpi_init(EGPI1_BASE_ADDR, &egpi1_cfg); |
|
| 6635 |
++ |
|
| 6636 |
++ pr_info("gpi_init(1) done\n");
|
|
| 6637 |
++ |
|
| 6638 |
++ gpi_init(EGPI2_BASE_ADDR, &egpi2_cfg); |
|
| 6639 |
++ |
|
| 6640 |
++ pr_info("gpi_init(2) done\n");
|
|
| 6641 |
++ |
|
| 6642 |
++ gpi_init(HGPI_BASE_ADDR, &hgpi_cfg); |
|
| 6643 |
++ |
|
| 6644 |
++ pr_info("gpi_init(hif) done\n");
|
|
| 6645 |
++ |
|
| 6646 |
++ bmu_enable(BMU1_BASE_ADDR); |
|
| 6647 |
++ |
|
| 6648 |
++ pr_info("bmu_enable(1) done\n");
|
|
| 6649 |
++ |
|
| 6650 |
++ bmu_enable(BMU2_BASE_ADDR); |
|
| 6651 |
++ |
|
| 6652 |
++ pr_info("bmu_enable(2) done\n");
|
|
| 6653 |
++ |
|
| 6654 |
++ return 0; |
|
| 6655 |
++} |
|
| 6656 |
++ |
|
| 6657 |
++void pfe_hw_exit(struct pfe *pfe) |
|
| 6658 |
++{
|
|
| 6659 |
++ pr_info("%s\n", __func__);
|
|
| 6660 |
++ |
|
| 6661 |
++ bmu_disable(BMU1_BASE_ADDR); |
|
| 6662 |
++ bmu_reset(BMU1_BASE_ADDR); |
|
| 6663 |
++ |
|
| 6664 |
++ bmu_disable(BMU2_BASE_ADDR); |
|
| 6665 |
++ bmu_reset(BMU2_BASE_ADDR); |
|
| 6666 |
++} |
|
| 6667 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c b/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c |
|
| 6668 |
+new file mode 100644 |
|
| 6669 |
+index 000000000000..c579eb58f277 |
|
| 6670 |
+--- /dev/null |
|
| 6671 |
+@@ -0,0 +1,394 @@ |
|
| 6672 |
++/* |
|
| 6673 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 6674 |
++ * Copyright 2017 NXP |
|
| 6675 |
++ * |
|
| 6676 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 6677 |
++ * it under the terms of the GNU General Public License as published by |
|
| 6678 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 6679 |
++ * (at your option) any later version. |
|
| 6680 |
++ * |
|
| 6681 |
++ * This program is distributed in the hope that it will be useful, |
|
| 6682 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 6683 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 6684 |
++ * GNU General Public License for more details. |
|
| 6685 |
++ * |
|
| 6686 |
++ * You should have received a copy of the GNU General Public License |
|
| 6687 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 6688 |
++ */ |
|
| 6689 |
++ |
|
| 6690 |
++#include <linux/module.h> |
|
| 6691 |
++#include <linux/device.h> |
|
| 6692 |
++#include <linux/of_net.h> |
|
| 6693 |
++#include <linux/of_address.h> |
|
| 6694 |
++#include <linux/platform_device.h> |
|
| 6695 |
++#include <linux/slab.h> |
|
| 6696 |
++#include <linux/clk.h> |
|
| 6697 |
++#include <linux/mfd/syscon.h> |
|
| 6698 |
++#include <linux/regmap.h> |
|
| 6699 |
++ |
|
| 6700 |
++#include "pfe_mod.h" |
|
| 6701 |
++ |
|
| 6702 |
++struct ls1012a_pfe_platform_data pfe_platform_data; |
|
| 6703 |
++ |
|
| 6704 |
++static int pfe_get_gemac_if_proprties(struct device_node *parent, int port, int |
|
| 6705 |
++ if_cnt, |
|
| 6706 |
++ struct ls1012a_pfe_platform_data |
|
| 6707 |
++ *pdata) |
|
| 6708 |
++{
|
|
| 6709 |
++ struct device_node *gem = NULL, *phy = NULL; |
|
| 6710 |
++ int size; |
|
| 6711 |
++ int ii = 0, phy_id = 0; |
|
| 6712 |
++ const u32 *addr; |
|
| 6713 |
++ const void *mac_addr; |
|
| 6714 |
++ |
|
| 6715 |
++ for (ii = 0; ii < if_cnt; ii++) {
|
|
| 6716 |
++ gem = of_get_next_child(parent, gem); |
|
| 6717 |
++ if (!gem) |
|
| 6718 |
++ goto err; |
|
| 6719 |
++ addr = of_get_property(gem, "reg", &size); |
|
| 6720 |
++ if (addr && (be32_to_cpup(addr) == port)) |
|
| 6721 |
++ break; |
|
| 6722 |
++ } |
|
| 6723 |
++ |
|
| 6724 |
++ if (ii >= if_cnt) {
|
|
| 6725 |
++ pr_err("%s:%d Failed to find interface = %d\n",
|
|
| 6726 |
++ __func__, __LINE__, if_cnt); |
|
| 6727 |
++ goto err; |
|
| 6728 |
++ } |
|
| 6729 |
++ |
|
| 6730 |
++ pdata->ls1012a_eth_pdata[port].gem_id = port; |
|
| 6731 |
++ |
|
| 6732 |
++ mac_addr = of_get_mac_address(gem); |
|
| 6733 |
++ |
|
| 6734 |
++ if (mac_addr) {
|
|
| 6735 |
++ memcpy(pdata->ls1012a_eth_pdata[port].mac_addr, mac_addr, |
|
| 6736 |
++ ETH_ALEN); |
|
| 6737 |
++ } |
|
| 6738 |
++ |
|
| 6739 |
++ pdata->ls1012a_eth_pdata[port].mii_config = of_get_phy_mode(gem); |
|
| 6740 |
++ |
|
| 6741 |
++ if ((pdata->ls1012a_eth_pdata[port].mii_config) < 0) |
|
| 6742 |
++ pr_err("%s:%d Incorrect Phy mode....\n", __func__,
|
|
| 6743 |
++ __LINE__); |
|
| 6744 |
++ |
|
| 6745 |
++ addr = of_get_property(gem, "fsl,gemac-bus-id", &size); |
|
| 6746 |
++ if (!addr) |
|
| 6747 |
++ pr_err("%s:%d Invalid gemac-bus-id....\n", __func__,
|
|
| 6748 |
++ __LINE__); |
|
| 6749 |
++ else |
|
| 6750 |
++ pdata->ls1012a_eth_pdata[port].bus_id = be32_to_cpup(addr); |
|
| 6751 |
++ |
|
| 6752 |
++ addr = of_get_property(gem, "fsl,gemac-phy-id", &size); |
|
| 6753 |
++ if (!addr) {
|
|
| 6754 |
++ pr_err("%s:%d Invalid gemac-phy-id....\n", __func__,
|
|
| 6755 |
++ __LINE__); |
|
| 6756 |
++ } else {
|
|
| 6757 |
++ phy_id = be32_to_cpup(addr); |
|
| 6758 |
++ pdata->ls1012a_eth_pdata[port].phy_id = phy_id; |
|
| 6759 |
++ pdata->ls1012a_mdio_pdata[0].phy_mask &= ~(1 << phy_id); |
|
| 6760 |
++ } |
|
| 6761 |
++ |
|
| 6762 |
++ addr = of_get_property(gem, "fsl,mdio-mux-val", &size); |
|
| 6763 |
++ if (!addr) |
|
| 6764 |
++ pr_err("%s: Invalid mdio-mux-val....\n", __func__);
|
|
| 6765 |
++ else |
|
| 6766 |
++ phy_id = be32_to_cpup(addr); |
|
| 6767 |
++ pdata->ls1012a_eth_pdata[port].mdio_muxval = phy_id; |
|
| 6768 |
++ |
|
| 6769 |
++ if (pdata->ls1012a_eth_pdata[port].phy_id < 32) |
|
| 6770 |
++ pfe->mdio_muxval[pdata->ls1012a_eth_pdata[port].phy_id] = |
|
| 6771 |
++ pdata->ls1012a_eth_pdata[port].mdio_muxval; |
|
| 6772 |
++ |
|
| 6773 |
++ addr = of_get_property(gem, "fsl,pfe-phy-if-flags", &size); |
|
| 6774 |
++ if (!addr) |
|
| 6775 |
++ pr_err("%s:%d Invalid pfe-phy-if-flags....\n",
|
|
| 6776 |
++ __func__, __LINE__); |
|
| 6777 |
++ else |
|
| 6778 |
++ pdata->ls1012a_eth_pdata[port].phy_flags = be32_to_cpup(addr); |
|
| 6779 |
++ |
|
| 6780 |
++ /* If PHY is enabled, read mdio properties */ |
|
| 6781 |
++ if (pdata->ls1012a_eth_pdata[port].phy_flags & GEMAC_NO_PHY) |
|
| 6782 |
++ goto done; |
|
| 6783 |
++ |
|
| 6784 |
++ phy = of_get_next_child(gem, NULL); |
|
| 6785 |
++ |
|
| 6786 |
++ addr = of_get_property(phy, "reg", &size); |
|
| 6787 |
++ |
|
| 6788 |
++ if (!addr) |
|
| 6789 |
++ pr_err("%s:%d Invalid phy enable flag....\n",
|
|
| 6790 |
++ __func__, __LINE__); |
|
| 6791 |
++ else |
|
| 6792 |
++ pdata->ls1012a_mdio_pdata[port].enabled = be32_to_cpup(addr); |
|
| 6793 |
++ |
|
| 6794 |
++ pdata->ls1012a_mdio_pdata[port].irq[0] = PHY_POLL; |
|
| 6795 |
++ |
|
| 6796 |
++done: |
|
| 6797 |
++ |
|
| 6798 |
++ return 0; |
|
| 6799 |
++ |
|
| 6800 |
++err: |
|
| 6801 |
++ return -1; |
|
| 6802 |
++} |
|
| 6803 |
++ |
|
| 6804 |
++/* |
|
| 6805 |
++ * |
|
| 6806 |
++ * pfe_platform_probe - |
|
| 6807 |
++ * |
|
| 6808 |
++ * |
|
| 6809 |
++ */ |
|
| 6810 |
++static int pfe_platform_probe(struct platform_device *pdev) |
|
| 6811 |
++{
|
|
| 6812 |
++ struct resource res; |
|
| 6813 |
++ int ii, rc, interface_count = 0, size = 0; |
|
| 6814 |
++ const u32 *prop; |
|
| 6815 |
++ struct device_node *np; |
|
| 6816 |
++ struct clk *pfe_clk; |
|
| 6817 |
++ |
|
| 6818 |
++ np = pdev->dev.of_node; |
|
| 6819 |
++ |
|
| 6820 |
++ if (!np) {
|
|
| 6821 |
++ pr_err("Invalid device node\n");
|
|
| 6822 |
++ return -EINVAL; |
|
| 6823 |
++ } |
|
| 6824 |
++ |
|
| 6825 |
++ pfe = kzalloc(sizeof(*pfe), GFP_KERNEL); |
|
| 6826 |
++ if (!pfe) {
|
|
| 6827 |
++ rc = -ENOMEM; |
|
| 6828 |
++ goto err_alloc; |
|
| 6829 |
++ } |
|
| 6830 |
++ |
|
| 6831 |
++ platform_set_drvdata(pdev, pfe); |
|
| 6832 |
++ |
|
| 6833 |
++ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); |
|
| 6834 |
++ |
|
| 6835 |
++ if (of_address_to_resource(np, 1, &res)) {
|
|
| 6836 |
++ rc = -ENOMEM; |
|
| 6837 |
++ pr_err("failed to get ddr resource\n");
|
|
| 6838 |
++ goto err_ddr; |
|
| 6839 |
++ } |
|
| 6840 |
++ |
|
| 6841 |
++ pfe->ddr_phys_baseaddr = res.start; |
|
| 6842 |
++ pfe->ddr_size = resource_size(&res); |
|
| 6843 |
++ |
|
| 6844 |
++ pfe->ddr_baseaddr = phys_to_virt(res.start); |
|
| 6845 |
++ if (!pfe->ddr_baseaddr) {
|
|
| 6846 |
++ pr_err("ioremap() ddr failed\n");
|
|
| 6847 |
++ rc = -ENOMEM; |
|
| 6848 |
++ goto err_ddr; |
|
| 6849 |
++ } |
|
| 6850 |
++ |
|
| 6851 |
++ pfe->scfg = |
|
| 6852 |
++ syscon_regmap_lookup_by_phandle(pdev->dev.of_node, |
|
| 6853 |
++ "fsl,pfe-scfg"); |
|
| 6854 |
++ if (IS_ERR(pfe->scfg)) {
|
|
| 6855 |
++ dev_err(&pdev->dev, "No syscfg phandle specified\n"); |
|
| 6856 |
++ return PTR_ERR(pfe->scfg); |
|
| 6857 |
++ } |
|
| 6858 |
++ |
|
| 6859 |
++ pfe->cbus_baseaddr = of_iomap(np, 0); |
|
| 6860 |
++ if (!pfe->cbus_baseaddr) {
|
|
| 6861 |
++ rc = -ENOMEM; |
|
| 6862 |
++ pr_err("failed to get axi resource\n");
|
|
| 6863 |
++ goto err_axi; |
|
| 6864 |
++ } |
|
| 6865 |
++ |
|
| 6866 |
++ pfe->hif_irq = platform_get_irq(pdev, 0); |
|
| 6867 |
++ if (pfe->hif_irq < 0) {
|
|
| 6868 |
++ pr_err("platform_get_irq for hif failed\n");
|
|
| 6869 |
++ rc = pfe->hif_irq; |
|
| 6870 |
++ goto err_hif_irq; |
|
| 6871 |
++ } |
|
| 6872 |
++ |
|
| 6873 |
++ pfe->wol_irq = platform_get_irq(pdev, 2); |
|
| 6874 |
++ if (pfe->wol_irq < 0) {
|
|
| 6875 |
++ pr_err("platform_get_irq for WoL failed\n");
|
|
| 6876 |
++ rc = pfe->wol_irq; |
|
| 6877 |
++ goto err_hif_irq; |
|
| 6878 |
++ } |
|
| 6879 |
++ |
|
| 6880 |
++ /* Read interface count */ |
|
| 6881 |
++ prop = of_get_property(np, "fsl,pfe-num-interfaces", &size); |
|
| 6882 |
++ if (!prop) {
|
|
| 6883 |
++ pr_err("Failed to read number of interfaces\n");
|
|
| 6884 |
++ rc = -ENXIO; |
|
| 6885 |
++ goto err_prop; |
|
| 6886 |
++ } |
|
| 6887 |
++ |
|
| 6888 |
++ interface_count = be32_to_cpup(prop); |
|
| 6889 |
++ if (interface_count <= 0) {
|
|
| 6890 |
++ pr_err("No ethernet interface count : %d\n",
|
|
| 6891 |
++ interface_count); |
|
| 6892 |
++ rc = -ENXIO; |
|
| 6893 |
++ goto err_prop; |
|
| 6894 |
++ } |
|
| 6895 |
++ |
|
| 6896 |
++ pfe_platform_data.ls1012a_mdio_pdata[0].phy_mask = 0xffffffff; |
|
| 6897 |
++ |
|
| 6898 |
++ for (ii = 0; ii < interface_count; ii++) {
|
|
| 6899 |
++ pfe_get_gemac_if_proprties(np, ii, interface_count, |
|
| 6900 |
++ &pfe_platform_data); |
|
| 6901 |
++ } |
|
| 6902 |
++ |
|
| 6903 |
++ pfe->dev = &pdev->dev; |
|
| 6904 |
++ |
|
| 6905 |
++ pfe->dev->platform_data = &pfe_platform_data; |
|
| 6906 |
++ |
|
| 6907 |
++ /* declare WoL capabilities */ |
|
| 6908 |
++ device_init_wakeup(&pdev->dev, true); |
|
| 6909 |
++ |
|
| 6910 |
++ /* find the clocks */ |
|
| 6911 |
++ pfe_clk = devm_clk_get(pfe->dev, "pfe"); |
|
| 6912 |
++ if (IS_ERR(pfe_clk)) |
|
| 6913 |
++ return PTR_ERR(pfe_clk); |
|
| 6914 |
++ |
|
| 6915 |
++ /* PFE clock is (platform clock / 2) */ |
|
| 6916 |
++ /* save sys_clk value as KHz */ |
|
| 6917 |
++ pfe->ctrl.sys_clk = clk_get_rate(pfe_clk) / (2 * 1000); |
|
| 6918 |
++ |
|
| 6919 |
++ rc = pfe_probe(pfe); |
|
| 6920 |
++ if (rc < 0) |
|
| 6921 |
++ goto err_probe; |
|
| 6922 |
++ |
|
| 6923 |
++ return 0; |
|
| 6924 |
++ |
|
| 6925 |
++err_probe: |
|
| 6926 |
++err_prop: |
|
| 6927 |
++err_hif_irq: |
|
| 6928 |
++ iounmap(pfe->cbus_baseaddr); |
|
| 6929 |
++ |
|
| 6930 |
++err_axi: |
|
| 6931 |
++ iounmap(pfe->ddr_baseaddr); |
|
| 6932 |
++ |
|
| 6933 |
++err_ddr: |
|
| 6934 |
++ platform_set_drvdata(pdev, NULL); |
|
| 6935 |
++ |
|
| 6936 |
++ kfree(pfe); |
|
| 6937 |
++ |
|
| 6938 |
++err_alloc: |
|
| 6939 |
++ return rc; |
|
| 6940 |
++} |
|
| 6941 |
++ |
|
| 6942 |
++/* |
|
| 6943 |
++ * pfe_platform_remove - |
|
| 6944 |
++ */ |
|
| 6945 |
++static int pfe_platform_remove(struct platform_device *pdev) |
|
| 6946 |
++{
|
|
| 6947 |
++ struct pfe *pfe = platform_get_drvdata(pdev); |
|
| 6948 |
++ int rc; |
|
| 6949 |
++ |
|
| 6950 |
++ pr_info("%s\n", __func__);
|
|
| 6951 |
++ |
|
| 6952 |
++ rc = pfe_remove(pfe); |
|
| 6953 |
++ |
|
| 6954 |
++ iounmap(pfe->cbus_baseaddr); |
|
| 6955 |
++ iounmap(pfe->ddr_baseaddr); |
|
| 6956 |
++ |
|
| 6957 |
++ platform_set_drvdata(pdev, NULL); |
|
| 6958 |
++ |
|
| 6959 |
++ kfree(pfe); |
|
| 6960 |
++ |
|
| 6961 |
++ return rc; |
|
| 6962 |
++} |
|
| 6963 |
++ |
|
| 6964 |
++#ifdef CONFIG_PM |
|
| 6965 |
++#ifdef CONFIG_PM_SLEEP |
|
| 6966 |
++int pfe_platform_suspend(struct device *dev) |
|
| 6967 |
++{
|
|
| 6968 |
++ struct pfe *pfe = platform_get_drvdata(to_platform_device(dev)); |
|
| 6969 |
++ struct net_device *netdev; |
|
| 6970 |
++ int i; |
|
| 6971 |
++ |
|
| 6972 |
++ pfe->wake = 0; |
|
| 6973 |
++ |
|
| 6974 |
++ for (i = 0; i < (NUM_GEMAC_SUPPORT); i++) {
|
|
| 6975 |
++ netdev = pfe->eth.eth_priv[i]->ndev; |
|
| 6976 |
++ |
|
| 6977 |
++ netif_device_detach(netdev); |
|
| 6978 |
++ |
|
| 6979 |
++ if (netif_running(netdev)) |
|
| 6980 |
++ if (pfe_eth_suspend(netdev)) |
|
| 6981 |
++ pfe->wake = 1; |
|
| 6982 |
++ } |
|
| 6983 |
++ |
|
| 6984 |
++ /* Shutdown PFE only if we're not waking up the system */ |
|
| 6985 |
++ if (!pfe->wake) {
|
|
| 6986 |
++#if defined(LS1012A_PFE_RESET_WA) |
|
| 6987 |
++ pfe_hif_rx_idle(&pfe->hif); |
|
| 6988 |
++#endif |
|
| 6989 |
++ pfe_ctrl_suspend(&pfe->ctrl); |
|
| 6990 |
++ pfe_firmware_exit(pfe); |
|
| 6991 |
++ |
|
| 6992 |
++ pfe_hif_exit(pfe); |
|
| 6993 |
++ pfe_hif_lib_exit(pfe); |
|
| 6994 |
++ |
|
| 6995 |
++ pfe_hw_exit(pfe); |
|
| 6996 |
++ } |
|
| 6997 |
++ |
|
| 6998 |
++ return 0; |
|
| 6999 |
++} |
|
| 7000 |
++ |
|
| 7001 |
++static int pfe_platform_resume(struct device *dev) |
|
| 7002 |
++{
|
|
| 7003 |
++ struct pfe *pfe = platform_get_drvdata(to_platform_device(dev)); |
|
| 7004 |
++ struct net_device *netdev; |
|
| 7005 |
++ int i; |
|
| 7006 |
++ |
|
| 7007 |
++ if (!pfe->wake) {
|
|
| 7008 |
++ pfe_hw_init(pfe, 1); |
|
| 7009 |
++ pfe_hif_lib_init(pfe); |
|
| 7010 |
++ pfe_hif_init(pfe); |
|
| 7011 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7012 |
++ util_enable(); |
|
| 7013 |
++#endif |
|
| 7014 |
++ tmu_enable(0xf); |
|
| 7015 |
++ class_enable(); |
|
| 7016 |
++ pfe_ctrl_resume(&pfe->ctrl); |
|
| 7017 |
++ } |
|
| 7018 |
++ |
|
| 7019 |
++ for (i = 0; i < (NUM_GEMAC_SUPPORT); i++) {
|
|
| 7020 |
++ netdev = pfe->eth.eth_priv[i]->ndev; |
|
| 7021 |
++ |
|
| 7022 |
++ if (pfe->eth.eth_priv[i]->mii_bus) |
|
| 7023 |
++ pfe_eth_mdio_reset(pfe->eth.eth_priv[i]->mii_bus); |
|
| 7024 |
++ |
|
| 7025 |
++ if (netif_running(netdev)) |
|
| 7026 |
++ pfe_eth_resume(netdev); |
|
| 7027 |
++ |
|
| 7028 |
++ netif_device_attach(netdev); |
|
| 7029 |
++ } |
|
| 7030 |
++ return 0; |
|
| 7031 |
++} |
|
| 7032 |
++#else |
|
| 7033 |
++#define pfe_platform_suspend NULL |
|
| 7034 |
++#define pfe_platform_resume NULL |
|
| 7035 |
++#endif |
|
| 7036 |
++ |
|
| 7037 |
++static const struct dev_pm_ops pfe_platform_pm_ops = {
|
|
| 7038 |
++ SET_SYSTEM_SLEEP_PM_OPS(pfe_platform_suspend, pfe_platform_resume) |
|
| 7039 |
++}; |
|
| 7040 |
++#endif |
|
| 7041 |
++ |
|
| 7042 |
++static const struct of_device_id pfe_match[] = {
|
|
| 7043 |
++ {
|
|
| 7044 |
++ .compatible = "fsl,pfe", |
|
| 7045 |
++ }, |
|
| 7046 |
++ {},
|
|
| 7047 |
++}; |
|
| 7048 |
++MODULE_DEVICE_TABLE(of, pfe_match); |
|
| 7049 |
++ |
|
| 7050 |
++static struct platform_driver pfe_platform_driver = {
|
|
| 7051 |
++ .probe = pfe_platform_probe, |
|
| 7052 |
++ .remove = pfe_platform_remove, |
|
| 7053 |
++ .driver = {
|
|
| 7054 |
++ .name = "pfe", |
|
| 7055 |
++ .of_match_table = pfe_match, |
|
| 7056 |
++#ifdef CONFIG_PM |
|
| 7057 |
++ .pm = &pfe_platform_pm_ops, |
|
| 7058 |
++#endif |
|
| 7059 |
++ }, |
|
| 7060 |
++}; |
|
| 7061 |
++ |
|
| 7062 |
++module_platform_driver(pfe_platform_driver); |
|
| 7063 |
++MODULE_LICENSE("GPL");
|
|
| 7064 |
++MODULE_DESCRIPTION("PFE Ethernet driver");
|
|
| 7065 |
++MODULE_AUTHOR("NXP DNCPE");
|
|
| 7066 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_mod.c b/drivers/staging/fsl_ppfe/pfe_mod.c |
|
| 7067 |
+new file mode 100644 |
|
| 7068 |
+index 000000000000..d5ba56a3c73f |
|
| 7069 |
+--- /dev/null |
|
| 7070 |
+@@ -0,0 +1,141 @@ |
|
| 7071 |
++/* |
|
| 7072 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 7073 |
++ * Copyright 2017 NXP |
|
| 7074 |
++ * |
|
| 7075 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 7076 |
++ * it under the terms of the GNU General Public License as published by |
|
| 7077 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 7078 |
++ * (at your option) any later version. |
|
| 7079 |
++ * |
|
| 7080 |
++ * This program is distributed in the hope that it will be useful, |
|
| 7081 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 7082 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 7083 |
++ * GNU General Public License for more details. |
|
| 7084 |
++ * |
|
| 7085 |
++ * You should have received a copy of the GNU General Public License |
|
| 7086 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 7087 |
++ */ |
|
| 7088 |
++ |
|
| 7089 |
++#include <linux/dma-mapping.h> |
|
| 7090 |
++#include "pfe_mod.h" |
|
| 7091 |
++ |
|
| 7092 |
++struct pfe *pfe; |
|
| 7093 |
++ |
|
| 7094 |
++/* |
|
| 7095 |
++ * pfe_probe - |
|
| 7096 |
++ */ |
|
| 7097 |
++int pfe_probe(struct pfe *pfe) |
|
| 7098 |
++{
|
|
| 7099 |
++ int rc; |
|
| 7100 |
++ |
|
| 7101 |
++ if (pfe->ddr_size < DDR_MAX_SIZE) {
|
|
| 7102 |
++ pr_err("%s: required DDR memory (%x) above platform ddr memory (%x)\n",
|
|
| 7103 |
++ __func__, (unsigned int)DDR_MAX_SIZE, pfe->ddr_size); |
|
| 7104 |
++ rc = -ENOMEM; |
|
| 7105 |
++ goto err_hw; |
|
| 7106 |
++ } |
|
| 7107 |
++ |
|
| 7108 |
++ if (((int)(pfe->ddr_phys_baseaddr + BMU2_DDR_BASEADDR) & |
|
| 7109 |
++ (8 * SZ_1M - 1)) != 0) {
|
|
| 7110 |
++ pr_err("%s: BMU2 base address (0x%x) must be aligned on 8MB boundary\n",
|
|
| 7111 |
++ __func__, (int)pfe->ddr_phys_baseaddr + |
|
| 7112 |
++ BMU2_DDR_BASEADDR); |
|
| 7113 |
++ rc = -ENOMEM; |
|
| 7114 |
++ goto err_hw; |
|
| 7115 |
++ } |
|
| 7116 |
++ |
|
| 7117 |
++ pr_info("cbus_baseaddr: %lx, ddr_baseaddr: %lx, ddr_phys_baseaddr: %lx, ddr_size: %x\n",
|
|
| 7118 |
++ (unsigned long)pfe->cbus_baseaddr, |
|
| 7119 |
++ (unsigned long)pfe->ddr_baseaddr, |
|
| 7120 |
++ pfe->ddr_phys_baseaddr, pfe->ddr_size); |
|
| 7121 |
++ |
|
| 7122 |
++ pfe_lib_init(pfe->cbus_baseaddr, pfe->ddr_baseaddr, |
|
| 7123 |
++ pfe->ddr_phys_baseaddr, pfe->ddr_size); |
|
| 7124 |
++ |
|
| 7125 |
++ rc = pfe_hw_init(pfe, 0); |
|
| 7126 |
++ if (rc < 0) |
|
| 7127 |
++ goto err_hw; |
|
| 7128 |
++ |
|
| 7129 |
++ rc = pfe_hif_lib_init(pfe); |
|
| 7130 |
++ if (rc < 0) |
|
| 7131 |
++ goto err_hif_lib; |
|
| 7132 |
++ |
|
| 7133 |
++ rc = pfe_hif_init(pfe); |
|
| 7134 |
++ if (rc < 0) |
|
| 7135 |
++ goto err_hif; |
|
| 7136 |
++ |
|
| 7137 |
++ rc = pfe_firmware_init(pfe); |
|
| 7138 |
++ if (rc < 0) |
|
| 7139 |
++ goto err_firmware; |
|
| 7140 |
++ |
|
| 7141 |
++ rc = pfe_ctrl_init(pfe); |
|
| 7142 |
++ if (rc < 0) |
|
| 7143 |
++ goto err_ctrl; |
|
| 7144 |
++ |
|
| 7145 |
++ rc = pfe_eth_init(pfe); |
|
| 7146 |
++ if (rc < 0) |
|
| 7147 |
++ goto err_eth; |
|
| 7148 |
++ |
|
| 7149 |
++ rc = pfe_sysfs_init(pfe); |
|
| 7150 |
++ if (rc < 0) |
|
| 7151 |
++ goto err_sysfs; |
|
| 7152 |
++ |
|
| 7153 |
++ rc = pfe_debugfs_init(pfe); |
|
| 7154 |
++ if (rc < 0) |
|
| 7155 |
++ goto err_debugfs; |
|
| 7156 |
++ |
|
| 7157 |
++ return 0; |
|
| 7158 |
++ |
|
| 7159 |
++err_debugfs: |
|
| 7160 |
++ pfe_sysfs_exit(pfe); |
|
| 7161 |
++ |
|
| 7162 |
++err_sysfs: |
|
| 7163 |
++ pfe_eth_exit(pfe); |
|
| 7164 |
++ |
|
| 7165 |
++err_eth: |
|
| 7166 |
++ pfe_ctrl_exit(pfe); |
|
| 7167 |
++ |
|
| 7168 |
++err_ctrl: |
|
| 7169 |
++ pfe_firmware_exit(pfe); |
|
| 7170 |
++ |
|
| 7171 |
++err_firmware: |
|
| 7172 |
++ pfe_hif_exit(pfe); |
|
| 7173 |
++ |
|
| 7174 |
++err_hif: |
|
| 7175 |
++ pfe_hif_lib_exit(pfe); |
|
| 7176 |
++ |
|
| 7177 |
++err_hif_lib: |
|
| 7178 |
++ pfe_hw_exit(pfe); |
|
| 7179 |
++ |
|
| 7180 |
++err_hw: |
|
| 7181 |
++ return rc; |
|
| 7182 |
++} |
|
| 7183 |
++ |
|
| 7184 |
++/* |
|
| 7185 |
++ * pfe_remove - |
|
| 7186 |
++ */ |
|
| 7187 |
++int pfe_remove(struct pfe *pfe) |
|
| 7188 |
++{
|
|
| 7189 |
++ pr_info("%s\n", __func__);
|
|
| 7190 |
++ |
|
| 7191 |
++ pfe_debugfs_exit(pfe); |
|
| 7192 |
++ |
|
| 7193 |
++ pfe_sysfs_exit(pfe); |
|
| 7194 |
++ |
|
| 7195 |
++ pfe_eth_exit(pfe); |
|
| 7196 |
++ |
|
| 7197 |
++ pfe_ctrl_exit(pfe); |
|
| 7198 |
++ |
|
| 7199 |
++#if defined(LS1012A_PFE_RESET_WA) |
|
| 7200 |
++ pfe_hif_rx_idle(&pfe->hif); |
|
| 7201 |
++#endif |
|
| 7202 |
++ pfe_firmware_exit(pfe); |
|
| 7203 |
++ |
|
| 7204 |
++ pfe_hif_exit(pfe); |
|
| 7205 |
++ |
|
| 7206 |
++ pfe_hif_lib_exit(pfe); |
|
| 7207 |
++ |
|
| 7208 |
++ pfe_hw_exit(pfe); |
|
| 7209 |
++ |
|
| 7210 |
++ return 0; |
|
| 7211 |
++} |
|
| 7212 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_sysfs.c b/drivers/staging/fsl_ppfe/pfe_sysfs.c |
|
| 7213 |
+new file mode 100644 |
|
| 7214 |
+index 000000000000..2a763844bdcb |
|
| 7215 |
+--- /dev/null |
|
| 7216 |
+@@ -0,0 +1,818 @@ |
|
| 7217 |
++/* |
|
| 7218 |
++ * Copyright 2015-2016 Freescale Semiconductor, Inc. |
|
| 7219 |
++ * Copyright 2017 NXP |
|
| 7220 |
++ * |
|
| 7221 |
++ * This program is free software; you can redistribute it and/or modify |
|
| 7222 |
++ * it under the terms of the GNU General Public License as published by |
|
| 7223 |
++ * the Free Software Foundation; either version 2 of the License, or |
|
| 7224 |
++ * (at your option) any later version. |
|
| 7225 |
++ * |
|
| 7226 |
++ * This program is distributed in the hope that it will be useful, |
|
| 7227 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 7228 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 7229 |
++ * GNU General Public License for more details. |
|
| 7230 |
++ * |
|
| 7231 |
++ * You should have received a copy of the GNU General Public License |
|
| 7232 |
++ * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 7233 |
++ */ |
|
| 7234 |
++ |
|
| 7235 |
++#include <linux/module.h> |
|
| 7236 |
++#include <linux/platform_device.h> |
|
| 7237 |
++ |
|
| 7238 |
++#include "pfe_mod.h" |
|
| 7239 |
++ |
|
| 7240 |
++#define PE_EXCEPTION_DUMP_ADDRESS 0x1fa8 |
|
| 7241 |
++#define NUM_QUEUES 16 |
|
| 7242 |
++ |
|
| 7243 |
++static char register_name[20][5] = {
|
|
| 7244 |
++ "EPC", "ECAS", "EID", "ED", |
|
| 7245 |
++ "r0", "r1", "r2", "r3", |
|
| 7246 |
++ "r4", "r5", "r6", "r7", |
|
| 7247 |
++ "r8", "r9", "r10", "r11", |
|
| 7248 |
++ "r12", "r13", "r14", "r15", |
|
| 7249 |
++}; |
|
| 7250 |
++ |
|
| 7251 |
++static char exception_name[14][20] = {
|
|
| 7252 |
++ "Reset", |
|
| 7253 |
++ "HardwareFailure", |
|
| 7254 |
++ "NMI", |
|
| 7255 |
++ "InstBreakpoint", |
|
| 7256 |
++ "DataBreakpoint", |
|
| 7257 |
++ "Unsupported", |
|
| 7258 |
++ "PrivilegeViolation", |
|
| 7259 |
++ "InstBusError", |
|
| 7260 |
++ "DataBusError", |
|
| 7261 |
++ "AlignmentError", |
|
| 7262 |
++ "ArithmeticError", |
|
| 7263 |
++ "SystemCall", |
|
| 7264 |
++ "MemoryManagement", |
|
| 7265 |
++ "Interrupt", |
|
| 7266 |
++}; |
|
| 7267 |
++ |
|
| 7268 |
++static unsigned long class_do_clear; |
|
| 7269 |
++static unsigned long tmu_do_clear; |
|
| 7270 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7271 |
++static unsigned long util_do_clear; |
|
| 7272 |
++#endif |
|
| 7273 |
++ |
|
| 7274 |
++static ssize_t display_pe_status(char *buf, int id, u32 dmem_addr, unsigned long |
|
| 7275 |
++ do_clear) |
|
| 7276 |
++{
|
|
| 7277 |
++ ssize_t len = 0; |
|
| 7278 |
++ u32 val; |
|
| 7279 |
++ char statebuf[5]; |
|
| 7280 |
++ struct pfe_cpumon *cpumon = &pfe->cpumon; |
|
| 7281 |
++ u32 debug_indicator; |
|
| 7282 |
++ u32 debug[20]; |
|
| 7283 |
++ |
|
| 7284 |
++ *(u32 *)statebuf = pe_dmem_read(id, dmem_addr, 4); |
|
| 7285 |
++ dmem_addr += 4; |
|
| 7286 |
++ |
|
| 7287 |
++ statebuf[4] = '\0'; |
|
| 7288 |
++ len += sprintf(buf + len, "state=%4s ", statebuf); |
|
| 7289 |
++ |
|
| 7290 |
++ val = pe_dmem_read(id, dmem_addr, 4); |
|
| 7291 |
++ dmem_addr += 4; |
|
| 7292 |
++ len += sprintf(buf + len, "ctr=%08x ", cpu_to_be32(val)); |
|
| 7293 |
++ |
|
| 7294 |
++ val = pe_dmem_read(id, dmem_addr, 4); |
|
| 7295 |
++ if (do_clear && val) |
|
| 7296 |
++ pe_dmem_write(id, 0, dmem_addr, 4); |
|
| 7297 |
++ dmem_addr += 4; |
|
| 7298 |
++ len += sprintf(buf + len, "rx=%u ", cpu_to_be32(val)); |
|
| 7299 |
++ |
|
| 7300 |
++ val = pe_dmem_read(id, dmem_addr, 4); |
|
| 7301 |
++ if (do_clear && val) |
|
| 7302 |
++ pe_dmem_write(id, 0, dmem_addr, 4); |
|
| 7303 |
++ dmem_addr += 4; |
|
| 7304 |
++ if (id >= TMU0_ID && id <= TMU_MAX_ID) |
|
| 7305 |
++ len += sprintf(buf + len, "qstatus=%x", cpu_to_be32(val)); |
|
| 7306 |
++ else |
|
| 7307 |
++ len += sprintf(buf + len, "tx=%u", cpu_to_be32(val)); |
|
| 7308 |
++ |
|
| 7309 |
++ val = pe_dmem_read(id, dmem_addr, 4); |
|
| 7310 |
++ if (do_clear && val) |
|
| 7311 |
++ pe_dmem_write(id, 0, dmem_addr, 4); |
|
| 7312 |
++ dmem_addr += 4; |
|
| 7313 |
++ if (val) |
|
| 7314 |
++ len += sprintf(buf + len, " drop=%u", cpu_to_be32(val)); |
|
| 7315 |
++ |
|
| 7316 |
++ len += sprintf(buf + len, " load=%d%%", cpumon->cpu_usage_pct[id]); |
|
| 7317 |
++ |
|
| 7318 |
++ len += sprintf(buf + len, "\n"); |
|
| 7319 |
++ |
|
| 7320 |
++ debug_indicator = pe_dmem_read(id, dmem_addr, 4); |
|
| 7321 |
++ dmem_addr += 4; |
|
| 7322 |
++ if (!strncmp((char *)&debug_indicator, "DBUG", 4)) {
|
|
| 7323 |
++ int j, last = 0; |
|
| 7324 |
++ |
|
| 7325 |
++ for (j = 0; j < 16; j++) {
|
|
| 7326 |
++ debug[j] = pe_dmem_read(id, dmem_addr, 4); |
|
| 7327 |
++ if (debug[j]) {
|
|
| 7328 |
++ if (do_clear) |
|
| 7329 |
++ pe_dmem_write(id, 0, dmem_addr, 4); |
|
| 7330 |
++ last = j + 1; |
|
| 7331 |
++ } |
|
| 7332 |
++ dmem_addr += 4; |
|
| 7333 |
++ } |
|
| 7334 |
++ for (j = 0; j < last; j++) {
|
|
| 7335 |
++ len += sprintf(buf + len, "%08x%s", |
|
| 7336 |
++ cpu_to_be32(debug[j]), |
|
| 7337 |
++ (j & 0x7) == 0x7 || j == last - 1 ? "\n" : " "); |
|
| 7338 |
++ } |
|
| 7339 |
++ } |
|
| 7340 |
++ |
|
| 7341 |
++ if (!strncmp(statebuf, "DEAD", 4)) {
|
|
| 7342 |
++ u32 i, dump = PE_EXCEPTION_DUMP_ADDRESS; |
|
| 7343 |
++ |
|
| 7344 |
++ len += sprintf(buf + len, "Exception details:\n"); |
|
| 7345 |
++ for (i = 0; i < 20; i++) {
|
|
| 7346 |
++ debug[i] = pe_dmem_read(id, dump, 4); |
|
| 7347 |
++ dump += 4; |
|
| 7348 |
++ if (i == 2) |
|
| 7349 |
++ len += sprintf(buf + len, "%4s = %08x (=%s) ", |
|
| 7350 |
++ register_name[i], cpu_to_be32(debug[i]), |
|
| 7351 |
++ exception_name[min((u32) |
|
| 7352 |
++ cpu_to_be32(debug[i]), (u32)13)]); |
|
| 7353 |
++ else |
|
| 7354 |
++ len += sprintf(buf + len, "%4s = %08x%s", |
|
| 7355 |
++ register_name[i], cpu_to_be32(debug[i]), |
|
| 7356 |
++ (i & 0x3) == 0x3 || i == 19 ? "\n" : " "); |
|
| 7357 |
++ } |
|
| 7358 |
++ } |
|
| 7359 |
++ |
|
| 7360 |
++ return len; |
|
| 7361 |
++} |
|
| 7362 |
++ |
|
| 7363 |
++static ssize_t class_phy_stats(char *buf, int phy) |
|
| 7364 |
++{
|
|
| 7365 |
++ ssize_t len = 0; |
|
| 7366 |
++ int off1 = phy * 0x28; |
|
| 7367 |
++ int off2 = phy * 0x10; |
|
| 7368 |
++ |
|
| 7369 |
++ if (phy == 3) |
|
| 7370 |
++ off1 = CLASS_PHY4_RX_PKTS - CLASS_PHY1_RX_PKTS; |
|
| 7371 |
++ |
|
| 7372 |
++ len += sprintf(buf + len, "phy: %d\n", phy); |
|
| 7373 |
++ len += sprintf(buf + len, |
|
| 7374 |
++ " rx: %10u, tx: %10u, intf: %10u, ipv4: %10u, ipv6: %10u\n", |
|
| 7375 |
++ readl(CLASS_PHY1_RX_PKTS + off1), |
|
| 7376 |
++ readl(CLASS_PHY1_TX_PKTS + off1), |
|
| 7377 |
++ readl(CLASS_PHY1_INTF_MATCH_PKTS + off1), |
|
| 7378 |
++ readl(CLASS_PHY1_V4_PKTS + off1), |
|
| 7379 |
++ readl(CLASS_PHY1_V6_PKTS + off1)); |
|
| 7380 |
++ |
|
| 7381 |
++ len += sprintf(buf + len, |
|
| 7382 |
++ " icmp: %10u, igmp: %10u, tcp: %10u, udp: %10u\n", |
|
| 7383 |
++ readl(CLASS_PHY1_ICMP_PKTS + off2), |
|
| 7384 |
++ readl(CLASS_PHY1_IGMP_PKTS + off2), |
|
| 7385 |
++ readl(CLASS_PHY1_TCP_PKTS + off2), |
|
| 7386 |
++ readl(CLASS_PHY1_UDP_PKTS + off2)); |
|
| 7387 |
++ |
|
| 7388 |
++ len += sprintf(buf + len, " err\n"); |
|
| 7389 |
++ len += sprintf(buf + len, |
|
| 7390 |
++ " lp: %10u, intf: %10u, l3: %10u, chcksum: %10u, ttl: %10u\n", |
|
| 7391 |
++ readl(CLASS_PHY1_LP_FAIL_PKTS + off1), |
|
| 7392 |
++ readl(CLASS_PHY1_INTF_FAIL_PKTS + off1), |
|
| 7393 |
++ readl(CLASS_PHY1_L3_FAIL_PKTS + off1), |
|
| 7394 |
++ readl(CLASS_PHY1_CHKSUM_ERR_PKTS + off1), |
|
| 7395 |
++ readl(CLASS_PHY1_TTL_ERR_PKTS + off1)); |
|
| 7396 |
++ |
|
| 7397 |
++ return len; |
|
| 7398 |
++} |
|
| 7399 |
++ |
|
| 7400 |
++/* qm_read_drop_stat |
|
| 7401 |
++ * This function is used to read the drop statistics from the TMU |
|
| 7402 |
++ * hw drop counter. Since the hw counter is always cleared afer |
|
| 7403 |
++ * reading, this function maintains the previous drop count, and |
|
| 7404 |
++ * adds the new value to it. That value can be retrieved by |
|
| 7405 |
++ * passing a pointer to it with the total_drops arg. |
|
| 7406 |
++ * |
|
| 7407 |
++ * @param tmu TMU number (0 - 3) |
|
| 7408 |
++ * @param queue queue number (0 - 15) |
|
| 7409 |
++ * @param total_drops pointer to location to store total drops (or NULL) |
|
| 7410 |
++ * @param do_reset if TRUE, clear total drops after updating |
|
| 7411 |
++ */ |
|
| 7412 |
++u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset) |
|
| 7413 |
++{
|
|
| 7414 |
++ static u32 qtotal[TMU_MAX_ID + 1][NUM_QUEUES]; |
|
| 7415 |
++ u32 val; |
|
| 7416 |
++ |
|
| 7417 |
++ writel((tmu << 8) | queue, TMU_TEQ_CTRL); |
|
| 7418 |
++ writel((tmu << 8) | queue, TMU_LLM_CTRL); |
|
| 7419 |
++ val = readl(TMU_TEQ_DROP_STAT); |
|
| 7420 |
++ qtotal[tmu][queue] += val; |
|
| 7421 |
++ if (total_drops) |
|
| 7422 |
++ *total_drops = qtotal[tmu][queue]; |
|
| 7423 |
++ if (do_reset) |
|
| 7424 |
++ qtotal[tmu][queue] = 0; |
|
| 7425 |
++ return val; |
|
| 7426 |
++} |
|
| 7427 |
++ |
|
| 7428 |
++static ssize_t tmu_queue_stats(char *buf, int tmu, int queue) |
|
| 7429 |
++{
|
|
| 7430 |
++ ssize_t len = 0; |
|
| 7431 |
++ u32 drops; |
|
| 7432 |
++ |
|
| 7433 |
++ len += sprintf(buf + len, "%d-%02d, ", tmu, queue); |
|
| 7434 |
++ |
|
| 7435 |
++ drops = qm_read_drop_stat(tmu, queue, NULL, 0); |
|
| 7436 |
++ |
|
| 7437 |
++ /* Select queue */ |
|
| 7438 |
++ writel((tmu << 8) | queue, TMU_TEQ_CTRL); |
|
| 7439 |
++ writel((tmu << 8) | queue, TMU_LLM_CTRL); |
|
| 7440 |
++ |
|
| 7441 |
++ len += sprintf(buf + len, |
|
| 7442 |
++ "(teq) drop: %10u, tx: %10u (llm) head: %08x, tail: %08x, drop: %10u\n", |
|
| 7443 |
++ drops, readl(TMU_TEQ_TRANS_STAT), |
|
| 7444 |
++ readl(TMU_LLM_QUE_HEADPTR), readl(TMU_LLM_QUE_TAILPTR), |
|
| 7445 |
++ readl(TMU_LLM_QUE_DROPCNT)); |
|
| 7446 |
++ |
|
| 7447 |
++ return len; |
|
| 7448 |
++} |
|
| 7449 |
++ |
|
| 7450 |
++static ssize_t tmu_queues(char *buf, int tmu) |
|
| 7451 |
++{
|
|
| 7452 |
++ ssize_t len = 0; |
|
| 7453 |
++ int queue; |
|
| 7454 |
++ |
|
| 7455 |
++ for (queue = 0; queue < 16; queue++) |
|
| 7456 |
++ len += tmu_queue_stats(buf + len, tmu, queue); |
|
| 7457 |
++ |
|
| 7458 |
++ return len; |
|
| 7459 |
++} |
|
| 7460 |
++ |
|
| 7461 |
++static ssize_t block_version(char *buf, void *addr) |
|
| 7462 |
++{
|
|
| 7463 |
++ ssize_t len = 0; |
|
| 7464 |
++ u32 val; |
|
| 7465 |
++ |
|
| 7466 |
++ val = readl(addr); |
|
| 7467 |
++ len += sprintf(buf + len, "revision: %x, version: %x, id: %x\n", |
|
| 7468 |
++ (val >> 24) & 0xff, (val >> 16) & 0xff, val & 0xffff); |
|
| 7469 |
++ |
|
| 7470 |
++ return len; |
|
| 7471 |
++} |
|
| 7472 |
++ |
|
| 7473 |
++static ssize_t bmu(char *buf, int id, void *base) |
|
| 7474 |
++{
|
|
| 7475 |
++ ssize_t len = 0; |
|
| 7476 |
++ |
|
| 7477 |
++ len += sprintf(buf + len, "%s: %d\n ", __func__, id); |
|
| 7478 |
++ |
|
| 7479 |
++ len += block_version(buf + len, base + BMU_VERSION); |
|
| 7480 |
++ |
|
| 7481 |
++ len += sprintf(buf + len, " buf size: %x\n", (1 << readl(base + |
|
| 7482 |
++ BMU_BUF_SIZE))); |
|
| 7483 |
++ len += sprintf(buf + len, " buf count: %x\n", readl(base + |
|
| 7484 |
++ BMU_BUF_CNT)); |
|
| 7485 |
++ len += sprintf(buf + len, " buf rem: %x\n", readl(base + |
|
| 7486 |
++ BMU_REM_BUF_CNT)); |
|
| 7487 |
++ len += sprintf(buf + len, " buf curr: %x\n", readl(base + |
|
| 7488 |
++ BMU_CURR_BUF_CNT)); |
|
| 7489 |
++ len += sprintf(buf + len, " free err: %x\n", readl(base + |
|
| 7490 |
++ BMU_FREE_ERR_ADDR)); |
|
| 7491 |
++ |
|
| 7492 |
++ return len; |
|
| 7493 |
++} |
|
| 7494 |
++ |
|
| 7495 |
++static ssize_t gpi(char *buf, int id, void *base) |
|
| 7496 |
++{
|
|
| 7497 |
++ ssize_t len = 0; |
|
| 7498 |
++ u32 val; |
|
| 7499 |
++ |
|
| 7500 |
++ len += sprintf(buf + len, "%s%d:\n ", __func__, id); |
|
| 7501 |
++ len += block_version(buf + len, base + GPI_VERSION); |
|
| 7502 |
++ |
|
| 7503 |
++ len += sprintf(buf + len, " tx under stick: %x\n", readl(base + |
|
| 7504 |
++ GPI_FIFO_STATUS)); |
|
| 7505 |
++ val = readl(base + GPI_FIFO_DEBUG); |
|
| 7506 |
++ len += sprintf(buf + len, " tx pkts: %x\n", (val >> 23) & |
|
| 7507 |
++ 0x3f); |
|
| 7508 |
++ len += sprintf(buf + len, " rx pkts: %x\n", (val >> 18) & |
|
| 7509 |
++ 0x3f); |
|
| 7510 |
++ len += sprintf(buf + len, " tx bytes: %x\n", (val >> 9) & |
|
| 7511 |
++ 0x1ff); |
|
| 7512 |
++ len += sprintf(buf + len, " rx bytes: %x\n", (val >> 0) & |
|
| 7513 |
++ 0x1ff); |
|
| 7514 |
++ len += sprintf(buf + len, " overrun: %x\n", readl(base + |
|
| 7515 |
++ GPI_OVERRUN_DROPCNT)); |
|
| 7516 |
++ |
|
| 7517 |
++ return len; |
|
| 7518 |
++} |
|
| 7519 |
++ |
|
| 7520 |
++static ssize_t pfe_set_class(struct device *dev, struct device_attribute *attr, |
|
| 7521 |
++ const char *buf, size_t count) |
|
| 7522 |
++{
|
|
| 7523 |
++ class_do_clear = kstrtoul(buf, 0, 0); |
|
| 7524 |
++ return count; |
|
| 7525 |
++} |
|
| 7526 |
++ |
|
| 7527 |
++static ssize_t pfe_show_class(struct device *dev, struct device_attribute *attr, |
|
| 7528 |
++ char *buf) |
|
| 7529 |
++{
|
|
| 7530 |
++ ssize_t len = 0; |
|
| 7531 |
++ int id; |
|
| 7532 |
++ u32 val; |
|
| 7533 |
++ struct pfe_cpumon *cpumon = &pfe->cpumon; |
|
| 7534 |
++ |
|
| 7535 |
++ len += block_version(buf + len, CLASS_VERSION); |
|
| 7536 |
++ |
|
| 7537 |
++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) {
|
|
| 7538 |
++ len += sprintf(buf + len, "%d: ", id - CLASS0_ID); |
|
| 7539 |
++ |
|
| 7540 |
++ val = readl(CLASS_PE0_DEBUG + id * 4); |
|
| 7541 |
++ len += sprintf(buf + len, "pc=1%04x ", val & 0xffff); |
|
| 7542 |
++ |
|
| 7543 |
++ len += display_pe_status(buf + len, id, CLASS_DM_PESTATUS, |
|
| 7544 |
++ class_do_clear); |
|
| 7545 |
++ } |
|
| 7546 |
++ len += sprintf(buf + len, "aggregate load=%d%%\n\n", |
|
| 7547 |
++ cpumon->class_usage_pct); |
|
| 7548 |
++ |
|
| 7549 |
++ len += sprintf(buf + len, "pe status: 0x%x\n", |
|
| 7550 |
++ readl(CLASS_PE_STATUS)); |
|
| 7551 |
++ len += sprintf(buf + len, "max buf cnt: 0x%x afull thres: 0x%x\n", |
|
| 7552 |
++ readl(CLASS_MAX_BUF_CNT), readl(CLASS_AFULL_THRES)); |
|
| 7553 |
++ len += sprintf(buf + len, "tsq max cnt: 0x%x tsq fifo thres: 0x%x\n", |
|
| 7554 |
++ readl(CLASS_TSQ_MAX_CNT), readl(CLASS_TSQ_FIFO_THRES)); |
|
| 7555 |
++ len += sprintf(buf + len, "state: 0x%x\n", readl(CLASS_STATE)); |
|
| 7556 |
++ |
|
| 7557 |
++ len += class_phy_stats(buf + len, 0); |
|
| 7558 |
++ len += class_phy_stats(buf + len, 1); |
|
| 7559 |
++ len += class_phy_stats(buf + len, 2); |
|
| 7560 |
++ len += class_phy_stats(buf + len, 3); |
|
| 7561 |
++ |
|
| 7562 |
++ return len; |
|
| 7563 |
++} |
|
| 7564 |
++ |
|
| 7565 |
++static ssize_t pfe_set_tmu(struct device *dev, struct device_attribute *attr, |
|
| 7566 |
++ const char *buf, size_t count) |
|
| 7567 |
++{
|
|
| 7568 |
++ tmu_do_clear = kstrtoul(buf, 0, 0); |
|
| 7569 |
++ return count; |
|
| 7570 |
++} |
|
| 7571 |
++ |
|
| 7572 |
++static ssize_t pfe_show_tmu(struct device *dev, struct device_attribute *attr, |
|
| 7573 |
++ char *buf) |
|
| 7574 |
++{
|
|
| 7575 |
++ ssize_t len = 0; |
|
| 7576 |
++ int id; |
|
| 7577 |
++ u32 val; |
|
| 7578 |
++ |
|
| 7579 |
++ len += block_version(buf + len, TMU_VERSION); |
|
| 7580 |
++ |
|
| 7581 |
++ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) {
|
|
| 7582 |
++ if (id == TMU2_ID) |
|
| 7583 |
++ continue; |
|
| 7584 |
++ len += sprintf(buf + len, "%d: ", id - TMU0_ID); |
|
| 7585 |
++ |
|
| 7586 |
++ len += display_pe_status(buf + len, id, TMU_DM_PESTATUS, |
|
| 7587 |
++ tmu_do_clear); |
|
| 7588 |
++ } |
|
| 7589 |
++ |
|
| 7590 |
++ len += sprintf(buf + len, "pe status: %x\n", readl(TMU_PE_STATUS)); |
|
| 7591 |
++ len += sprintf(buf + len, "inq fifo cnt: %x\n", |
|
| 7592 |
++ readl(TMU_PHY_INQ_FIFO_CNT)); |
|
| 7593 |
++ val = readl(TMU_INQ_STAT); |
|
| 7594 |
++ len += sprintf(buf + len, "inq wr ptr: %x\n", val & 0x3ff); |
|
| 7595 |
++ len += sprintf(buf + len, "inq rd ptr: %x\n", val >> 10); |
|
| 7596 |
++ |
|
| 7597 |
++ return len; |
|
| 7598 |
++} |
|
| 7599 |
++ |
|
| 7600 |
++static unsigned long drops_do_clear; |
|
| 7601 |
++static u32 class_drop_counter[CLASS_NUM_DROP_COUNTERS]; |
|
| 7602 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7603 |
++static u32 util_drop_counter[UTIL_NUM_DROP_COUNTERS]; |
|
| 7604 |
++#endif |
|
| 7605 |
++ |
|
| 7606 |
++char *class_drop_description[CLASS_NUM_DROP_COUNTERS] = {
|
|
| 7607 |
++ "ICC", |
|
| 7608 |
++ "Host Pkt Error", |
|
| 7609 |
++ "Rx Error", |
|
| 7610 |
++ "IPsec Outbound", |
|
| 7611 |
++ "IPsec Inbound", |
|
| 7612 |
++ "EXPT IPsec Error", |
|
| 7613 |
++ "Reassembly", |
|
| 7614 |
++ "Fragmenter", |
|
| 7615 |
++ "NAT-T", |
|
| 7616 |
++ "Socket", |
|
| 7617 |
++ "Multicast", |
|
| 7618 |
++ "NAT-PT", |
|
| 7619 |
++ "Tx Disabled", |
|
| 7620 |
++}; |
|
| 7621 |
++ |
|
| 7622 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7623 |
++char *util_drop_description[UTIL_NUM_DROP_COUNTERS] = {
|
|
| 7624 |
++ "IPsec Outbound", |
|
| 7625 |
++ "IPsec Inbound", |
|
| 7626 |
++ "IPsec Rate Limiter", |
|
| 7627 |
++ "Fragmenter", |
|
| 7628 |
++ "Socket", |
|
| 7629 |
++ "Tx Disabled", |
|
| 7630 |
++ "Rx Error", |
|
| 7631 |
++}; |
|
| 7632 |
++#endif |
|
| 7633 |
++ |
|
| 7634 |
++static ssize_t pfe_set_drops(struct device *dev, struct device_attribute *attr, |
|
| 7635 |
++ const char *buf, size_t count) |
|
| 7636 |
++{
|
|
| 7637 |
++ drops_do_clear = kstrtoul(buf, 0, 0); |
|
| 7638 |
++ return count; |
|
| 7639 |
++} |
|
| 7640 |
++ |
|
| 7641 |
++static u32 tmu_drops[4][16]; |
|
| 7642 |
++static ssize_t pfe_show_drops(struct device *dev, struct device_attribute *attr, |
|
| 7643 |
++ char *buf) |
|
| 7644 |
++{
|
|
| 7645 |
++ ssize_t len = 0; |
|
| 7646 |
++ int id, dropnum; |
|
| 7647 |
++ int tmu, queue; |
|
| 7648 |
++ u32 val; |
|
| 7649 |
++ u32 dmem_addr; |
|
| 7650 |
++ int num_class_drops = 0, num_tmu_drops = 0, num_util_drops = 0; |
|
| 7651 |
++ struct pfe_ctrl *ctrl = &pfe->ctrl; |
|
| 7652 |
++ |
|
| 7653 |
++ memset(class_drop_counter, 0, sizeof(class_drop_counter)); |
|
| 7654 |
++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) {
|
|
| 7655 |
++ if (drops_do_clear) |
|
| 7656 |
++ pe_sync_stop(ctrl, (1 << id)); |
|
| 7657 |
++ for (dropnum = 0; dropnum < CLASS_NUM_DROP_COUNTERS; |
|
| 7658 |
++ dropnum++) {
|
|
| 7659 |
++ dmem_addr = CLASS_DM_DROP_CNTR; |
|
| 7660 |
++ val = be32_to_cpu(pe_dmem_read(id, dmem_addr, 4)); |
|
| 7661 |
++ class_drop_counter[dropnum] += val; |
|
| 7662 |
++ num_class_drops += val; |
|
| 7663 |
++ if (drops_do_clear) |
|
| 7664 |
++ pe_dmem_write(id, 0, dmem_addr, 4); |
|
| 7665 |
++ } |
|
| 7666 |
++ if (drops_do_clear) |
|
| 7667 |
++ pe_start(ctrl, (1 << id)); |
|
| 7668 |
++ } |
|
| 7669 |
++ |
|
| 7670 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7671 |
++ if (drops_do_clear) |
|
| 7672 |
++ pe_sync_stop(ctrl, (1 << UTIL_ID)); |
|
| 7673 |
++ for (dropnum = 0; dropnum < UTIL_NUM_DROP_COUNTERS; dropnum++) {
|
|
| 7674 |
++ dmem_addr = UTIL_DM_DROP_CNTR; |
|
| 7675 |
++ val = be32_to_cpu(pe_dmem_read(UTIL_ID, dmem_addr, 4)); |
|
| 7676 |
++ util_drop_counter[dropnum] = val; |
|
| 7677 |
++ num_util_drops += val; |
|
| 7678 |
++ if (drops_do_clear) |
|
| 7679 |
++ pe_dmem_write(UTIL_ID, 0, dmem_addr, 4); |
|
| 7680 |
++ } |
|
| 7681 |
++ if (drops_do_clear) |
|
| 7682 |
++ pe_start(ctrl, (1 << UTIL_ID)); |
|
| 7683 |
++#endif |
|
| 7684 |
++ for (tmu = 0; tmu < 4; tmu++) {
|
|
| 7685 |
++ for (queue = 0; queue < 16; queue++) {
|
|
| 7686 |
++ qm_read_drop_stat(tmu, queue, &tmu_drops[tmu][queue], |
|
| 7687 |
++ drops_do_clear); |
|
| 7688 |
++ num_tmu_drops += tmu_drops[tmu][queue]; |
|
| 7689 |
++ } |
|
| 7690 |
++ } |
|
| 7691 |
++ |
|
| 7692 |
++ if (num_class_drops == 0 && num_util_drops == 0 && num_tmu_drops == 0) |
|
| 7693 |
++ len += sprintf(buf + len, "No PE drops\n\n"); |
|
| 7694 |
++ |
|
| 7695 |
++ if (num_class_drops > 0) {
|
|
| 7696 |
++ len += sprintf(buf + len, "Class PE drops --\n"); |
|
| 7697 |
++ for (dropnum = 0; dropnum < CLASS_NUM_DROP_COUNTERS; |
|
| 7698 |
++ dropnum++) {
|
|
| 7699 |
++ if (class_drop_counter[dropnum] > 0) |
|
| 7700 |
++ len += sprintf(buf + len, " %s: %d\n", |
|
| 7701 |
++ class_drop_description[dropnum], |
|
| 7702 |
++ class_drop_counter[dropnum]); |
|
| 7703 |
++ } |
|
| 7704 |
++ len += sprintf(buf + len, "\n"); |
|
| 7705 |
++ } |
|
| 7706 |
++ |
|
| 7707 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7708 |
++ if (num_util_drops > 0) {
|
|
| 7709 |
++ len += sprintf(buf + len, "Util PE drops --\n"); |
|
| 7710 |
++ for (dropnum = 0; dropnum < UTIL_NUM_DROP_COUNTERS; dropnum++) {
|
|
| 7711 |
++ if (util_drop_counter[dropnum] > 0) |
|
| 7712 |
++ len += sprintf(buf + len, " %s: %d\n", |
|
| 7713 |
++ util_drop_description[dropnum], |
|
| 7714 |
++ util_drop_counter[dropnum]); |
|
| 7715 |
++ } |
|
| 7716 |
++ len += sprintf(buf + len, "\n"); |
|
| 7717 |
++ } |
|
| 7718 |
++#endif |
|
| 7719 |
++ if (num_tmu_drops > 0) {
|
|
| 7720 |
++ len += sprintf(buf + len, "TMU drops --\n"); |
|
| 7721 |
++ for (tmu = 0; tmu < 4; tmu++) {
|
|
| 7722 |
++ for (queue = 0; queue < 16; queue++) {
|
|
| 7723 |
++ if (tmu_drops[tmu][queue] > 0) |
|
| 7724 |
++ len += sprintf(buf + len, |
|
| 7725 |
++ " TMU%d-Q%d: %d\n" |
|
| 7726 |
++ , tmu, queue, tmu_drops[tmu][queue]); |
|
| 7727 |
++ } |
|
| 7728 |
++ } |
|
| 7729 |
++ len += sprintf(buf + len, "\n"); |
|
| 7730 |
++ } |
|
| 7731 |
++ |
|
| 7732 |
++ return len; |
|
| 7733 |
++} |
|
| 7734 |
++ |
|
| 7735 |
++static ssize_t pfe_show_tmu0_queues(struct device *dev, struct device_attribute |
|
| 7736 |
++ *attr, char *buf) |
|
| 7737 |
++{
|
|
| 7738 |
++ return tmu_queues(buf, 0); |
|
| 7739 |
++} |
|
| 7740 |
++ |
|
| 7741 |
++static ssize_t pfe_show_tmu1_queues(struct device *dev, struct device_attribute |
|
| 7742 |
++ *attr, char *buf) |
|
| 7743 |
++{
|
|
| 7744 |
++ return tmu_queues(buf, 1); |
|
| 7745 |
++} |
|
| 7746 |
++ |
|
| 7747 |
++static ssize_t pfe_show_tmu2_queues(struct device *dev, struct device_attribute |
|
| 7748 |
++ *attr, char *buf) |
|
| 7749 |
++{
|
|
| 7750 |
++ return tmu_queues(buf, 2); |
|
| 7751 |
++} |
|
| 7752 |
++ |
|
| 7753 |
++static ssize_t pfe_show_tmu3_queues(struct device *dev, struct device_attribute |
|
| 7754 |
++ *attr, char *buf) |
|
| 7755 |
++{
|
|
| 7756 |
++ return tmu_queues(buf, 3); |
|
| 7757 |
++} |
|
| 7758 |
++ |
|
| 7759 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7760 |
++static ssize_t pfe_set_util(struct device *dev, struct device_attribute *attr, |
|
| 7761 |
++ const char *buf, size_t count) |
|
| 7762 |
++{
|
|
| 7763 |
++ util_do_clear = kstrtoul(buf, NULL, 0); |
|
| 7764 |
++ return count; |
|
| 7765 |
++} |
|
| 7766 |
++ |
|
| 7767 |
++static ssize_t pfe_show_util(struct device *dev, struct device_attribute *attr, |
|
| 7768 |
++ char *buf) |
|
| 7769 |
++{
|
|
| 7770 |
++ ssize_t len = 0; |
|
| 7771 |
++ struct pfe_ctrl *ctrl = &pfe->ctrl; |
|
| 7772 |
++ |
|
| 7773 |
++ len += block_version(buf + len, UTIL_VERSION); |
|
| 7774 |
++ |
|
| 7775 |
++ pe_sync_stop(ctrl, (1 << UTIL_ID)); |
|
| 7776 |
++ len += display_pe_status(buf + len, UTIL_ID, UTIL_DM_PESTATUS, |
|
| 7777 |
++ util_do_clear); |
|
| 7778 |
++ pe_start(ctrl, (1 << UTIL_ID)); |
|
| 7779 |
++ |
|
| 7780 |
++ len += sprintf(buf + len, "pe status: %x\n", readl(UTIL_PE_STATUS)); |
|
| 7781 |
++ len += sprintf(buf + len, "max buf cnt: %x\n", |
|
| 7782 |
++ readl(UTIL_MAX_BUF_CNT)); |
|
| 7783 |
++ len += sprintf(buf + len, "tsq max cnt: %x\n", |
|
| 7784 |
++ readl(UTIL_TSQ_MAX_CNT)); |
|
| 7785 |
++ |
|
| 7786 |
++ return len; |
|
| 7787 |
++} |
|
| 7788 |
++#endif |
|
| 7789 |
++ |
|
| 7790 |
++static ssize_t pfe_show_bmu(struct device *dev, struct device_attribute *attr, |
|
| 7791 |
++ char *buf) |
|
| 7792 |
++{
|
|
| 7793 |
++ ssize_t len = 0; |
|
| 7794 |
++ |
|
| 7795 |
++ len += bmu(buf + len, 1, BMU1_BASE_ADDR); |
|
| 7796 |
++ len += bmu(buf + len, 2, BMU2_BASE_ADDR); |
|
| 7797 |
++ |
|
| 7798 |
++ return len; |
|
| 7799 |
++} |
|
| 7800 |
++ |
|
| 7801 |
++static ssize_t pfe_show_hif(struct device *dev, struct device_attribute *attr, |
|
| 7802 |
++ char *buf) |
|
| 7803 |
++{
|
|
| 7804 |
++ ssize_t len = 0; |
|
| 7805 |
++ |
|
| 7806 |
++ len += sprintf(buf + len, "hif:\n "); |
|
| 7807 |
++ len += block_version(buf + len, HIF_VERSION); |
|
| 7808 |
++ |
|
| 7809 |
++ len += sprintf(buf + len, " tx curr bd: %x\n", |
|
| 7810 |
++ readl(HIF_TX_CURR_BD_ADDR)); |
|
| 7811 |
++ len += sprintf(buf + len, " tx status: %x\n", |
|
| 7812 |
++ readl(HIF_TX_STATUS)); |
|
| 7813 |
++ len += sprintf(buf + len, " tx dma status: %x\n", |
|
| 7814 |
++ readl(HIF_TX_DMA_STATUS)); |
|
| 7815 |
++ |
|
| 7816 |
++ len += sprintf(buf + len, " rx curr bd: %x\n", |
|
| 7817 |
++ readl(HIF_RX_CURR_BD_ADDR)); |
|
| 7818 |
++ len += sprintf(buf + len, " rx status: %x\n", |
|
| 7819 |
++ readl(HIF_RX_STATUS)); |
|
| 7820 |
++ len += sprintf(buf + len, " rx dma status: %x\n", |
|
| 7821 |
++ readl(HIF_RX_DMA_STATUS)); |
|
| 7822 |
++ |
|
| 7823 |
++ len += sprintf(buf + len, "hif nocopy:\n "); |
|
| 7824 |
++ len += block_version(buf + len, HIF_NOCPY_VERSION); |
|
| 7825 |
++ |
|
| 7826 |
++ len += sprintf(buf + len, " tx curr bd: %x\n", |
|
| 7827 |
++ readl(HIF_NOCPY_TX_CURR_BD_ADDR)); |
|
| 7828 |
++ len += sprintf(buf + len, " tx status: %x\n", |
|
| 7829 |
++ readl(HIF_NOCPY_TX_STATUS)); |
|
| 7830 |
++ len += sprintf(buf + len, " tx dma status: %x\n", |
|
| 7831 |
++ readl(HIF_NOCPY_TX_DMA_STATUS)); |
|
| 7832 |
++ |
|
| 7833 |
++ len += sprintf(buf + len, " rx curr bd: %x\n", |
|
| 7834 |
++ readl(HIF_NOCPY_RX_CURR_BD_ADDR)); |
|
| 7835 |
++ len += sprintf(buf + len, " rx status: %x\n", |
|
| 7836 |
++ readl(HIF_NOCPY_RX_STATUS)); |
|
| 7837 |
++ len += sprintf(buf + len, " rx dma status: %x\n", |
|
| 7838 |
++ readl(HIF_NOCPY_RX_DMA_STATUS)); |
|
| 7839 |
++ |
|
| 7840 |
++ return len; |
|
| 7841 |
++} |
|
| 7842 |
++ |
|
| 7843 |
++static ssize_t pfe_show_gpi(struct device *dev, struct device_attribute *attr, |
|
| 7844 |
++ char *buf) |
|
| 7845 |
++{
|
|
| 7846 |
++ ssize_t len = 0; |
|
| 7847 |
++ |
|
| 7848 |
++ len += gpi(buf + len, 0, EGPI1_BASE_ADDR); |
|
| 7849 |
++ len += gpi(buf + len, 1, EGPI2_BASE_ADDR); |
|
| 7850 |
++ len += gpi(buf + len, 3, HGPI_BASE_ADDR); |
|
| 7851 |
++ |
|
| 7852 |
++ return len; |
|
| 7853 |
++} |
|
| 7854 |
++ |
|
| 7855 |
++static ssize_t pfe_show_pfemem(struct device *dev, struct device_attribute |
|
| 7856 |
++ *attr, char *buf) |
|
| 7857 |
++{
|
|
| 7858 |
++ ssize_t len = 0; |
|
| 7859 |
++ struct pfe_memmon *memmon = &pfe->memmon; |
|
| 7860 |
++ |
|
| 7861 |
++ len += sprintf(buf + len, "Kernel Memory: %d Bytes (%d KB)\n", |
|
| 7862 |
++ memmon->kernel_memory_allocated, |
|
| 7863 |
++ (memmon->kernel_memory_allocated + 1023) / 1024); |
|
| 7864 |
++ |
|
| 7865 |
++ return len; |
|
| 7866 |
++} |
|
| 7867 |
++ |
|
| 7868 |
++#ifdef HIF_NAPI_STATS |
|
| 7869 |
++static ssize_t pfe_show_hif_napi_stats(struct device *dev, |
|
| 7870 |
++ struct device_attribute *attr, |
|
| 7871 |
++ char *buf) |
|
| 7872 |
++{
|
|
| 7873 |
++ struct platform_device *pdev = to_platform_device(dev); |
|
| 7874 |
++ struct pfe *pfe = platform_get_drvdata(pdev); |
|
| 7875 |
++ ssize_t len = 0; |
|
| 7876 |
++ |
|
| 7877 |
++ len += sprintf(buf + len, "sched: %u\n", |
|
| 7878 |
++ pfe->hif.napi_counters[NAPI_SCHED_COUNT]); |
|
| 7879 |
++ len += sprintf(buf + len, "poll: %u\n", |
|
| 7880 |
++ pfe->hif.napi_counters[NAPI_POLL_COUNT]); |
|
| 7881 |
++ len += sprintf(buf + len, "packet: %u\n", |
|
| 7882 |
++ pfe->hif.napi_counters[NAPI_PACKET_COUNT]); |
|
| 7883 |
++ len += sprintf(buf + len, "budget: %u\n", |
|
| 7884 |
++ pfe->hif.napi_counters[NAPI_FULL_BUDGET_COUNT]); |
|
| 7885 |
++ len += sprintf(buf + len, "desc: %u\n", |
|
| 7886 |
++ pfe->hif.napi_counters[NAPI_DESC_COUNT]); |
|
| 7887 |
++ len += sprintf(buf + len, "full: %u\n", |
|
| 7888 |
++ pfe->hif.napi_counters[NAPI_CLIENT_FULL_COUNT]); |
|
| 7889 |
++ |
|
| 7890 |
++ return len; |
|
| 7891 |
++} |
|
| 7892 |
++ |
|
| 7893 |
++static ssize_t pfe_set_hif_napi_stats(struct device *dev, |
|
| 7894 |
++ struct device_attribute *attr, |
|
| 7895 |
++ const char *buf, size_t count) |
|
| 7896 |
++{
|
|
| 7897 |
++ struct platform_device *pdev = to_platform_device(dev); |
|
| 7898 |
++ struct pfe *pfe = platform_get_drvdata(pdev); |
|
| 7899 |
++ |
|
| 7900 |
++ memset(pfe->hif.napi_counters, 0, sizeof(pfe->hif.napi_counters)); |
|
| 7901 |
++ |
|
| 7902 |
++ return count; |
|
| 7903 |
++} |
|
| 7904 |
++ |
|
| 7905 |
++static DEVICE_ATTR(hif_napi_stats, 0644, pfe_show_hif_napi_stats, |
|
| 7906 |
++ pfe_set_hif_napi_stats); |
|
| 7907 |
++#endif |
|
| 7908 |
++ |
|
| 7909 |
++static DEVICE_ATTR(class, 0644, pfe_show_class, pfe_set_class); |
|
| 7910 |
++static DEVICE_ATTR(tmu, 0644, pfe_show_tmu, pfe_set_tmu); |
|
| 7911 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7912 |
++static DEVICE_ATTR(util, 0644, pfe_show_util, pfe_set_util); |
|
| 7913 |
++#endif |
|
| 7914 |
++static DEVICE_ATTR(bmu, 0444, pfe_show_bmu, NULL); |
|
| 7915 |
++static DEVICE_ATTR(hif, 0444, pfe_show_hif, NULL); |
|
| 7916 |
++static DEVICE_ATTR(gpi, 0444, pfe_show_gpi, NULL); |
|
| 7917 |
++static DEVICE_ATTR(drops, 0644, pfe_show_drops, pfe_set_drops); |
|
| 7918 |
++static DEVICE_ATTR(tmu0_queues, 0444, pfe_show_tmu0_queues, NULL); |
|
| 7919 |
++static DEVICE_ATTR(tmu1_queues, 0444, pfe_show_tmu1_queues, NULL); |
|
| 7920 |
++static DEVICE_ATTR(tmu2_queues, 0444, pfe_show_tmu2_queues, NULL); |
|
| 7921 |
++static DEVICE_ATTR(tmu3_queues, 0444, pfe_show_tmu3_queues, NULL); |
|
| 7922 |
++static DEVICE_ATTR(pfemem, 0444, pfe_show_pfemem, NULL); |
|
| 7923 |
++ |
|
| 7924 |
++int pfe_sysfs_init(struct pfe *pfe) |
|
| 7925 |
++{
|
|
| 7926 |
++ if (device_create_file(pfe->dev, &dev_attr_class)) |
|
| 7927 |
++ goto err_class; |
|
| 7928 |
++ |
|
| 7929 |
++ if (device_create_file(pfe->dev, &dev_attr_tmu)) |
|
| 7930 |
++ goto err_tmu; |
|
| 7931 |
++ |
|
| 7932 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 7933 |
++ if (device_create_file(pfe->dev, &dev_attr_util)) |
|
| 7934 |
++ goto err_util; |
|
| 7935 |
++#endif |
|
| 7936 |
++ |
|
| 7937 |
++ if (device_create_file(pfe->dev, &dev_attr_bmu)) |
|
| 7938 |
++ goto err_bmu; |
|
| 7939 |
++ |
|
| 7940 |
++ if (device_create_file(pfe->dev, &dev_attr_hif)) |
|
| 7941 |
++ goto err_hif; |
|
| 7942 |
++ |
|
| 7943 |
++ if (device_create_file(pfe->dev, &dev_attr_gpi)) |
|
| 7944 |
++ goto err_gpi; |
|
| 7945 |
++ |
|
| 7946 |
++ if (device_create_file(pfe->dev, &dev_attr_drops)) |
|
| 7947 |
++ goto err_drops; |
|
| 7948 |
++ |
|
| 7949 |
++ if (device_create_file(pfe->dev, &dev_attr_tmu0_queues)) |
|
| 7950 |
++ goto err_tmu0_queues; |
|
| 7951 |
++ |
|
| 7952 |
++ if (device_create_file(pfe->dev, &dev_attr_tmu1_queues)) |
|
| 7953 |
++ goto err_tmu1_queues; |
|
| 7954 |
++ |
|
| 7955 |
++ if (device_create_file(pfe->dev, &dev_attr_tmu2_queues)) |
|
| 7956 |
++ goto err_tmu2_queues; |
|
| 7957 |
++ |
|
| 7958 |
++ if (device_create_file(pfe->dev, &dev_attr_tmu3_queues)) |
|
| 7959 |
++ goto err_tmu3_queues; |
|
| 7960 |
++ |
|
| 7961 |
++ if (device_create_file(pfe->dev, &dev_attr_pfemem)) |
|
| 7962 |
++ goto err_pfemem; |
|
| 7963 |
++ |
|
| 7964 |
++#ifdef HIF_NAPI_STATS |
|
| 7965 |
++ if (device_create_file(pfe->dev, &dev_attr_hif_napi_stats)) |
|
| 7966 |
++ goto err_hif_napi_stats; |
|
| 7967 |
++#endif |
|
| 7968 |
++ |
|
| 7969 |
++ return 0; |
|
| 7970 |
++ |
|
| 7971 |
++#ifdef HIF_NAPI_STATS |
|
| 7972 |
++err_hif_napi_stats: |
|
| 7973 |
++ device_remove_file(pfe->dev, &dev_attr_pfemem); |
|
| 7974 |
++#endif |
|
| 7975 |
++ |
|
| 7976 |
++err_pfemem: |
|
| 7977 |
++ device_remove_file(pfe->dev, &dev_attr_tmu3_queues); |
|
| 7978 |
++ |
|
| 7979 |
++err_tmu3_queues: |
|
| 7980 |
++ device_remove_file(pfe->dev, &dev_attr_tmu2_queues); |
|
| 7981 |
++ |
|
| 7982 |
++err_tmu2_queues: |
|
| 7983 |
++ device_remove_file(pfe->dev, &dev_attr_tmu1_queues); |
|
| 7984 |
++ |
|
| 7985 |
++err_tmu1_queues: |
|
| 7986 |
++ device_remove_file(pfe->dev, &dev_attr_tmu0_queues); |
|
| 7987 |
++ |
|
| 7988 |
++err_tmu0_queues: |
|
| 7989 |
++ device_remove_file(pfe->dev, &dev_attr_drops); |
|
| 7990 |
++ |
|
| 7991 |
++err_drops: |
|
| 7992 |
++ device_remove_file(pfe->dev, &dev_attr_gpi); |
|
| 7993 |
++ |
|
| 7994 |
++err_gpi: |
|
| 7995 |
++ device_remove_file(pfe->dev, &dev_attr_hif); |
|
| 7996 |
++ |
|
| 7997 |
++err_hif: |
|
| 7998 |
++ device_remove_file(pfe->dev, &dev_attr_bmu); |
|
| 7999 |
++ |
|
| 8000 |
++err_bmu: |
|
| 8001 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 8002 |
++ device_remove_file(pfe->dev, &dev_attr_util); |
|
| 8003 |
++ |
|
| 8004 |
++err_util: |
|
| 8005 |
++#endif |
|
| 8006 |
++ device_remove_file(pfe->dev, &dev_attr_tmu); |
|
| 8007 |
++ |
|
| 8008 |
++err_tmu: |
|
| 8009 |
++ device_remove_file(pfe->dev, &dev_attr_class); |
|
| 8010 |
++ |
|
| 8011 |
++err_class: |
|
| 8012 |
++ return -1; |
|
| 8013 |
++} |
|
| 8014 |
++ |
|
| 8015 |
++void pfe_sysfs_exit(struct pfe *pfe) |
|
| 8016 |
++{
|
|
| 8017 |
++#ifdef HIF_NAPI_STATS |
|
| 8018 |
++ device_remove_file(pfe->dev, &dev_attr_hif_napi_stats); |
|
| 8019 |
++#endif |
|
| 8020 |
++ device_remove_file(pfe->dev, &dev_attr_pfemem); |
|
| 8021 |
++ device_remove_file(pfe->dev, &dev_attr_tmu3_queues); |
|
| 8022 |
++ device_remove_file(pfe->dev, &dev_attr_tmu2_queues); |
|
| 8023 |
++ device_remove_file(pfe->dev, &dev_attr_tmu1_queues); |
|
| 8024 |
++ device_remove_file(pfe->dev, &dev_attr_tmu0_queues); |
|
| 8025 |
++ device_remove_file(pfe->dev, &dev_attr_drops); |
|
| 8026 |
++ device_remove_file(pfe->dev, &dev_attr_gpi); |
|
| 8027 |
++ device_remove_file(pfe->dev, &dev_attr_hif); |
|
| 8028 |
++ device_remove_file(pfe->dev, &dev_attr_bmu); |
|
| 8029 |
++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) |
|
| 8030 |
++ device_remove_file(pfe->dev, &dev_attr_util); |
|
| 8031 |
++#endif |
|
| 8032 |
++ device_remove_file(pfe->dev, &dev_attr_tmu); |
|
| 8033 |
++ device_remove_file(pfe->dev, &dev_attr_class); |
|
| 8034 |
++} |
|
| 8035 |
+-- |
|
| 8036 |
+2.14.2 |
|
| 8037 |
+ |
| 0 | 8038 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,42 @@ |
| 0 |
+From 76f019fd039a2329ce85ece89ef7e9fa6b0d0f11 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 11 Oct 2017 19:23:38 +0530 |
|
| 3 |
+Subject: [PATCH 03/22] staging: fsl_ppfe/eth: fix RGMII tx delay issue |
|
| 4 |
+ |
|
| 5 |
+Recently logic to enable RGMII tx delay was changed by |
|
| 6 |
+below patch. |
|
| 7 |
+ |
|
| 8 |
+https://patchwork.kernel.org/patch/9447581/ |
|
| 9 |
+ |
|
| 10 |
+Based on the patch, appropriate change is made in PFE driver. |
|
| 11 |
+ |
|
| 12 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 13 |
+Signed-off-by: Anjaneyulu Jagarlmudi <anji.jagarlmudi@nxp.com> |
|
| 14 |
+ |
|
| 15 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 16 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 17 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 18 |
+] |
|
| 19 |
+ |
|
| 20 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 21 |
+--- |
|
| 22 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 3 ++- |
|
| 23 |
+ 1 file changed, 2 insertions(+), 1 deletion(-) |
|
| 24 |
+ |
|
| 25 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 26 |
+index 5aa718be42c2..a0171f3e7537 100644 |
|
| 27 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 28 |
+@@ -1068,7 +1068,8 @@ static void pfe_eth_adjust_link(struct net_device *ndev) |
|
| 29 |
+ new_state = 1; |
|
| 30 |
+ gemac_set_speed(priv->EMAC_baseaddr, |
|
| 31 |
+ pfe_get_phydev_speed(phydev)); |
|
| 32 |
+- if (priv->einfo->mii_config == PHY_INTERFACE_MODE_RGMII) |
|
| 33 |
++ if (priv->einfo->mii_config == |
|
| 34 |
++ PHY_INTERFACE_MODE_RGMII_TXID) |
|
| 35 |
+ pfe_set_rgmii_speed(phydev); |
|
| 36 |
+ priv->oldspeed = phydev->speed; |
|
| 37 |
+ } |
|
| 38 |
+-- |
|
| 39 |
+2.14.2 |
|
| 40 |
+ |
| 0 | 41 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,110 @@ |
| 0 |
+From 1ded4ecc39d6f6af69ff3724568c6564d20f17fb Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 18 Oct 2017 14:29:30 +0530 |
|
| 3 |
+Subject: [PATCH 04/22] staging: fsl_ppfe/eth: remove unused functions |
|
| 4 |
+ |
|
| 5 |
+Remove unused functions hif_xmit_pkt & hif_lib_xmit_pkt. |
|
| 6 |
+ |
|
| 7 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 8 |
+ |
|
| 9 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 10 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 11 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 12 |
+] |
|
| 13 |
+ |
|
| 14 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 15 |
+--- |
|
| 16 |
+ drivers/staging/fsl_ppfe/pfe_hif.c | 24 +----------------------- |
|
| 17 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.c | 34 ---------------------------------- |
|
| 18 |
+ 2 files changed, 1 insertion(+), 57 deletions(-) |
|
| 19 |
+ |
|
| 20 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif.c b/drivers/staging/fsl_ppfe/pfe_hif.c |
|
| 21 |
+index 6844595da9f1..61b4d57c8a34 100644 |
|
| 22 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif.c |
|
| 23 |
+@@ -844,29 +844,6 @@ void __hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int |
|
| 24 |
+ return; |
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+-int hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int q_no, |
|
| 28 |
+- void *data, unsigned int len) |
|
| 29 |
+-{
|
|
| 30 |
+- int rc = 0; |
|
| 31 |
+- |
|
| 32 |
+- spin_lock_bh(&hif->tx_lock); |
|
| 33 |
+- |
|
| 34 |
+- if (!hif->txavail) {
|
|
| 35 |
+- rc = 1; |
|
| 36 |
+- } else {
|
|
| 37 |
+- __hif_xmit_pkt(hif, client_id, q_no, data, len, |
|
| 38 |
+- HIF_FIRST_BUFFER | HIF_LAST_BUFFER); |
|
| 39 |
+- hif_tx_dma_start(); |
|
| 40 |
+- } |
|
| 41 |
+- |
|
| 42 |
+- if (hif->txavail < (hif->tx_ring_size >> 1)) |
|
| 43 |
+- __hif_tx_done_process(hif, TX_FREE_MAX_COUNT); |
|
| 44 |
+- |
|
| 45 |
+- spin_unlock_bh(&hif->tx_lock); |
|
| 46 |
+- |
|
| 47 |
+- return rc; |
|
| 48 |
+-} |
|
| 49 |
+- |
|
| 50 |
+ static irqreturn_t wol_isr(int irq, void *dev_id) |
|
| 51 |
+ {
|
|
| 52 |
+ pr_info("WoL\n");
|
|
| 53 |
+@@ -907,6 +884,7 @@ static irqreturn_t hif_isr(int irq, void *dev_id) |
|
| 54 |
+ __napi_schedule(&hif->napi); |
|
| 55 |
+ } |
|
| 56 |
+ } |
|
| 57 |
++ |
|
| 58 |
+ if (int_status & HIF_TXPKT_INT) {
|
|
| 59 |
+ int_status &= ~(HIF_TXPKT_INT); |
|
| 60 |
+ int_enable_mask &= ~(HIF_TXPKT_INT); |
|
| 61 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.c b/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 62 |
+index 4274a59257fe..d5a5701bf987 100644 |
|
| 63 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 64 |
+@@ -512,40 +512,6 @@ void __hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void |
|
| 65 |
+ queue->jiffies_last_packet = jiffies; |
|
| 66 |
+ } |
|
| 67 |
+ |
|
| 68 |
+-/*This function puts the given packet in the specific client queue */ |
|
| 69 |
+-int hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void *data, |
|
| 70 |
+- unsigned int len, u32 client_ctrl, void *client_data) |
|
| 71 |
+-{
|
|
| 72 |
+- struct hif_client_tx_queue *queue = &client->tx_q[qno]; |
|
| 73 |
+- struct tx_queue_desc *desc = queue->base + queue->write_idx; |
|
| 74 |
+- |
|
| 75 |
+- if (queue->tx_pending < queue->size) {
|
|
| 76 |
+- /*Construct pkt header */ |
|
| 77 |
+- |
|
| 78 |
+- data -= sizeof(struct hif_hdr); |
|
| 79 |
+- len += sizeof(struct hif_hdr); |
|
| 80 |
+- |
|
| 81 |
+- hif_hdr_write(data, client->id, qno, client_ctrl); |
|
| 82 |
+- |
|
| 83 |
+- desc->data = client_data; |
|
| 84 |
+- desc->ctrl = CL_DESC_OWN | CL_DESC_FLAGS(HIF_FIRST_BUFFER | |
|
| 85 |
+- HIF_LAST_BUFFER | HIF_DATA_VALID); |
|
| 86 |
+- |
|
| 87 |
+- if (hif_xmit_pkt(&pfe->hif, client->id, qno, data, len)) |
|
| 88 |
+- return 1; |
|
| 89 |
+- |
|
| 90 |
+- inc_cl_idx(queue->write_idx); |
|
| 91 |
+- queue->tx_pending++; |
|
| 92 |
+- queue->jiffies_last_packet = jiffies; |
|
| 93 |
+- |
|
| 94 |
+- return 0; |
|
| 95 |
+- } |
|
| 96 |
+- |
|
| 97 |
+- pr_debug("%s Tx client %d qno %d is full\n", __func__, client->id,
|
|
| 98 |
+- qno); |
|
| 99 |
+- return 1; |
|
| 100 |
+-} |
|
| 101 |
+- |
|
| 102 |
+ void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, |
|
| 103 |
+ unsigned int *flags, int count) |
|
| 104 |
+ {
|
|
| 105 |
+-- |
|
| 106 |
+2.14.2 |
|
| 107 |
+ |
| 0 | 108 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,91 @@ |
| 0 |
+From 8ae5bb44b311a6fc1425382167e4666ff2a11f8d Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 18 Oct 2017 18:34:41 +0530 |
|
| 3 |
+Subject: [PATCH 05/22] staging: fsl_ppfe/eth: fix read/write/ack idx issue |
|
| 4 |
+ |
|
| 5 |
+While fixing checkpatch errors some of the index increments |
|
| 6 |
+were commented out. They are enabled. |
|
| 7 |
+ |
|
| 8 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 9 |
+ |
|
| 10 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 11 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 12 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 13 |
+] |
|
| 14 |
+ |
|
| 15 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 16 |
+--- |
|
| 17 |
+ drivers/staging/fsl_ppfe/pfe_hif.c | 8 ++++---- |
|
| 18 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.c | 9 +++------ |
|
| 19 |
+ 2 files changed, 7 insertions(+), 10 deletions(-) |
|
| 20 |
+ |
|
| 21 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif.c b/drivers/staging/fsl_ppfe/pfe_hif.c |
|
| 22 |
+index 61b4d57c8a34..6835e14021a2 100644 |
|
| 23 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif.c |
|
| 24 |
+@@ -511,9 +511,9 @@ static void *client_put_rxpacket(struct hif_rx_queue *queue, void *pkt, u32 len, |
|
| 25 |
+ */ |
|
| 26 |
+ smp_wmb(); |
|
| 27 |
+ writel(CL_DESC_BUF_LEN(len) | flags, &desc->ctrl); |
|
| 28 |
+- /* queue->write_idx = (queue->write_idx + 1) |
|
| 29 |
+- * & (queue->size - 1); |
|
| 30 |
+- */ |
|
| 31 |
++ queue->write_idx = (queue->write_idx + 1) |
|
| 32 |
++ & (queue->size - 1); |
|
| 33 |
++ |
|
| 34 |
+ free_pkt += pfe_pkt_headroom; |
|
| 35 |
+ } |
|
| 36 |
+ } |
|
| 37 |
+@@ -703,7 +703,7 @@ static int client_ack_txpacket(struct pfe_hif *hif, unsigned int client_id, |
|
| 38 |
+ |
|
| 39 |
+ if (readl(&desc->ctrl) & CL_DESC_OWN) {
|
|
| 40 |
+ writel((readl(&desc->ctrl) & ~CL_DESC_OWN), &desc->ctrl); |
|
| 41 |
+- /* queue->ack_idx = (queue->ack_idx + 1) & (queue->size - 1); */ |
|
| 42 |
++ queue->ack_idx = (queue->ack_idx + 1) & (queue->size - 1); |
|
| 43 |
+ |
|
| 44 |
+ return 0; |
|
| 45 |
+ |
|
| 46 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.c b/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 47 |
+index d5a5701bf987..837eaa244ff6 100644 |
|
| 48 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 49 |
+@@ -211,9 +211,6 @@ static int hif_lib_client_init_rx_buffers(struct hif_client_s *client, int |
|
| 50 |
+ return 1; |
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+-#define inc_cl_idx(idxname) \ |
|
| 54 |
+- ({ typeof(idxname) idxname_ = (idxname); \
|
|
| 55 |
+- ((idxname_) = (idxname_ + 1) & (queue->size - 1)); }) |
|
| 56 |
+ |
|
| 57 |
+ static void hif_lib_client_cleanup_tx_queue(struct hif_client_tx_queue *queue) |
|
| 58 |
+ {
|
|
| 59 |
+@@ -465,7 +462,7 @@ void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int |
|
| 60 |
+ smp_wmb(); |
|
| 61 |
+ |
|
| 62 |
+ desc->ctrl = CL_DESC_BUF_LEN(pfe_pkt_size) | CL_DESC_OWN; |
|
| 63 |
+- inc_cl_idx(queue->read_idx); |
|
| 64 |
++ queue->read_idx = (queue->read_idx + 1) & (queue->size - 1); |
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ /*spin_unlock_irqrestore(&client->rx_lock, flags); */ |
|
| 68 |
+@@ -507,7 +504,7 @@ void __hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void |
|
| 69 |
+ |
|
| 70 |
+ __hif_xmit_pkt(&pfe->hif, client->id, qno, data, len, flags); |
|
| 71 |
+ |
|
| 72 |
+- inc_cl_idx(queue->write_idx); |
|
| 73 |
++ queue->write_idx = (queue->write_idx + 1) & (queue->size - 1); |
|
| 74 |
+ queue->tx_pending++; |
|
| 75 |
+ queue->jiffies_last_packet = jiffies; |
|
| 76 |
+ } |
|
| 77 |
+@@ -544,7 +541,7 @@ void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, |
|
| 78 |
+ if (desc->ctrl & CL_DESC_OWN) |
|
| 79 |
+ return NULL; |
|
| 80 |
+ |
|
| 81 |
+- inc_cl_idx(queue->read_idx); |
|
| 82 |
++ queue->read_idx = (queue->read_idx + 1) & (queue->size - 1); |
|
| 83 |
+ queue->tx_pending--; |
|
| 84 |
+ |
|
| 85 |
+ *flags = CL_DESC_GET_FLAGS(desc->ctrl); |
|
| 86 |
+-- |
|
| 87 |
+2.14.2 |
|
| 88 |
+ |
| 0 | 89 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,38 @@ |
| 0 |
+From 6a0a4302336e653577ab6819c54e2bba9b2e1ef9 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Fri, 27 Oct 2017 11:20:47 +0530 |
|
| 3 |
+Subject: [PATCH 06/22] staging: fsl_ppfe/eth: Make phy_ethtool_ksettings_get |
|
| 4 |
+ return void |
|
| 5 |
+ |
|
| 6 |
+Make return value void since function never return meaningful value |
|
| 7 |
+ |
|
| 8 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 9 |
+ |
|
| 10 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 11 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 12 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 13 |
+] |
|
| 14 |
+ |
|
| 15 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 16 |
+--- |
|
| 17 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 4 +++- |
|
| 18 |
+ 1 file changed, 3 insertions(+), 1 deletion(-) |
|
| 19 |
+ |
|
| 20 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 21 |
+index a0171f3e7537..89e60ce424f0 100644 |
|
| 22 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 23 |
+@@ -577,7 +577,9 @@ static int pfe_eth_get_settings(struct net_device *ndev, |
|
| 24 |
+ if (!phydev) |
|
| 25 |
+ return -ENODEV; |
|
| 26 |
+ |
|
| 27 |
+- return phy_ethtool_ksettings_get(phydev, cmd); |
|
| 28 |
++ phy_ethtool_ksettings_get(phydev, cmd); |
|
| 29 |
++ |
|
| 30 |
++ return 0; |
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ /* |
|
| 34 |
+-- |
|
| 35 |
+2.14.2 |
|
| 36 |
+ |
| 0 | 37 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,83 @@ |
| 0 |
+From 3ad9c8e3f97138e34d03b88a63352d65deb1cef8 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 15 Nov 2017 13:45:27 +0530 |
|
| 3 |
+Subject: [PATCH 07/22] staging: fsl_ppfe/eth: add function to update tmu |
|
| 4 |
+ credits |
|
| 5 |
+ |
|
| 6 |
+__hif_lib_update_credit function is used to update the tmu credits. |
|
| 7 |
+If tx_qos is set, tmu credit is updated based on the number of packets |
|
| 8 |
+transmitted by tmu. |
|
| 9 |
+ |
|
| 10 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 11 |
+Signed-off-by: Anjaneyulu Jagarlmudi <anji.jagarlmudi@nxp.com> |
|
| 12 |
+ |
|
| 13 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 14 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 15 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 16 |
+] |
|
| 17 |
+ |
|
| 18 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 19 |
+--- |
|
| 20 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.c | 33 +++++++++++++++++++++++++++++++++ |
|
| 21 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.h | 1 + |
|
| 22 |
+ 2 files changed, 34 insertions(+) |
|
| 23 |
+ |
|
| 24 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.c b/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 25 |
+index 837eaa244ff6..2ec47bf952e0 100644 |
|
| 26 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 27 |
+@@ -565,6 +565,39 @@ static void hif_lib_tmu_credit_init(struct pfe *pfe) |
|
| 28 |
+ } |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 31 |
++/* __hif_lib_update_credit |
|
| 32 |
++ * |
|
| 33 |
++ * @param[in] client hif client context |
|
| 34 |
++ * @param[in] queue queue number in match with TMU |
|
| 35 |
++ */ |
|
| 36 |
++void __hif_lib_update_credit(struct hif_client_s *client, unsigned int queue) |
|
| 37 |
++{
|
|
| 38 |
++ unsigned int tmu_tx_packets, tmp; |
|
| 39 |
++ |
|
| 40 |
++ if (tx_qos) {
|
|
| 41 |
++ tmu_tx_packets = be32_to_cpu(pe_dmem_read(TMU0_ID + |
|
| 42 |
++ client->id, TMU_DM_TX_TRANS, 4)); |
|
| 43 |
++ |
|
| 44 |
++ /* tx_packets counter overflowed */ |
|
| 45 |
++ if (tmu_tx_packets > |
|
| 46 |
++ pfe->tmu_credit.tx_packets[client->id][queue]) {
|
|
| 47 |
++ tmp = UINT_MAX - tmu_tx_packets + |
|
| 48 |
++ pfe->tmu_credit.tx_packets[client->id][queue]; |
|
| 49 |
++ |
|
| 50 |
++ pfe->tmu_credit.tx_credit[client->id][queue] = |
|
| 51 |
++ pfe->tmu_credit.tx_credit_max[client->id][queue] - tmp; |
|
| 52 |
++ } else {
|
|
| 53 |
++ /* TMU tx <= pfe_eth tx, normal case or both OF since |
|
| 54 |
++ * last time |
|
| 55 |
++ */ |
|
| 56 |
++ pfe->tmu_credit.tx_credit[client->id][queue] = |
|
| 57 |
++ pfe->tmu_credit.tx_credit_max[client->id][queue] - |
|
| 58 |
++ (pfe->tmu_credit.tx_packets[client->id][queue] - |
|
| 59 |
++ tmu_tx_packets); |
|
| 60 |
++ } |
|
| 61 |
++ } |
|
| 62 |
++} |
|
| 63 |
++ |
|
| 64 |
+ int pfe_hif_lib_init(struct pfe *pfe) |
|
| 65 |
+ {
|
|
| 66 |
+ int rc; |
|
| 67 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.h b/drivers/staging/fsl_ppfe/pfe_hif_lib.h |
|
| 68 |
+index 49e7b5f1f9c3..d48eb14a29b8 100644 |
|
| 69 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif_lib.h |
|
| 70 |
+@@ -185,6 +185,7 @@ void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, |
|
| 71 |
+ void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int |
|
| 72 |
+ *ofst, unsigned int *rx_ctrl, |
|
| 73 |
+ unsigned int *desc_ctrl, void **priv_data); |
|
| 74 |
++void __hif_lib_update_credit(struct hif_client_s *client, unsigned int queue); |
|
| 75 |
+ void hif_lib_set_rx_cpu_affinity(struct hif_client_s *client, int cpu_id); |
|
| 76 |
+ void hif_lib_set_tx_queue_nocpy(struct hif_client_s *client, int qno, int |
|
| 77 |
+ enable); |
|
| 78 |
+-- |
|
| 79 |
+2.14.2 |
|
| 80 |
+ |
| 0 | 81 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,101 @@ |
| 0 |
+From 3caccca49ab8a42589d6bffbeba0e4c083118f80 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Kavi Akhila-B46177 <akhila.kavi@nxp.com> |
|
| 2 |
+Date: Thu, 2 Nov 2017 12:05:35 +0530 |
|
| 3 |
+Subject: [PATCH 08/22] staging: fsl_ppfe/eth: Avoid packet drop at TMU queues |
|
| 4 |
+ |
|
| 5 |
+Added flow control between TMU queues and PFE Linux driver, |
|
| 6 |
+based on TMU credits availability. |
|
| 7 |
+Added tx_qos module parameter to control this behavior. |
|
| 8 |
+Use queue-0 as default queue to transmit packets. |
|
| 9 |
+ |
|
| 10 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 11 |
+Signed-off-by: Akhila Kavi <akhila.kavi@nxp.com> |
|
| 12 |
+Signed-off-by: Anjaneyulu Jagarlmudi <anji.jagarlmudi@nxp.com> |
|
| 13 |
+ |
|
| 14 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 15 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 16 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 17 |
+] |
|
| 18 |
+ |
|
| 19 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 20 |
+--- |
|
| 21 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 17 +++++++++++++---- |
|
| 22 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.c | 7 +++++-- |
|
| 23 |
+ 2 files changed, 18 insertions(+), 6 deletions(-) |
|
| 24 |
+ |
|
| 25 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 26 |
+index 89e60ce424f0..8771ad5c0634 100644 |
|
| 27 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 28 |
+@@ -293,10 +293,10 @@ static int pfe_eth_sysfs_init(struct net_device *ndev) |
|
| 29 |
+ /* Initialize the default values */ |
|
| 30 |
+ |
|
| 31 |
+ /* |
|
| 32 |
+- * By default, packets without conntrack will use this default high |
|
| 33 |
++ * By default, packets without conntrack will use this default low |
|
| 34 |
+ * priority queue |
|
| 35 |
+ */ |
|
| 36 |
+- priv->default_priority = 15; |
|
| 37 |
++ priv->default_priority = 0; |
|
| 38 |
+ |
|
| 39 |
+ /* Create our sysfs files */ |
|
| 40 |
+ err = device_create_file(&ndev->dev, &dev_attr_default_priority); |
|
| 41 |
+@@ -1566,10 +1566,17 @@ static int pfe_eth_might_stop_tx(struct pfe_eth_priv_s *priv, int queuenum, |
|
| 42 |
+ unsigned int n_segs) |
|
| 43 |
+ {
|
|
| 44 |
+ ktime_t kt; |
|
| 45 |
++ int tried = 0; |
|
| 46 |
+ |
|
| 47 |
++try_again: |
|
| 48 |
+ if (unlikely((__hif_tx_avail(&pfe->hif) < n_desc) || |
|
| 49 |
+- (hif_lib_tx_avail(&priv->client, queuenum) < n_desc) || |
|
| 50 |
++ (hif_lib_tx_avail(&priv->client, queuenum) < n_desc) || |
|
| 51 |
+ (hif_lib_tx_credit_avail(pfe, priv->id, queuenum) < n_segs))) {
|
|
| 52 |
++ if (!tried) {
|
|
| 53 |
++ __hif_lib_update_credit(&priv->client, queuenum); |
|
| 54 |
++ tried = 1; |
|
| 55 |
++ goto try_again; |
|
| 56 |
++ } |
|
| 57 |
+ #ifdef PFE_ETH_TX_STATS |
|
| 58 |
+ if (__hif_tx_avail(&pfe->hif) < n_desc) {
|
|
| 59 |
+ priv->stop_queue_hif[queuenum]++; |
|
| 60 |
+@@ -1692,8 +1699,10 @@ static void pfe_eth_flush_tx(struct pfe_eth_priv_s *priv) |
|
| 61 |
+ |
|
| 62 |
+ netif_info(priv, tx_done, priv->ndev, "%s\n", __func__); |
|
| 63 |
+ |
|
| 64 |
+- for (ii = 0; ii < emac_txq_cnt; ii++) |
|
| 65 |
++ for (ii = 0; ii < emac_txq_cnt; ii++) {
|
|
| 66 |
+ pfe_eth_flush_txQ(priv, ii, 0, 0); |
|
| 67 |
++ __hif_lib_update_credit(&priv->client, ii); |
|
| 68 |
++ } |
|
| 69 |
+ } |
|
| 70 |
+ |
|
| 71 |
+ void pfe_tx_get_req_desc(struct sk_buff *skb, unsigned int *n_desc, unsigned int |
|
| 72 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.c b/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 73 |
+index 2ec47bf952e0..eeab4ff3b6b8 100644 |
|
| 74 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 75 |
+@@ -34,7 +34,10 @@ |
|
| 76 |
+ |
|
| 77 |
+ unsigned int lro_mode; |
|
| 78 |
+ unsigned int page_mode; |
|
| 79 |
+-unsigned int tx_qos; |
|
| 80 |
++unsigned int tx_qos = 1; |
|
| 81 |
++module_param(tx_qos, uint, 0444); |
|
| 82 |
++MODULE_PARM_DESC(tx_qos, "0: disable ,\n" |
|
| 83 |
++ "1: enable (default), guarantee no packet drop at TMU level\n"); |
|
| 84 |
+ unsigned int pfe_pkt_size; |
|
| 85 |
+ unsigned int pfe_pkt_headroom; |
|
| 86 |
+ unsigned int emac_txq_cnt; |
|
| 87 |
+@@ -576,7 +579,7 @@ void __hif_lib_update_credit(struct hif_client_s *client, unsigned int queue) |
|
| 88 |
+ |
|
| 89 |
+ if (tx_qos) {
|
|
| 90 |
+ tmu_tx_packets = be32_to_cpu(pe_dmem_read(TMU0_ID + |
|
| 91 |
+- client->id, TMU_DM_TX_TRANS, 4)); |
|
| 92 |
++ client->id, (TMU_DM_TX_TRANS + (queue * 4)), 4)); |
|
| 93 |
+ |
|
| 94 |
+ /* tx_packets counter overflowed */ |
|
| 95 |
+ if (tmu_tx_packets > |
|
| 96 |
+-- |
|
| 97 |
+2.14.2 |
|
| 98 |
+ |
| 0 | 99 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,89 @@ |
| 0 |
+From a9327228db24a51da3e01cd770690b66fe475e47 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com> |
|
| 2 |
+Date: Wed, 29 Nov 2017 12:08:00 +0530 |
|
| 3 |
+Subject: [PATCH 09/22] staging: fsl_ppfe/eth: Enable PFE in clause 45 mode |
|
| 4 |
+ |
|
| 5 |
+when we opearate in clause 45 mode, we need to call |
|
| 6 |
+the function get_phy_device() with its 3rd argument as |
|
| 7 |
+"true" and then the resultant phy device needs to be |
|
| 8 |
+register with phy layer via phy_device_register() |
|
| 9 |
+ |
|
| 10 |
+Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com> |
|
| 11 |
+ |
|
| 12 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 13 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 14 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 15 |
+] |
|
| 16 |
+ |
|
| 17 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 18 |
+--- |
|
| 19 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 32 +++++++++++++++++++++++++++++--- |
|
| 20 |
+ 1 file changed, 29 insertions(+), 3 deletions(-) |
|
| 21 |
+ |
|
| 22 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 23 |
+index 8771ad5c0634..8d2b1da0cc20 100644 |
|
| 24 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 25 |
+@@ -923,7 +923,8 @@ static int pfe_eth_mdio_init(struct pfe_eth_priv_s *priv, |
|
| 26 |
+ struct ls1012a_mdio_platform_data *minfo) |
|
| 27 |
+ {
|
|
| 28 |
+ struct mii_bus *bus; |
|
| 29 |
+- int rc; |
|
| 30 |
++ int rc, ii; |
|
| 31 |
++ struct phy_device *phydev; |
|
| 32 |
+ |
|
| 33 |
+ netif_info(priv, drv, priv->ndev, "%s\n", __func__); |
|
| 34 |
+ pr_info("%s\n", __func__);
|
|
| 35 |
+@@ -962,6 +963,31 @@ static int pfe_eth_mdio_init(struct pfe_eth_priv_s *priv, |
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ priv->mii_bus = bus; |
|
| 39 |
++ |
|
| 40 |
++ /* For clause 45 we need to call get_phy_device() with it's |
|
| 41 |
++ * 3rd argument as true and then register the phy device |
|
| 42 |
++ * via phy_device_register() |
|
| 43 |
++ */ |
|
| 44 |
++ |
|
| 45 |
++ if (priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) {
|
|
| 46 |
++ for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) {
|
|
| 47 |
++ phydev = get_phy_device(priv->mii_bus, |
|
| 48 |
++ priv->einfo->phy_id + ii, true); |
|
| 49 |
++ if (!phydev || IS_ERR(phydev)) {
|
|
| 50 |
++ rc = -EIO; |
|
| 51 |
++ netdev_err(priv->ndev, "fail to get device\n"); |
|
| 52 |
++ goto err1; |
|
| 53 |
++ } |
|
| 54 |
++ rc = phy_device_register(phydev); |
|
| 55 |
++ if (rc) {
|
|
| 56 |
++ phy_device_free(phydev); |
|
| 57 |
++ netdev_err(priv->ndev, |
|
| 58 |
++ "phy_device_register() failed\n"); |
|
| 59 |
++ goto err1; |
|
| 60 |
++ } |
|
| 61 |
++ } |
|
| 62 |
++ } |
|
| 63 |
++ |
|
| 64 |
+ pfe_eth_mdio_reset(bus); |
|
| 65 |
+ |
|
| 66 |
+ return 0; |
|
| 67 |
+@@ -1149,7 +1175,7 @@ static void ls1012a_configure_serdes(struct net_device *ndev) |
|
| 68 |
+ int sgmii_2500 = 0; |
|
| 69 |
+ struct mii_bus *bus = priv->mii_bus; |
|
| 70 |
+ |
|
| 71 |
+- if (priv->einfo->mii_config == PHY_INTERFACE_MODE_SGMII_2500) |
|
| 72 |
++ if (priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) |
|
| 73 |
+ sgmii_2500 = 1; |
|
| 74 |
+ |
|
| 75 |
+ netif_info(priv, drv, ndev, "%s\n", __func__); |
|
| 76 |
+@@ -1198,7 +1224,7 @@ static int pfe_phy_init(struct net_device *ndev) |
|
| 77 |
+ netif_info(priv, drv, ndev, "%s: %s\n", __func__, phy_id); |
|
| 78 |
+ interface = priv->einfo->mii_config; |
|
| 79 |
+ if ((interface == PHY_INTERFACE_MODE_SGMII) || |
|
| 80 |
+- (interface == PHY_INTERFACE_MODE_SGMII_2500)) {
|
|
| 81 |
++ (interface == PHY_INTERFACE_MODE_2500SGMII)) {
|
|
| 82 |
+ /*Configure SGMII PCS */ |
|
| 83 |
+ if (pfe->scfg) {
|
|
| 84 |
+ /*Config MDIO from serdes */ |
|
| 85 |
+-- |
|
| 86 |
+2.14.2 |
|
| 87 |
+ |
| 0 | 88 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,55 @@ |
| 0 |
+From 1ba5f5745e480b7d1a5627f396f343e546f6c395 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com> |
|
| 2 |
+Date: Wed, 29 Nov 2017 12:21:43 +0530 |
|
| 3 |
+Subject: [PATCH 10/22] staging: fsl_ppfe/eth: Disable autonegotiation for 2.5G |
|
| 4 |
+ SGMII |
|
| 5 |
+ |
|
| 6 |
+PCS initialization sequence for 2.5G SGMII interface governs |
|
| 7 |
+auto negotiation to be in disabled mode |
|
| 8 |
+ |
|
| 9 |
+Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com> |
|
| 10 |
+ |
|
| 11 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 12 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 13 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 14 |
+] |
|
| 15 |
+ |
|
| 16 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 17 |
+--- |
|
| 18 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 7 +++++-- |
|
| 19 |
+ 1 file changed, 5 insertions(+), 2 deletions(-) |
|
| 20 |
+ |
|
| 21 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 22 |
+index 8d2b1da0cc20..9e8850b28990 100644 |
|
| 23 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 24 |
+@@ -1174,6 +1174,7 @@ static void ls1012a_configure_serdes(struct net_device *ndev) |
|
| 25 |
+ struct pfe_eth_priv_s *priv = pfe->eth.eth_priv[0]; |
|
| 26 |
+ int sgmii_2500 = 0; |
|
| 27 |
+ struct mii_bus *bus = priv->mii_bus; |
|
| 28 |
++ u16 value = 0; |
|
| 29 |
+ |
|
| 30 |
+ if (priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) |
|
| 31 |
+ sgmii_2500 = 1; |
|
| 32 |
+@@ -1191,14 +1192,16 @@ static void ls1012a_configure_serdes(struct net_device *ndev) |
|
| 33 |
+ pfe_eth_mdio_write(bus, 0, 0x4, 0x4001); |
|
| 34 |
+ pfe_eth_mdio_write(bus, 0, 0x12, 0xa120); |
|
| 35 |
+ pfe_eth_mdio_write(bus, 0, 0x13, 0x7); |
|
| 36 |
++ /* Autonegotiation need to be disabled for 2.5G SGMII mode*/ |
|
| 37 |
++ value = 0x0140; |
|
| 38 |
++ pfe_eth_mdio_write(bus, 0, 0x0, value); |
|
| 39 |
+ } else {
|
|
| 40 |
+ pfe_eth_mdio_write(bus, 0, 0x14, 0xb); |
|
| 41 |
+ pfe_eth_mdio_write(bus, 0, 0x4, 0x1a1); |
|
| 42 |
+ pfe_eth_mdio_write(bus, 0, 0x12, 0x400); |
|
| 43 |
+ pfe_eth_mdio_write(bus, 0, 0x13, 0x0); |
|
| 44 |
++ pfe_eth_mdio_write(bus, 0, 0x0, 0x1140); |
|
| 45 |
+ } |
|
| 46 |
+- |
|
| 47 |
+- pfe_eth_mdio_write(bus, 0, 0x0, 0x1140); |
|
| 48 |
+ } |
|
| 49 |
+ |
|
| 50 |
+ /* |
|
| 51 |
+-- |
|
| 52 |
+2.14.2 |
|
| 53 |
+ |
| 0 | 54 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,43 @@ |
| 0 |
+From 389086e1ab9c389224f6c6c79b6ab3b764044973 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Guanhua Gao <guanhua.gao@nxp.com> |
|
| 2 |
+Date: Fri, 12 Jan 2018 16:28:20 +0800 |
|
| 3 |
+Subject: [PATCH 11/22] staging: fsl_ppfe/eth: add missing included header file |
|
| 4 |
+MIME-Version: 1.0 |
|
| 5 |
+Content-Type: text/plain; charset=UTF-8 |
|
| 6 |
+Content-Transfer-Encoding: 8bit |
|
| 7 |
+ |
|
| 8 |
+ppfe compilation on dash-lts 4.14 reports error: |
|
| 9 |
+In file included from drivers/staging/fsl_ppfe/pfe_mod.h:30:0, |
|
| 10 |
+ from drivers/staging/fsl_ppfe/pfe_mod.c:20: |
|
| 11 |
+drivers/staging/fsl_ppfe/pfe_hif.h:172:24: error: field â_cleanup_taskletâas incomplete type |
|
| 12 |
+ struct tasklet_struct tx_cleanup_tasklet; |
|
| 13 |
+ |
|
| 14 |
+The structure tasklet_struct is defined in interrupt.h, add it to fix the compilation error. |
|
| 15 |
+ |
|
| 16 |
+Signed-off-by: Guanhua Gao <guanhua.gao@nxp.com> |
|
| 17 |
+ |
|
| 18 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 19 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 20 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 21 |
+] |
|
| 22 |
+ |
|
| 23 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 24 |
+--- |
|
| 25 |
+ drivers/staging/fsl_ppfe/pfe_hif.h | 1 + |
|
| 26 |
+ 1 file changed, 1 insertion(+) |
|
| 27 |
+ |
|
| 28 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif.h b/drivers/staging/fsl_ppfe/pfe_hif.h |
|
| 29 |
+index 6e36f0c1f4ff..8281adb12cd7 100644 |
|
| 30 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif.h |
|
| 31 |
+@@ -20,6 +20,7 @@ |
|
| 32 |
+ #define _PFE_HIF_H_ |
|
| 33 |
+ |
|
| 34 |
+ #include <linux/netdevice.h> |
|
| 35 |
++#include <linux/interrupt.h> |
|
| 36 |
+ |
|
| 37 |
+ #define HIF_NAPI_STATS |
|
| 38 |
+ |
|
| 39 |
+-- |
|
| 40 |
+2.14.2 |
|
| 41 |
+ |
| 0 | 42 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,59 @@ |
| 0 |
+From 429966138df2fbc6a81203d587f87d12bb071b05 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Yangbo Lu <yangbo.lu@nxp.com> |
|
| 2 |
+Date: Tue, 30 Jan 2018 20:22:24 +0800 |
|
| 3 |
+Subject: [PATCH 12/22] staging: fsl_ppfe/eth: clean up |
|
| 4 |
+ iounmap(pfe->ddr_baseaddr) |
|
| 5 |
+ |
|
| 6 |
+pfe->ddr_baseaddr was got through phys_to_virt() not ioremap(), |
|
| 7 |
+so iounmap() for pfe->ddr_baseaddr should be removed. |
|
| 8 |
+ |
|
| 9 |
+Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> |
|
| 10 |
+ |
|
| 11 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 12 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 13 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 14 |
+] |
|
| 15 |
+ |
|
| 16 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 17 |
+--- |
|
| 18 |
+ drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c | 9 --------- |
|
| 19 |
+ 1 file changed, 9 deletions(-) |
|
| 20 |
+ |
|
| 21 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c b/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c |
|
| 22 |
+index c579eb58f277..f3eb88de66a4 100644 |
|
| 23 |
+--- a/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c |
|
| 24 |
+@@ -169,13 +169,7 @@ static int pfe_platform_probe(struct platform_device *pdev) |
|
| 25 |
+ |
|
| 26 |
+ pfe->ddr_phys_baseaddr = res.start; |
|
| 27 |
+ pfe->ddr_size = resource_size(&res); |
|
| 28 |
+- |
|
| 29 |
+ pfe->ddr_baseaddr = phys_to_virt(res.start); |
|
| 30 |
+- if (!pfe->ddr_baseaddr) {
|
|
| 31 |
+- pr_err("ioremap() ddr failed\n");
|
|
| 32 |
+- rc = -ENOMEM; |
|
| 33 |
+- goto err_ddr; |
|
| 34 |
+- } |
|
| 35 |
+ |
|
| 36 |
+ pfe->scfg = |
|
| 37 |
+ syscon_regmap_lookup_by_phandle(pdev->dev.of_node, |
|
| 38 |
+@@ -257,8 +251,6 @@ static int pfe_platform_probe(struct platform_device *pdev) |
|
| 39 |
+ iounmap(pfe->cbus_baseaddr); |
|
| 40 |
+ |
|
| 41 |
+ err_axi: |
|
| 42 |
+- iounmap(pfe->ddr_baseaddr); |
|
| 43 |
+- |
|
| 44 |
+ err_ddr: |
|
| 45 |
+ platform_set_drvdata(pdev, NULL); |
|
| 46 |
+ |
|
| 47 |
+@@ -281,7 +273,6 @@ static int pfe_platform_remove(struct platform_device *pdev) |
|
| 48 |
+ rc = pfe_remove(pfe); |
|
| 49 |
+ |
|
| 50 |
+ iounmap(pfe->cbus_baseaddr); |
|
| 51 |
+- iounmap(pfe->ddr_baseaddr); |
|
| 52 |
+ |
|
| 53 |
+ platform_set_drvdata(pdev, NULL); |
|
| 54 |
+ |
|
| 55 |
+-- |
|
| 56 |
+2.14.2 |
|
| 57 |
+ |
| 0 | 58 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,42 @@ |
| 0 |
+From 105bded455f8893a6cb7c28b061609d59d5734a7 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Thu, 8 Mar 2018 13:58:38 +0530 |
|
| 3 |
+Subject: [PATCH 13/22] staging: fsl_ppfe/eth: calculate PFE_PKT_SIZE with |
|
| 4 |
+ SKB_DATA_ALIGN |
|
| 5 |
+ |
|
| 6 |
+pfe packet size was calculated without considering skb data alignment |
|
| 7 |
+and this resulted in jumbo frames crashing kernel when the |
|
| 8 |
+cacheline size increased from 64 to 128 bytes with |
|
| 9 |
+commit 97303480753e ("arm64: Increase the max granular size").
|
|
| 10 |
+ |
|
| 11 |
+Modify pfe packet size caclulation to include skb data alignment of |
|
| 12 |
+sizeof(struct skb_shared_info). |
|
| 13 |
+ |
|
| 14 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 15 |
+ |
|
| 16 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 17 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 18 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 19 |
+] |
|
| 20 |
+ |
|
| 21 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 22 |
+--- |
|
| 23 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.h | 2 +- |
|
| 24 |
+ 1 file changed, 1 insertion(+), 1 deletion(-) |
|
| 25 |
+ |
|
| 26 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.h b/drivers/staging/fsl_ppfe/pfe_hif_lib.h |
|
| 27 |
+index d48eb14a29b8..08031f1f3117 100644 |
|
| 28 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif_lib.h |
|
| 29 |
+@@ -146,7 +146,7 @@ struct tx_queue_desc {
|
|
| 30 |
+ #define PFE_BUF_SIZE 2048 |
|
| 31 |
+ #define PFE_PKT_HEADROOM 128 |
|
| 32 |
+ |
|
| 33 |
+-#define SKB_SHARED_INFO_SIZE (sizeof(struct skb_shared_info)) |
|
| 34 |
++#define SKB_SHARED_INFO_SIZE SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) |
|
| 35 |
+ #define PFE_PKT_SIZE (PFE_BUF_SIZE - PFE_PKT_HEADROOM \ |
|
| 36 |
+ - SKB_SHARED_INFO_SIZE) |
|
| 37 |
+ #define MAX_L2_HDR_SIZE 14 /* Not correct for VLAN/PPPoE */ |
|
| 38 |
+-- |
|
| 39 |
+2.14.2 |
|
| 40 |
+ |
| 0 | 41 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,171 @@ |
| 0 |
+From 6425d31ff45a3fd0984ada7fb9440618d785b31b Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Akhil Goyal <akhil.goyal@nxp.com> |
|
| 2 |
+Date: Fri, 13 Apr 2018 15:41:28 +0530 |
|
| 3 |
+Subject: [PATCH 14/22] staging: fsl_ppfe/eth: support for userspace networking |
|
| 4 |
+ |
|
| 5 |
+This patch adds the userspace mode support to fsl_ppfe network driver. |
|
| 6 |
+In the new mode, basic hardware initialization is performed in kernel, while |
|
| 7 |
+the datapath and HIF handling is the responsibility of the userspace. |
|
| 8 |
+ |
|
| 9 |
+The new command line parameter is added to initialize the ppfe module |
|
| 10 |
+in userspace mode. By default the module remains in kernelspace networking |
|
| 11 |
+mode. |
|
| 12 |
+To enable userspace mode, use "insmod pfe.ko us=1" |
|
| 13 |
+ |
|
| 14 |
+Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com> |
|
| 15 |
+Signed-off-by: Gagandeep Singh <g.singh@nxp.com> |
|
| 16 |
+ |
|
| 17 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 18 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 19 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 20 |
+] |
|
| 21 |
+ |
|
| 22 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 23 |
+--- |
|
| 24 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 21 +++++++++++++++++++-- |
|
| 25 |
+ drivers/staging/fsl_ppfe/pfe_mod.c | 15 +++++++++++++++ |
|
| 26 |
+ drivers/staging/fsl_ppfe/pfe_mod.h | 2 ++ |
|
| 27 |
+ 3 files changed, 36 insertions(+), 2 deletions(-) |
|
| 28 |
+ |
|
| 29 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 30 |
+index 9e8850b28990..297aa01b695a 100644 |
|
| 31 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 32 |
+@@ -2296,6 +2296,8 @@ static int pfe_eth_init_one(struct pfe *pfe, int id) |
|
| 33 |
+ goto err0; |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
++ if (us) |
|
| 37 |
++ emac_txq_cnt = EMAC_TXQ_CNT; |
|
| 38 |
+ /* Create an ethernet device instance */ |
|
| 39 |
+ ndev = alloc_etherdev_mq(sizeof(*priv), emac_txq_cnt); |
|
| 40 |
+ |
|
| 41 |
+@@ -2342,6 +2344,9 @@ static int pfe_eth_init_one(struct pfe *pfe, int id) |
|
| 42 |
+ } |
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
++ if (us) |
|
| 46 |
++ goto phy_init; |
|
| 47 |
++ |
|
| 48 |
+ ndev->mtu = 1500; |
|
| 49 |
+ |
|
| 50 |
+ /* Set MTU limits */ |
|
| 51 |
+@@ -2381,6 +2386,8 @@ static int pfe_eth_init_one(struct pfe *pfe, int id) |
|
| 52 |
+ netdev_err(ndev, "register_netdev() failed\n"); |
|
| 53 |
+ goto err3; |
|
| 54 |
+ } |
|
| 55 |
++ |
|
| 56 |
++phy_init: |
|
| 57 |
+ device_init_wakeup(&ndev->dev, WAKE_MAGIC); |
|
| 58 |
+ |
|
| 59 |
+ if (!(priv->einfo->phy_flags & GEMAC_NO_PHY)) {
|
|
| 60 |
+@@ -2392,6 +2399,12 @@ static int pfe_eth_init_one(struct pfe *pfe, int id) |
|
| 61 |
+ } |
|
| 62 |
+ } |
|
| 63 |
+ |
|
| 64 |
++ if (us) {
|
|
| 65 |
++ if (priv->phydev) |
|
| 66 |
++ phy_start(priv->phydev); |
|
| 67 |
++ return 0; |
|
| 68 |
++ } |
|
| 69 |
++ |
|
| 70 |
+ netif_carrier_on(ndev); |
|
| 71 |
+ |
|
| 72 |
+ /* Create all the sysfs files */ |
|
| 73 |
+@@ -2403,6 +2416,8 @@ static int pfe_eth_init_one(struct pfe *pfe, int id) |
|
| 74 |
+ |
|
| 75 |
+ return 0; |
|
| 76 |
+ err4: |
|
| 77 |
++ if (us) |
|
| 78 |
++ goto err3; |
|
| 79 |
+ unregister_netdev(ndev); |
|
| 80 |
+ err3: |
|
| 81 |
+ pfe_eth_mdio_exit(priv->mii_bus); |
|
| 82 |
+@@ -2449,9 +2464,11 @@ static void pfe_eth_exit_one(struct pfe_eth_priv_s *priv) |
|
| 83 |
+ {
|
|
| 84 |
+ netif_info(priv, probe, priv->ndev, "%s\n", __func__); |
|
| 85 |
+ |
|
| 86 |
+- pfe_eth_sysfs_exit(priv->ndev); |
|
| 87 |
++ if (!us) {
|
|
| 88 |
++ pfe_eth_sysfs_exit(priv->ndev); |
|
| 89 |
+ |
|
| 90 |
+- unregister_netdev(priv->ndev); |
|
| 91 |
++ unregister_netdev(priv->ndev); |
|
| 92 |
++ } |
|
| 93 |
+ |
|
| 94 |
+ if (!(priv->einfo->phy_flags & GEMAC_NO_PHY)) |
|
| 95 |
+ pfe_phy_exit(priv->ndev); |
|
| 96 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_mod.c b/drivers/staging/fsl_ppfe/pfe_mod.c |
|
| 97 |
+index d5ba56a3c73f..ca418456c26f 100644 |
|
| 98 |
+--- a/drivers/staging/fsl_ppfe/pfe_mod.c |
|
| 99 |
+@@ -19,6 +19,10 @@ |
|
| 100 |
+ #include <linux/dma-mapping.h> |
|
| 101 |
+ #include "pfe_mod.h" |
|
| 102 |
+ |
|
| 103 |
++unsigned int us; |
|
| 104 |
++module_param(us, uint, 0444); |
|
| 105 |
++MODULE_PARM_DESC(us, "0: module enabled for kernel networking (DEFAULT)\n" |
|
| 106 |
++ "1: module enabled for userspace networking\n"); |
|
| 107 |
+ struct pfe *pfe; |
|
| 108 |
+ |
|
| 109 |
+ /* |
|
| 110 |
+@@ -56,6 +60,9 @@ int pfe_probe(struct pfe *pfe) |
|
| 111 |
+ if (rc < 0) |
|
| 112 |
+ goto err_hw; |
|
| 113 |
+ |
|
| 114 |
++ if (us) |
|
| 115 |
++ goto firmware_init; |
|
| 116 |
++ |
|
| 117 |
+ rc = pfe_hif_lib_init(pfe); |
|
| 118 |
+ if (rc < 0) |
|
| 119 |
+ goto err_hif_lib; |
|
| 120 |
+@@ -64,6 +71,7 @@ int pfe_probe(struct pfe *pfe) |
|
| 121 |
+ if (rc < 0) |
|
| 122 |
+ goto err_hif; |
|
| 123 |
+ |
|
| 124 |
++firmware_init: |
|
| 125 |
+ rc = pfe_firmware_init(pfe); |
|
| 126 |
+ if (rc < 0) |
|
| 127 |
+ goto err_firmware; |
|
| 128 |
+@@ -99,6 +107,9 @@ int pfe_probe(struct pfe *pfe) |
|
| 129 |
+ pfe_firmware_exit(pfe); |
|
| 130 |
+ |
|
| 131 |
+ err_firmware: |
|
| 132 |
++ if (us) |
|
| 133 |
++ goto err_hif_lib; |
|
| 134 |
++ |
|
| 135 |
+ pfe_hif_exit(pfe); |
|
| 136 |
+ |
|
| 137 |
+ err_hif: |
|
| 138 |
+@@ -131,10 +142,14 @@ int pfe_remove(struct pfe *pfe) |
|
| 139 |
+ #endif |
|
| 140 |
+ pfe_firmware_exit(pfe); |
|
| 141 |
+ |
|
| 142 |
++ if (us) |
|
| 143 |
++ goto hw_exit; |
|
| 144 |
++ |
|
| 145 |
+ pfe_hif_exit(pfe); |
|
| 146 |
+ |
|
| 147 |
+ pfe_hif_lib_exit(pfe); |
|
| 148 |
+ |
|
| 149 |
++hw_exit: |
|
| 150 |
+ pfe_hw_exit(pfe); |
|
| 151 |
+ |
|
| 152 |
+ return 0; |
|
| 153 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_mod.h b/drivers/staging/fsl_ppfe/pfe_mod.h |
|
| 154 |
+index 3012f17fef31..014ae65ca34a 100644 |
|
| 155 |
+--- a/drivers/staging/fsl_ppfe/pfe_mod.h |
|
| 156 |
+@@ -22,6 +22,8 @@ |
|
| 157 |
+ #include <linux/device.h> |
|
| 158 |
+ #include <linux/elf.h> |
|
| 159 |
+ |
|
| 160 |
++extern unsigned int us; |
|
| 161 |
++ |
|
| 162 |
+ struct pfe; |
|
| 163 |
+ |
|
| 164 |
+ #include "pfe_hw.h" |
|
| 165 |
+-- |
|
| 166 |
+2.14.2 |
|
| 167 |
+ |
| 0 | 168 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,57 @@ |
| 0 |
+From 09626eade30d9c41ce18fdcc9f566c3aba9ee716 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Mon, 30 Apr 2018 11:40:01 +0530 |
|
| 3 |
+Subject: [PATCH 15/22] staging: fsl_ppfe/eth: unregister netdev after |
|
| 4 |
+ pfe_phy_exit |
|
| 5 |
+ |
|
| 6 |
+rmmod pfe.ko throws below warning: |
|
| 7 |
+ |
|
| 8 |
+kernfs: can not remove 'phydev', no directory |
|
| 9 |
+------------[ cut here ]------------ |
|
| 10 |
+WARNING: CPU: 0 PID: 2230 at fs/kernfs/dir.c:1481 |
|
| 11 |
+kernfs_remove_by_name_ns+0x90/0xa0 |
|
| 12 |
+ |
|
| 13 |
+This is caused when the unregistered netdev structure is accessed to |
|
| 14 |
+disconnect phy. |
|
| 15 |
+ |
|
| 16 |
+Resolve the issue by unregistering netdev after disconnecting phy. |
|
| 17 |
+ |
|
| 18 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 19 |
+ |
|
| 20 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 21 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 22 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 23 |
+] |
|
| 24 |
+ |
|
| 25 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 26 |
+--- |
|
| 27 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 8 ++++---- |
|
| 28 |
+ 1 file changed, 4 insertions(+), 4 deletions(-) |
|
| 29 |
+ |
|
| 30 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 31 |
+index 297aa01b695a..265045fcb008 100644 |
|
| 32 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 33 |
+@@ -2464,15 +2464,15 @@ static void pfe_eth_exit_one(struct pfe_eth_priv_s *priv) |
|
| 34 |
+ {
|
|
| 35 |
+ netif_info(priv, probe, priv->ndev, "%s\n", __func__); |
|
| 36 |
+ |
|
| 37 |
+- if (!us) {
|
|
| 38 |
++ if (!us) |
|
| 39 |
+ pfe_eth_sysfs_exit(priv->ndev); |
|
| 40 |
+ |
|
| 41 |
+- unregister_netdev(priv->ndev); |
|
| 42 |
+- } |
|
| 43 |
+- |
|
| 44 |
+ if (!(priv->einfo->phy_flags & GEMAC_NO_PHY)) |
|
| 45 |
+ pfe_phy_exit(priv->ndev); |
|
| 46 |
+ |
|
| 47 |
++ if (!us) |
|
| 48 |
++ unregister_netdev(priv->ndev); |
|
| 49 |
++ |
|
| 50 |
+ if (priv->mii_bus) |
|
| 51 |
+ pfe_eth_mdio_exit(priv->mii_bus); |
|
| 52 |
+ |
|
| 53 |
+-- |
|
| 54 |
+2.14.2 |
|
| 55 |
+ |
| 0 | 56 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,61 @@ |
| 0 |
+From d799c0372e6bde0f6b8786bb1705de46115b05b6 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: anuj batham <anuj.batham@nxp.com> |
|
| 2 |
+Date: Fri, 27 Apr 2018 14:38:09 +0530 |
|
| 3 |
+Subject: [PATCH 16/22] staging: fsl_ppfe/eth: HW parse results for DPDK |
|
| 4 |
+ |
|
| 5 |
+HW Parse results are included in the packet headroom. |
|
| 6 |
+Length and Offset calculation now accommodates parse info size. |
|
| 7 |
+ |
|
| 8 |
+Signed-off-by: Archana Madhavan <archana.madhavan@nxp.com> |
|
| 9 |
+ |
|
| 10 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 11 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 12 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 13 |
+] |
|
| 14 |
+ |
|
| 15 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 16 |
+--- |
|
| 17 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.c | 7 +++++-- |
|
| 18 |
+ drivers/staging/fsl_ppfe/pfe_hif_lib.h | 1 + |
|
| 19 |
+ 2 files changed, 6 insertions(+), 2 deletions(-) |
|
| 20 |
+ |
|
| 21 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.c b/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 22 |
+index eeab4ff3b6b8..16fcf2daeef8 100644 |
|
| 23 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif_lib.c |
|
| 24 |
+@@ -435,6 +435,7 @@ void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int |
|
| 25 |
+ u16 size = *rx_ctrl >> HIF_CTRL_RX_OFFSET_OFST; |
|
| 26 |
+ |
|
| 27 |
+ if (size) {
|
|
| 28 |
++ size += PFE_PARSE_INFO_SIZE; |
|
| 29 |
+ *len = CL_DESC_BUF_LEN(desc->ctrl) - |
|
| 30 |
+ PFE_PKT_HEADER_SZ - size; |
|
| 31 |
+ *ofst = pfe_pkt_headroom + PFE_PKT_HEADER_SZ |
|
| 32 |
+@@ -442,8 +443,10 @@ void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int |
|
| 33 |
+ *priv_data = desc->data + PFE_PKT_HEADER_SZ; |
|
| 34 |
+ } else {
|
|
| 35 |
+ *len = CL_DESC_BUF_LEN(desc->ctrl) - |
|
| 36 |
+- PFE_PKT_HEADER_SZ; |
|
| 37 |
+- *ofst = pfe_pkt_headroom + PFE_PKT_HEADER_SZ; |
|
| 38 |
++ PFE_PKT_HEADER_SZ - PFE_PARSE_INFO_SIZE; |
|
| 39 |
++ *ofst = pfe_pkt_headroom |
|
| 40 |
++ + PFE_PKT_HEADER_SZ |
|
| 41 |
++ + PFE_PARSE_INFO_SIZE; |
|
| 42 |
+ *priv_data = NULL; |
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hif_lib.h b/drivers/staging/fsl_ppfe/pfe_hif_lib.h |
|
| 46 |
+index 08031f1f3117..c8334a6b6a13 100644 |
|
| 47 |
+--- a/drivers/staging/fsl_ppfe/pfe_hif_lib.h |
|
| 48 |
+@@ -23,6 +23,7 @@ |
|
| 49 |
+ |
|
| 50 |
+ #define HIF_CL_REQ_TIMEOUT 10 |
|
| 51 |
+ #define GFP_DMA_PFE 0 |
|
| 52 |
++#define PFE_PARSE_INFO_SIZE 16 |
|
| 53 |
+ |
|
| 54 |
+ enum {
|
|
| 55 |
+ REQUEST_CL_REGISTER = 0, |
|
| 56 |
+-- |
|
| 57 |
+2.14.2 |
|
| 58 |
+ |
| 0 | 59 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,42 @@ |
| 0 |
+From ab625957c7d169031b91bc7dba0d72bbee063fff Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 20 Jun 2018 10:22:32 +0530 |
|
| 3 |
+Subject: [PATCH 17/22] staging: fsl_ppfe/eth: reorganize pfe_netdev_ops |
|
| 4 |
+ |
|
| 5 |
+Reorganize members of struct pfe_netdev_ops to match with the order |
|
| 6 |
+of members in struct net_device_ops defined in include/linux/netdevice.h |
|
| 7 |
+ |
|
| 8 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 9 |
+ |
|
| 10 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 11 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 12 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 13 |
+] |
|
| 14 |
+ |
|
| 15 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 16 |
+--- |
|
| 17 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 6 +++--- |
|
| 18 |
+ 1 file changed, 3 insertions(+), 3 deletions(-) |
|
| 19 |
+ |
|
| 20 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 21 |
+index 265045fcb008..0aa08d251b7c 100644 |
|
| 22 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 23 |
+@@ -2243,11 +2243,11 @@ static const struct net_device_ops pfe_netdev_ops = {
|
|
| 24 |
+ .ndo_stop = pfe_eth_close, |
|
| 25 |
+ .ndo_start_xmit = pfe_eth_send_packet, |
|
| 26 |
+ .ndo_select_queue = pfe_eth_select_queue, |
|
| 27 |
+- .ndo_get_stats = pfe_eth_get_stats, |
|
| 28 |
+- .ndo_set_mac_address = pfe_eth_set_mac_address, |
|
| 29 |
+ .ndo_set_rx_mode = pfe_eth_set_multi, |
|
| 30 |
+- .ndo_set_features = pfe_eth_set_features, |
|
| 31 |
++ .ndo_set_mac_address = pfe_eth_set_mac_address, |
|
| 32 |
+ .ndo_validate_addr = eth_validate_addr, |
|
| 33 |
++ .ndo_get_stats = pfe_eth_get_stats, |
|
| 34 |
++ .ndo_set_features = pfe_eth_set_features, |
|
| 35 |
+ }; |
|
| 36 |
+ |
|
| 37 |
+ /* pfe_eth_init_one |
|
| 38 |
+-- |
|
| 39 |
+2.14.2 |
|
| 40 |
+ |
| 0 | 41 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,58 @@ |
| 0 |
+From 1f2258f3645c6ed5eebda50b4b575b67330ec04e Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 20 Jun 2018 10:22:50 +0530 |
|
| 3 |
+Subject: [PATCH 18/22] staging: fsl_ppfe/eth: use mask for rx max frame len |
|
| 4 |
+ |
|
| 5 |
+Define and use PFE_RCR_MAX_FL_MASK to properly set Rx max frame |
|
| 6 |
+length of MAC Receive Control Register. |
|
| 7 |
+ |
|
| 8 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 9 |
+ |
|
| 10 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 11 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 12 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 13 |
+] |
|
| 14 |
+ |
|
| 15 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 16 |
+--- |
|
| 17 |
+ drivers/staging/fsl_ppfe/pfe_hal.c | 10 ++++++---- |
|
| 18 |
+ 1 file changed, 6 insertions(+), 4 deletions(-) |
|
| 19 |
+ |
|
| 20 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hal.c b/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 21 |
+index 0915034b281b..7e89606bb40c 100644 |
|
| 22 |
+--- a/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 23 |
+@@ -19,6 +19,8 @@ |
|
| 24 |
+ #include "pfe_mod.h" |
|
| 25 |
+ #include "pfe/pfe.h" |
|
| 26 |
+ |
|
| 27 |
++#define PFE_RCR_MAX_FL_MASK 0xC000FFFF |
|
| 28 |
++ |
|
| 29 |
+ void *cbus_base_addr; |
|
| 30 |
+ void *ddr_base_addr; |
|
| 31 |
+ unsigned long ddr_phys_base_addr; |
|
| 32 |
+@@ -1011,8 +1013,8 @@ void gemac_no_broadcast(void *base) |
|
| 33 |
+ void gemac_enable_1536_rx(void *base) |
|
| 34 |
+ {
|
|
| 35 |
+ /* Set 1536 as Maximum frame length */ |
|
| 36 |
+- writel(readl(base + EMAC_RCNTRL_REG) | (1536 << 16), base + |
|
| 37 |
+- EMAC_RCNTRL_REG); |
|
| 38 |
++ writel((readl(base + EMAC_RCNTRL_REG) & PFE_RCR_MAX_FL_MASK) |
|
| 39 |
++ | (1536 << 16), base + EMAC_RCNTRL_REG); |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ /* GEMAC enable jumbo function. |
|
| 43 |
+@@ -1020,8 +1022,8 @@ void gemac_enable_1536_rx(void *base) |
|
| 44 |
+ */ |
|
| 45 |
+ void gemac_enable_rx_jmb(void *base) |
|
| 46 |
+ {
|
|
| 47 |
+- writel(readl(base + EMAC_RCNTRL_REG) | (JUMBO_FRAME_SIZE << 16), base |
|
| 48 |
+- + EMAC_RCNTRL_REG); |
|
| 49 |
++ writel((readl(base + EMAC_RCNTRL_REG) & PFE_RCR_MAX_FL_MASK) |
|
| 50 |
++ | (JUMBO_FRAME_SIZE << 16), base + EMAC_RCNTRL_REG); |
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ /* GEMAC enable stacked vlan function. |
|
| 54 |
+-- |
|
| 55 |
+2.14.2 |
|
| 56 |
+ |
| 0 | 57 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,90 @@ |
| 0 |
+From bfd03698e85a6bff663280e538dab2eea4fb90ff Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 20 Jun 2018 10:23:01 +0530 |
|
| 3 |
+Subject: [PATCH 19/22] staging: fsl_ppfe/eth: define pfe ndo_change_mtu |
|
| 4 |
+ function |
|
| 5 |
+ |
|
| 6 |
+Define ndo_change_mtu function for pfe. This sets the max Rx frame |
|
| 7 |
+length to the new mtu. |
|
| 8 |
+ |
|
| 9 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 10 |
+ |
|
| 11 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 12 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 13 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 14 |
+] |
|
| 15 |
+ |
|
| 16 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 17 |
+--- |
|
| 18 |
+ drivers/staging/fsl_ppfe/include/pfe/pfe.h | 1 + |
|
| 19 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 12 ++++++++++++ |
|
| 20 |
+ drivers/staging/fsl_ppfe/pfe_hal.c | 11 +++++++++++ |
|
| 21 |
+ 3 files changed, 24 insertions(+) |
|
| 22 |
+ |
|
| 23 |
+diff --git a/drivers/staging/fsl_ppfe/include/pfe/pfe.h b/drivers/staging/fsl_ppfe/include/pfe/pfe.h |
|
| 24 |
+index d93ae4c60251..79eeafa60eb6 100644 |
|
| 25 |
+--- a/drivers/staging/fsl_ppfe/include/pfe/pfe.h |
|
| 26 |
+@@ -303,6 +303,7 @@ void gemac_allow_broadcast(void *base); |
|
| 27 |
+ void gemac_no_broadcast(void *base); |
|
| 28 |
+ void gemac_enable_1536_rx(void *base); |
|
| 29 |
+ void gemac_disable_1536_rx(void *base); |
|
| 30 |
++void gemac_set_rx_max_fl(void *base, int mtu); |
|
| 31 |
+ void gemac_enable_rx_jmb(void *base); |
|
| 32 |
+ void gemac_disable_rx_jmb(void *base); |
|
| 33 |
+ void gemac_enable_stacked_vlan(void *base); |
|
| 34 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 35 |
+index 0aa08d251b7c..77d7a7b682c6 100644 |
|
| 36 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 37 |
+@@ -1345,6 +1345,17 @@ static int pfe_eth_event_handler(void *data, int event, int qno) |
|
| 38 |
+ return 0; |
|
| 39 |
+ } |
|
| 40 |
+ |
|
| 41 |
++static int pfe_eth_change_mtu(struct net_device *ndev, int new_mtu) |
|
| 42 |
++{
|
|
| 43 |
++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 44 |
++ |
|
| 45 |
++ ndev->mtu = new_mtu; |
|
| 46 |
++ new_mtu += ETH_HLEN + ETH_FCS_LEN; |
|
| 47 |
++ gemac_set_rx_max_fl(priv->EMAC_baseaddr, new_mtu); |
|
| 48 |
++ |
|
| 49 |
++ return 0; |
|
| 50 |
++} |
|
| 51 |
++ |
|
| 52 |
+ /* pfe_eth_open |
|
| 53 |
+ */ |
|
| 54 |
+ static int pfe_eth_open(struct net_device *ndev) |
|
| 55 |
+@@ -2246,6 +2257,7 @@ static const struct net_device_ops pfe_netdev_ops = {
|
|
| 56 |
+ .ndo_set_rx_mode = pfe_eth_set_multi, |
|
| 57 |
+ .ndo_set_mac_address = pfe_eth_set_mac_address, |
|
| 58 |
+ .ndo_validate_addr = eth_validate_addr, |
|
| 59 |
++ .ndo_change_mtu = pfe_eth_change_mtu, |
|
| 60 |
+ .ndo_get_stats = pfe_eth_get_stats, |
|
| 61 |
+ .ndo_set_features = pfe_eth_set_features, |
|
| 62 |
+ }; |
|
| 63 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hal.c b/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 64 |
+index 7e89606bb40c..cb8cb9cbd42f 100644 |
|
| 65 |
+--- a/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 66 |
+@@ -1017,6 +1017,17 @@ void gemac_enable_1536_rx(void *base) |
|
| 67 |
+ | (1536 << 16), base + EMAC_RCNTRL_REG); |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
++/* GEMAC set rx Max frame length. |
|
| 71 |
++ * @param[in] base GEMAC base address |
|
| 72 |
++ * @param[in] mtu new mtu |
|
| 73 |
++ */ |
|
| 74 |
++void gemac_set_rx_max_fl(void *base, int mtu) |
|
| 75 |
++{
|
|
| 76 |
++ /* Set mtu as Maximum frame length */ |
|
| 77 |
++ writel((readl(base + EMAC_RCNTRL_REG) & PFE_RCR_MAX_FL_MASK) |
|
| 78 |
++ | (mtu << 16), base + EMAC_RCNTRL_REG); |
|
| 79 |
++} |
|
| 80 |
++ |
|
| 81 |
+ /* GEMAC enable jumbo function. |
|
| 82 |
+ * @param[in] base GEMAC base address |
|
| 83 |
+ */ |
|
| 84 |
+-- |
|
| 85 |
+2.14.2 |
|
| 86 |
+ |
| 0 | 87 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,60 @@ |
| 0 |
+From 26a83eb4f3f492ad5454f6ebec86efe8da7a1641 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 20 Jun 2018 10:23:16 +0530 |
|
| 3 |
+Subject: [PATCH 20/22] staging: fsl_ppfe/eth: remove jumbo frame enable from |
|
| 4 |
+ gemac init |
|
| 5 |
+ |
|
| 6 |
+MAC Receive Control Register was configured to allow jumbo frames. |
|
| 7 |
+This is removed as jumbo frames can be supported anytime by changing |
|
| 8 |
+mtu which will in turn modify MAX_FL field of MAC RCR. |
|
| 9 |
+Jumbo frames caused pfe to hang on LS1012A rev 1.0 Silicon due to |
|
| 10 |
+erratum A-010897. |
|
| 11 |
+ |
|
| 12 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 13 |
+ |
|
| 14 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 15 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 16 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 17 |
+] |
|
| 18 |
+ |
|
| 19 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 20 |
+--- |
|
| 21 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 1 - |
|
| 22 |
+ drivers/staging/fsl_ppfe/pfe_hal.c | 9 --------- |
|
| 23 |
+ 2 files changed, 10 deletions(-) |
|
| 24 |
+ |
|
| 25 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 26 |
+index 77d7a7b682c6..b272e72baf5f 100644 |
|
| 27 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 28 |
+@@ -1272,7 +1272,6 @@ static int pfe_gemac_init(struct pfe_eth_priv_s *priv) |
|
| 29 |
+ gemac_set_config(priv->EMAC_baseaddr, &cfg); |
|
| 30 |
+ gemac_allow_broadcast(priv->EMAC_baseaddr); |
|
| 31 |
+ gemac_enable_1536_rx(priv->EMAC_baseaddr); |
|
| 32 |
+- gemac_enable_rx_jmb(priv->EMAC_baseaddr); |
|
| 33 |
+ gemac_enable_stacked_vlan(priv->EMAC_baseaddr); |
|
| 34 |
+ gemac_enable_pause_rx(priv->EMAC_baseaddr); |
|
| 35 |
+ gemac_set_bus_width(priv->EMAC_baseaddr, 64); |
|
| 36 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hal.c b/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 37 |
+index cb8cb9cbd42f..cfd02ccc313a 100644 |
|
| 38 |
+--- a/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 39 |
+@@ -1028,15 +1028,6 @@ void gemac_set_rx_max_fl(void *base, int mtu) |
|
| 40 |
+ | (mtu << 16), base + EMAC_RCNTRL_REG); |
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+-/* GEMAC enable jumbo function. |
|
| 44 |
+- * @param[in] base GEMAC base address |
|
| 45 |
+- */ |
|
| 46 |
+-void gemac_enable_rx_jmb(void *base) |
|
| 47 |
+-{
|
|
| 48 |
+- writel((readl(base + EMAC_RCNTRL_REG) & PFE_RCR_MAX_FL_MASK) |
|
| 49 |
+- | (JUMBO_FRAME_SIZE << 16), base + EMAC_RCNTRL_REG); |
|
| 50 |
+-} |
|
| 51 |
+- |
|
| 52 |
+ /* GEMAC enable stacked vlan function. |
|
| 53 |
+ * @param[in] base GEMAC base address |
|
| 54 |
+ */ |
|
| 55 |
+-- |
|
| 56 |
+2.14.2 |
|
| 57 |
+ |
| 0 | 58 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,40 @@ |
| 0 |
+From 4a57b7304d1200e4e653f3e2b5f4cd61654cd191 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 20 Jun 2018 10:23:32 +0530 |
|
| 3 |
+Subject: [PATCH 21/22] staging: fsl_ppfe/eth: disable CRC removal |
|
| 4 |
+ |
|
| 5 |
+Disable CRC removal from the packet, so that packets are forwarded |
|
| 6 |
+as is to Linux. |
|
| 7 |
+CRC configuration in MAC will be reflected in the packet received |
|
| 8 |
+to Linux. |
|
| 9 |
+ |
|
| 10 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 11 |
+ |
|
| 12 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 13 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 14 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 15 |
+] |
|
| 16 |
+ |
|
| 17 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 18 |
+--- |
|
| 19 |
+ drivers/staging/fsl_ppfe/pfe_hal.c | 4 ++-- |
|
| 20 |
+ 1 file changed, 2 insertions(+), 2 deletions(-) |
|
| 21 |
+ |
|
| 22 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hal.c b/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 23 |
+index cfd02ccc313a..ec7764648c0c 100644 |
|
| 24 |
+--- a/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 25 |
+@@ -869,8 +869,8 @@ void gemac_set_mode(void *base, int mode) |
|
| 26 |
+ /*Remove loopbank*/ |
|
| 27 |
+ val &= ~EMAC_RCNTRL_LOOP; |
|
| 28 |
+ |
|
| 29 |
+- /*Enable flow control and MII mode*/ |
|
| 30 |
+- val |= (EMAC_RCNTRL_FCE | EMAC_RCNTRL_MII_MODE); |
|
| 31 |
++ /* Enable flow control and MII mode and terminate received CRC */ |
|
| 32 |
++ val |= (EMAC_RCNTRL_FCE | EMAC_RCNTRL_MII_MODE | EMAC_RCNTRL_CRC_FWD); |
|
| 33 |
+ |
|
| 34 |
+ writel(val, base + EMAC_RCNTRL_REG); |
|
| 35 |
+ } |
|
| 36 |
+-- |
|
| 37 |
+2.14.2 |
|
| 38 |
+ |
| 0 | 39 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,123 @@ |
| 0 |
+From 4cd81dcda58bf1533c646d35ceb4decefd565410 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 2 |
+Date: Wed, 20 Jun 2018 10:23:41 +0530 |
|
| 3 |
+Subject: [PATCH 22/22] staging: fsl_ppfe/eth: handle ls1012a errata_a010897 |
|
| 4 |
+ |
|
| 5 |
+On LS1012A rev 1.0, Jumbo frames are not supported as it causes |
|
| 6 |
+the PFE controller to hang. A reset of the entire chip is required |
|
| 7 |
+to resume normal operation. |
|
| 8 |
+ |
|
| 9 |
+To handle this errata, frames with length > 1900 are truncated for |
|
| 10 |
+rev 1.0 of LS1012A. |
|
| 11 |
+ |
|
| 12 |
+Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> |
|
| 13 |
+ |
|
| 14 |
+[ Srinidhi Rao : Ported this patch to photon linux from |
|
| 15 |
+ qoriq-components linux 'linux-4.14-nxp' |
|
| 16 |
+ (https://source.codeaurora.org/external/qoriq/qoriq-components/linux) |
|
| 17 |
+] |
|
| 18 |
+ |
|
| 19 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 20 |
+--- |
|
| 21 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 20 +++++++++++++++++++- |
|
| 22 |
+ drivers/staging/fsl_ppfe/pfe_eth.h | 3 ++- |
|
| 23 |
+ drivers/staging/fsl_ppfe/pfe_hal.c | 10 +++++++++- |
|
| 24 |
+ 3 files changed, 30 insertions(+), 3 deletions(-) |
|
| 25 |
+ |
|
| 26 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 27 |
+index b272e72baf5f..dba5a49e180e 100644 |
|
| 28 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 29 |
+@@ -44,6 +44,7 @@ |
|
| 30 |
+ #include <linux/delay.h> |
|
| 31 |
+ #include <linux/regmap.h> |
|
| 32 |
+ #include <linux/i2c.h> |
|
| 33 |
++#include <linux/fsl/guts.h> |
|
| 34 |
+ |
|
| 35 |
+ #if defined(CONFIG_NF_CONNTRACK_MARK) |
|
| 36 |
+ #include <net/netfilter/nf_conntrack.h> |
|
| 37 |
+@@ -52,6 +53,10 @@ |
|
| 38 |
+ #include "pfe_mod.h" |
|
| 39 |
+ #include "pfe_eth.h" |
|
| 40 |
+ |
|
| 41 |
++#define LS1012A_REV_1_0 0x87040010 |
|
| 42 |
++ |
|
| 43 |
++bool pfe_errata_a010897; |
|
| 44 |
++ |
|
| 45 |
+ static void *cbus_emac_base[3]; |
|
| 46 |
+ static void *cbus_gpi_base[3]; |
|
| 47 |
+ |
|
| 48 |
+@@ -2362,7 +2367,15 @@ static int pfe_eth_init_one(struct pfe *pfe, int id) |
|
| 49 |
+ |
|
| 50 |
+ /* Set MTU limits */ |
|
| 51 |
+ ndev->min_mtu = ETH_MIN_MTU; |
|
| 52 |
+- ndev->max_mtu = JUMBO_FRAME_SIZE; |
|
| 53 |
++ |
|
| 54 |
++/* |
|
| 55 |
++ * Jumbo frames are not supported on LS1012A rev-1.0. |
|
| 56 |
++ * So max mtu should be restricted to supported frame length. |
|
| 57 |
++ */ |
|
| 58 |
++ if (pfe_errata_a010897) |
|
| 59 |
++ ndev->max_mtu = JUMBO_FRAME_SIZE_V1 - ETH_HLEN - ETH_FCS_LEN; |
|
| 60 |
++ else |
|
| 61 |
++ ndev->max_mtu = JUMBO_FRAME_SIZE_V2 - ETH_HLEN - ETH_FCS_LEN; |
|
| 62 |
+ |
|
| 63 |
+ /* supported features */ |
|
| 64 |
+ ndev->hw_features = NETIF_F_SG; |
|
| 65 |
+@@ -2453,6 +2466,11 @@ int pfe_eth_init(struct pfe *pfe) |
|
| 66 |
+ cbus_gpi_base[0] = EGPI1_BASE_ADDR; |
|
| 67 |
+ cbus_gpi_base[1] = EGPI2_BASE_ADDR; |
|
| 68 |
+ |
|
| 69 |
++ if (fsl_guts_get_svr() == LS1012A_REV_1_0) |
|
| 70 |
++ pfe_errata_a010897 = true; |
|
| 71 |
++ else |
|
| 72 |
++ pfe_errata_a010897 = false; |
|
| 73 |
++ |
|
| 74 |
+ for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) {
|
|
| 75 |
+ err = pfe_eth_init_one(pfe, ii); |
|
| 76 |
+ if (err) |
|
| 77 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.h b/drivers/staging/fsl_ppfe/pfe_eth.h |
|
| 78 |
+index 721bef3ef53b..051e2d4cee53 100644 |
|
| 79 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.h |
|
| 80 |
+@@ -85,7 +85,8 @@ struct ls1012a_pfe_platform_data {
|
|
| 81 |
+ #define EMAC_TXQ_CNT 16 |
|
| 82 |
+ #define EMAC_TXQ_DEPTH (HIF_TX_DESC_NT) |
|
| 83 |
+ |
|
| 84 |
+-#define JUMBO_FRAME_SIZE 10258 |
|
| 85 |
++#define JUMBO_FRAME_SIZE_V1 1900 |
|
| 86 |
++#define JUMBO_FRAME_SIZE_V2 10258 |
|
| 87 |
+ /* |
|
| 88 |
+ * Client Tx queue threshold, for txQ flush condition. |
|
| 89 |
+ * It must be smaller than the queue size (in case we ever change it in the |
|
| 90 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_hal.c b/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 91 |
+index ec7764648c0c..e55a63f123df 100644 |
|
| 92 |
+--- a/drivers/staging/fsl_ppfe/pfe_hal.c |
|
| 93 |
+@@ -19,6 +19,9 @@ |
|
| 94 |
+ #include "pfe_mod.h" |
|
| 95 |
+ #include "pfe/pfe.h" |
|
| 96 |
+ |
|
| 97 |
++/* A-010897: Jumbo frame is not supported */ |
|
| 98 |
++extern bool pfe_errata_a010897; |
|
| 99 |
++ |
|
| 100 |
+ #define PFE_RCR_MAX_FL_MASK 0xC000FFFF |
|
| 101 |
+ |
|
| 102 |
+ void *cbus_base_addr; |
|
| 103 |
+@@ -1102,7 +1105,12 @@ void gemac_set_config(void *base, struct gemac_cfg *cfg) |
|
| 104 |
+ /*GEMAC config taken from VLSI */ |
|
| 105 |
+ writel(0x00000004, base + EMAC_TFWR_STR_FWD); |
|
| 106 |
+ writel(0x00000005, base + EMAC_RX_SECTION_FULL); |
|
| 107 |
+- writel(0x00003fff, base + EMAC_TRUNC_FL); |
|
| 108 |
++ |
|
| 109 |
++ if (pfe_errata_a010897) |
|
| 110 |
++ writel(0x0000076c, base + EMAC_TRUNC_FL); |
|
| 111 |
++ else |
|
| 112 |
++ writel(0x00003fff, base + EMAC_TRUNC_FL); |
|
| 113 |
++ |
|
| 114 |
+ writel(0x00000030, base + EMAC_TX_SECTION_EMPTY); |
|
| 115 |
+ writel(0x00000000, base + EMAC_MIB_CTRL_STS_REG); |
|
| 116 |
+ |
|
| 117 |
+-- |
|
| 118 |
+2.14.2 |
|
| 119 |
+ |
| 0 | 120 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,375 @@ |
| 0 |
+From f190432842ad8888d09b4ee1a107cf7e0f97b137 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: srinidhira0 <srinidhir@vmware.com> |
|
| 2 |
+Date: Fri, 11 Jan 2019 10:38:51 +0000 |
|
| 3 |
+Subject: [PATCH] staging: fsl_ppfe/eth: Modify Kconfig to enable pfe driver |
|
| 4 |
+ |
|
| 5 |
+This patch is intended to enable the compilation of |
|
| 6 |
+fsl_ppfe driver based on the kernel config file. |
|
| 7 |
+This patch aslo adds Device Tree files which has been |
|
| 8 |
+ported from qoriq-components/linux git, 'linux-4.14-nxp' |
|
| 9 |
+branch |
|
| 10 |
+ |
|
| 11 |
+Signed-off-by: srinidhira0 <srinidhir@vmware.com> |
|
| 12 |
+--- |
|
| 13 |
+ arch/arm64/boot/dts/freescale/Makefile | 1 + |
|
| 14 |
+ arch/arm64/boot/dts/freescale/fsl-ls1012a-frwy.dts | 172 +++++++++++++++++++++ |
|
| 15 |
+ arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 41 ++++- |
|
| 16 |
+ drivers/staging/Kconfig | 2 + |
|
| 17 |
+ drivers/staging/Makefile | 1 + |
|
| 18 |
+ drivers/staging/fsl_ppfe/Kconfig | 2 +- |
|
| 19 |
+ drivers/staging/fsl_ppfe/Makefile | 2 +- |
|
| 20 |
+ drivers/staging/fsl_ppfe/pfe_eth.c | 15 +- |
|
| 21 |
+ 8 files changed, 225 insertions(+), 11 deletions(-) |
|
| 22 |
+ create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1012a-frwy.dts |
|
| 23 |
+ |
|
| 24 |
+diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile |
|
| 25 |
+index 86e18adb695a..25a9fb766438 100644 |
|
| 26 |
+--- a/arch/arm64/boot/dts/freescale/Makefile |
|
| 27 |
+@@ -1,5 +1,6 @@ |
|
| 28 |
+ # SPDX-License-Identifier: GPL-2.0 |
|
| 29 |
+ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-frdm.dtb |
|
| 30 |
++dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-frwy.dtb |
|
| 31 |
+ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-qds.dtb |
|
| 32 |
+ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-rdb.dtb |
|
| 33 |
+ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb |
|
| 34 |
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frwy.dts b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frwy.dts |
|
| 35 |
+new file mode 100644 |
|
| 36 |
+index 000000000000..3418bb0a906c |
|
| 37 |
+--- /dev/null |
|
| 38 |
+@@ -0,0 +1,172 @@ |
|
| 39 |
++/* |
|
| 40 |
++ * Device Tree file for NXP LS1012A FRWY Board. |
|
| 41 |
++ * |
|
| 42 |
++ * Copyright 2018 NXP |
|
| 43 |
++ * |
|
| 44 |
++ * This file is dual-licensed: you can use it either under the terms |
|
| 45 |
++ * of the GPLv2 or the X11 license, at your option. Note that this dual |
|
| 46 |
++ * licensing only applies to this file, and not this project as a |
|
| 47 |
++ * whole. |
|
| 48 |
++ * |
|
| 49 |
++ * a) This library is free software; you can redistribute it and/or |
|
| 50 |
++ * modify it under the terms of the GNU General Public License as |
|
| 51 |
++ * published by the Free Software Foundation; either version 2 of the |
|
| 52 |
++ * License, or (at your option) any later version. |
|
| 53 |
++ * |
|
| 54 |
++ * This library is distributed in the hope that it will be useful, |
|
| 55 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 56 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 57 |
++ * GNU General Public License for more details. |
|
| 58 |
++ * |
|
| 59 |
++ * Or, alternatively, |
|
| 60 |
++ * |
|
| 61 |
++ * b) Permission is hereby granted, free of charge, to any person |
|
| 62 |
++ * obtaining a copy of this software and associated documentation |
|
| 63 |
++ * files (the "Software"), to deal in the Software without |
|
| 64 |
++ * restriction, including without limitation the rights to use, |
|
| 65 |
++ * copy, modify, merge, publish, distribute, sublicense, and/or |
|
| 66 |
++ * sell copies of the Software, and to permit persons to whom the |
|
| 67 |
++ * Software is furnished to do so, subject to the following |
|
| 68 |
++ * conditions: |
|
| 69 |
++ * |
|
| 70 |
++ * The above copyright notice and this permission notice shall be |
|
| 71 |
++ * included in all copies or substantial portions of the Software. |
|
| 72 |
++ * |
|
| 73 |
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
| 74 |
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|
| 75 |
++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
| 76 |
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|
| 77 |
++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|
| 78 |
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
| 79 |
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|
| 80 |
++ * OTHER DEALINGS IN THE SOFTWARE. |
|
| 81 |
++ */ |
|
| 82 |
++/dts-v1/; |
|
| 83 |
++ |
|
| 84 |
++#include "fsl-ls1012a.dtsi" |
|
| 85 |
++ |
|
| 86 |
++/ {
|
|
| 87 |
++ model = "LS1012A FRWY Board"; |
|
| 88 |
++ compatible = "fsl,ls1012a-frwy", "fsl,ls1012a"; |
|
| 89 |
++ |
|
| 90 |
++ aliases {
|
|
| 91 |
++ ethernet0 = &pfe_mac0; |
|
| 92 |
++ ethernet1 = &pfe_mac1; |
|
| 93 |
++ }; |
|
| 94 |
++ |
|
| 95 |
++ sys_mclk: clock-mclk {
|
|
| 96 |
++ compatible = "fixed-clock"; |
|
| 97 |
++ #clock-cells = <0>; |
|
| 98 |
++ clock-frequency = <25000000>; |
|
| 99 |
++ }; |
|
| 100 |
++ |
|
| 101 |
++ reg_1p8v: regulator-1p8v {
|
|
| 102 |
++ compatible = "regulator-fixed"; |
|
| 103 |
++ regulator-name = "1P8V"; |
|
| 104 |
++ regulator-min-microvolt = <1800000>; |
|
| 105 |
++ regulator-max-microvolt = <1800000>; |
|
| 106 |
++ regulator-always-on; |
|
| 107 |
++ }; |
|
| 108 |
++ |
|
| 109 |
++ sound {
|
|
| 110 |
++ compatible = "simple-audio-card"; |
|
| 111 |
++ simple-audio-card,format = "i2s"; |
|
| 112 |
++ simple-audio-card,widgets = |
|
| 113 |
++ "Microphone", "Microphone Jack", |
|
| 114 |
++ "Headphone", "Headphone Jack", |
|
| 115 |
++ "Speaker", "Speaker Ext", |
|
| 116 |
++ "Line", "Line In Jack"; |
|
| 117 |
++ simple-audio-card,routing = |
|
| 118 |
++ "MIC_IN", "Microphone Jack", |
|
| 119 |
++ "Microphone Jack", "Mic Bias", |
|
| 120 |
++ "LINE_IN", "Line In Jack", |
|
| 121 |
++ "Headphone Jack", "HP_OUT", |
|
| 122 |
++ "Speaker Ext", "LINE_OUT"; |
|
| 123 |
++ |
|
| 124 |
++ simple-audio-card,cpu {
|
|
| 125 |
++ sound-dai = <&sai2>; |
|
| 126 |
++ frame-master; |
|
| 127 |
++ bitclock-master; |
|
| 128 |
++ }; |
|
| 129 |
++ |
|
| 130 |
++ simple-audio-card,codec {
|
|
| 131 |
++ sound-dai = <&codec>; |
|
| 132 |
++ frame-master; |
|
| 133 |
++ bitclock-master; |
|
| 134 |
++ system-clock-frequency = <25000000>; |
|
| 135 |
++ }; |
|
| 136 |
++ }; |
|
| 137 |
++}; |
|
| 138 |
++ |
|
| 139 |
++&pcie {
|
|
| 140 |
++ status = "okay"; |
|
| 141 |
++}; |
|
| 142 |
++ |
|
| 143 |
++&duart0 {
|
|
| 144 |
++ status = "okay"; |
|
| 145 |
++}; |
|
| 146 |
++ |
|
| 147 |
++&i2c0 {
|
|
| 148 |
++ status = "okay"; |
|
| 149 |
++ |
|
| 150 |
++ codec: sgtl5000@a {
|
|
| 151 |
++ compatible = "fsl,sgtl5000"; |
|
| 152 |
++ #sound-dai-cells = <0>; |
|
| 153 |
++ reg = <0xa>; |
|
| 154 |
++ VDDA-supply = <®_1p8v>; |
|
| 155 |
++ VDDIO-supply = <®_1p8v>; |
|
| 156 |
++ clocks = <&sys_mclk>; |
|
| 157 |
++ clock-names = "pfe"; |
|
| 158 |
++ }; |
|
| 159 |
++}; |
|
| 160 |
++ |
|
| 161 |
++&pfe {
|
|
| 162 |
++ status = "okay"; |
|
| 163 |
++ #address-cells = <1>; |
|
| 164 |
++ #size-cells = <0>; |
|
| 165 |
++ |
|
| 166 |
++ ethernet@0 {
|
|
| 167 |
++ compatible = "fsl,pfe-gemac-port"; |
|
| 168 |
++ #address-cells = <1>; |
|
| 169 |
++ #size-cells = <0>; |
|
| 170 |
++ reg = <0x0>; /* GEM_ID */ |
|
| 171 |
++ fsl,gemac-bus-id = <0x0>; /* BUS_ID */ |
|
| 172 |
++ fsl,gemac-phy-id = <0x2>; /* PHY_ID */ |
|
| 173 |
++ fsl,mdio-mux-val = <0x0>; |
|
| 174 |
++ phy-mode = "sgmii"; |
|
| 175 |
++ fsl,pfe-phy-if-flags = <0x0>; |
|
| 176 |
++ local-mac-address = [ 00 1A 2B 3C 4D 5E ]; |
|
| 177 |
++ fsl,pfe-gemac-if-name = "eth0"; |
|
| 178 |
++ fsl,pfe-gemac-mode = <0x1B00>; /* GEMAC_SW_CONF | GEMAC_SW_FULL_DUPLEX | |
|
| 179 |
++GEMAC_SW_SPEED_1G */ |
|
| 180 |
++ mdio@0 {
|
|
| 181 |
++ reg = <0x1>; /* enabled/disabled */ |
|
| 182 |
++ fsl,mdio-phy-mask = <0xFFFFFFF9>; |
|
| 183 |
++ }; |
|
| 184 |
++ }; |
|
| 185 |
++ |
|
| 186 |
++ ethernet@1 {
|
|
| 187 |
++ compatible = "fsl,pfe-gemac-port"; |
|
| 188 |
++ #address-cells = <1>; |
|
| 189 |
++ #size-cells = <0>; |
|
| 190 |
++ reg = <0x1>; /* GEM_ID */ |
|
| 191 |
++ fsl,gemac-bus-id = <0x1>; /* BUS_ID */ |
|
| 192 |
++ fsl,gemac-phy-id = <0x1>; /* PHY_ID */ |
|
| 193 |
++ fsl,mdio-mux-val = <0x0>; |
|
| 194 |
++ local-mac-address = [ 00 AA BB CC DD EE ]; |
|
| 195 |
++ phy-mode = "rgmii"; |
|
| 196 |
++ fsl,pfe-gemac-if-name = "eth2"; |
|
| 197 |
++ fsl,pfe-phy-if-flags = <0x0>; |
|
| 198 |
++ fsl,pfe-gemac-mode = <0x1B00>; /* GEMAC_SW_CONF | GEMAC_SW_FULL_DUPLEX | |
|
| 199 |
++GEMAC_SW_SPEED_1G */ |
|
| 200 |
++ |
|
| 201 |
++ mdio@0 {
|
|
| 202 |
++ reg = <0x0>; /* enabled/disabled */ |
|
| 203 |
++ fsl,mdio-phy-mask = <0xFFFFFFF9>; |
|
| 204 |
++ }; |
|
| 205 |
++ }; |
|
| 206 |
++}; |
|
| 207 |
++ |
|
| 208 |
++&sai2 {
|
|
| 209 |
++ status = "okay"; |
|
| 210 |
++}; |
|
| 211 |
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi |
|
| 212 |
+index 68ac78c4564d..343e3d88b73e 100644 |
|
| 213 |
+--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi |
|
| 214 |
+@@ -474,7 +474,7 @@ |
|
| 215 |
+ interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>; |
|
| 216 |
+ }; |
|
| 217 |
+ |
|
| 218 |
+- pcie@3400000 {
|
|
| 219 |
++ pcie: pcie@3400000 {
|
|
| 220 |
+ compatible = "fsl,ls1012a-pcie", "snps,dw-pcie"; |
|
| 221 |
+ reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */ |
|
| 222 |
+ 0x40 0x00000000 0x0 0x00002000>; /* configuration space */ |
|
| 223 |
+@@ -497,6 +497,45 @@ |
|
| 224 |
+ <0000 0 0 3 &gic 0 112 IRQ_TYPE_LEVEL_HIGH>, |
|
| 225 |
+ <0000 0 0 4 &gic 0 113 IRQ_TYPE_LEVEL_HIGH>; |
|
| 226 |
+ }; |
|
| 227 |
++ rcpm: rcpm@1ee2000 {
|
|
| 228 |
++ compatible = "fsl,ls1012a-rcpm", "fsl,qoriq-rcpm-2.1"; |
|
| 229 |
++ reg = <0x0 0x1ee2000 0x0 0x1000>; |
|
| 230 |
++ fsl,#rcpm-wakeup-cells = <1>; |
|
| 231 |
++ }; |
|
| 232 |
++ }; |
|
| 233 |
++ |
|
| 234 |
++ reserved-memory {
|
|
| 235 |
++ #address-cells = <2>; |
|
| 236 |
++ #size-cells = <2>; |
|
| 237 |
++ ranges; |
|
| 238 |
++ |
|
| 239 |
++ pfe_reserved: packetbuffer@83400000 {
|
|
| 240 |
++ reg = <0 0x83400000 0 0xc00000>; |
|
| 241 |
++ }; |
|
| 242 |
++ }; |
|
| 243 |
++ |
|
| 244 |
++ pfe: pfe@04000000 {
|
|
| 245 |
++ compatible = "fsl,pfe"; |
|
| 246 |
++ reg = <0x0 0x04000000 0x0 0xc00000>, /* AXI 16M */ |
|
| 247 |
++ <0x0 0x83400000 0x0 0xc00000>; /* PFE DDR 12M */ |
|
| 248 |
++ reg-names = "pfe", "pfe-ddr"; |
|
| 249 |
++ fsl,pfe-num-interfaces = <0x2>; |
|
| 250 |
++ interrupts = <0 172 0x4>, /* HIF interrupt */ |
|
| 251 |
++ <0 173 0x4>, /*HIF_NOCPY interrupt */ |
|
| 252 |
++ <0 174 0x4>; /* WoL interrupt */ |
|
| 253 |
++ interrupt-names = "pfe_hif", "pfe_hif_nocpy", "pfe_wol"; |
|
| 254 |
++ memory-region = <&pfe_reserved>; |
|
| 255 |
++ fsl,pfe-scfg = <&scfg 0>; |
|
| 256 |
++ fsl,rcpm-wakeup = <&rcpm 0xf0000020>; |
|
| 257 |
++ clocks = <&clockgen 4 0>; |
|
| 258 |
++ clock-names = "pfe"; |
|
| 259 |
++ |
|
| 260 |
++ status = "okay"; |
|
| 261 |
++ pfe_mac0: ethernet@0 {
|
|
| 262 |
++ }; |
|
| 263 |
++ |
|
| 264 |
++ pfe_mac1: ethernet@1 {
|
|
| 265 |
++ }; |
|
| 266 |
+ }; |
|
| 267 |
+ |
|
| 268 |
+ firmware {
|
|
| 269 |
+diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig |
|
| 270 |
+index 1abf76be2aa8..2744ecad2294 100644 |
|
| 271 |
+--- a/drivers/staging/Kconfig |
|
| 272 |
+@@ -126,4 +126,6 @@ source "drivers/staging/axis-fifo/Kconfig" |
|
| 273 |
+ |
|
| 274 |
+ source "drivers/staging/erofs/Kconfig" |
|
| 275 |
+ |
|
| 276 |
++source "drivers/staging/fsl_ppfe/Kconfig" |
|
| 277 |
++ |
|
| 278 |
+ endif # STAGING |
|
| 279 |
+diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile |
|
| 280 |
+index ab0cbe8815b1..13bf0fa8a262 100644 |
|
| 281 |
+--- a/drivers/staging/Makefile |
|
| 282 |
+@@ -53,3 +53,4 @@ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ |
|
| 283 |
+ obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/ |
|
| 284 |
+ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ |
|
| 285 |
+ obj-$(CONFIG_EROFS_FS) += erofs/ |
|
| 286 |
++obj-$(CONFIG_FSL_PPFE) += fsl_ppfe/ |
|
| 287 |
+diff --git a/drivers/staging/fsl_ppfe/Kconfig b/drivers/staging/fsl_ppfe/Kconfig |
|
| 288 |
+index e40964354cad..c38c669ed59f 100644 |
|
| 289 |
+--- a/drivers/staging/fsl_ppfe/Kconfig |
|
| 290 |
+@@ -2,7 +2,7 @@ |
|
| 291 |
+ # Freescale Programmable Packet Forwarding Engine driver |
|
| 292 |
+ # |
|
| 293 |
+ config FSL_PPFE |
|
| 294 |
+- bool "Freescale PPFE Driver" |
|
| 295 |
++ tristate "Freescale PPFE Driver" |
|
| 296 |
+ default n |
|
| 297 |
+ ---help--- |
|
| 298 |
+ Freescale LS1012A SoC has a Programmable Packet Forwarding Engine. |
|
| 299 |
+diff --git a/drivers/staging/fsl_ppfe/Makefile b/drivers/staging/fsl_ppfe/Makefile |
|
| 300 |
+index 07cd351b9221..513efefd8ded 100644 |
|
| 301 |
+--- a/drivers/staging/fsl_ppfe/Makefile |
|
| 302 |
+@@ -4,7 +4,7 @@ |
|
| 303 |
+ |
|
| 304 |
+ ccflags-y += -I$(src)/include -I$(src) |
|
| 305 |
+ |
|
| 306 |
+-obj-m += pfe.o |
|
| 307 |
++obj-$(CONFIG_FSL_PPFE) += pfe.o |
|
| 308 |
+ |
|
| 309 |
+ pfe-y += pfe_mod.o \ |
|
| 310 |
+ pfe_hw.o \ |
|
| 311 |
+diff --git a/drivers/staging/fsl_ppfe/pfe_eth.c b/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 312 |
+index dba5a49e180e..767c069c517a 100644 |
|
| 313 |
+--- a/drivers/staging/fsl_ppfe/pfe_eth.c |
|
| 314 |
+@@ -974,7 +974,10 @@ static int pfe_eth_mdio_init(struct pfe_eth_priv_s *priv, |
|
| 315 |
+ * via phy_device_register() |
|
| 316 |
+ */ |
|
| 317 |
+ |
|
| 318 |
+- if (priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) {
|
|
| 319 |
++ /* Since 4.19 Kernel does not support 2.5GBPS SGMII yet, |
|
| 320 |
++ Disabling the cluse 45 phy register |
|
| 321 |
++ */ |
|
| 322 |
++ /*if (priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) {
|
|
| 323 |
+ for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) {
|
|
| 324 |
+ phydev = get_phy_device(priv->mii_bus, |
|
| 325 |
+ priv->einfo->phy_id + ii, true); |
|
| 326 |
+@@ -991,7 +994,7 @@ static int pfe_eth_mdio_init(struct pfe_eth_priv_s *priv, |
|
| 327 |
+ goto err1; |
|
| 328 |
+ } |
|
| 329 |
+ } |
|
| 330 |
+- } |
|
| 331 |
++ } */ |
|
| 332 |
+ |
|
| 333 |
+ pfe_eth_mdio_reset(bus); |
|
| 334 |
+ |
|
| 335 |
+@@ -1181,9 +1184,6 @@ static void ls1012a_configure_serdes(struct net_device *ndev) |
|
| 336 |
+ struct mii_bus *bus = priv->mii_bus; |
|
| 337 |
+ u16 value = 0; |
|
| 338 |
+ |
|
| 339 |
+- if (priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) |
|
| 340 |
+- sgmii_2500 = 1; |
|
| 341 |
+- |
|
| 342 |
+ netif_info(priv, drv, ndev, "%s\n", __func__); |
|
| 343 |
+ /* PCS configuration done with corresponding GEMAC */ |
|
| 344 |
+ |
|
| 345 |
+@@ -1231,8 +1231,7 @@ static int pfe_phy_init(struct net_device *ndev) |
|
| 346 |
+ |
|
| 347 |
+ netif_info(priv, drv, ndev, "%s: %s\n", __func__, phy_id); |
|
| 348 |
+ interface = priv->einfo->mii_config; |
|
| 349 |
+- if ((interface == PHY_INTERFACE_MODE_SGMII) || |
|
| 350 |
+- (interface == PHY_INTERFACE_MODE_2500SGMII)) {
|
|
| 351 |
++ if ( interface == PHY_INTERFACE_MODE_SGMII ) {
|
|
| 352 |
+ /*Configure SGMII PCS */ |
|
| 353 |
+ if (pfe->scfg) {
|
|
| 354 |
+ /*Config MDIO from serdes */ |
|
| 355 |
+@@ -1823,7 +1822,7 @@ static int pfe_eth_send_packet(struct sk_buff *skb, struct net_device *ndev) |
|
| 356 |
+ * |
|
| 357 |
+ */ |
|
| 358 |
+ static u16 pfe_eth_select_queue(struct net_device *ndev, struct sk_buff *skb, |
|
| 359 |
+- void *accel_priv, |
|
| 360 |
++ struct net_device *sb_dev, |
|
| 361 |
+ select_queue_fallback_t fallback) |
|
| 362 |
+ {
|
|
| 363 |
+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); |
|
| 364 |
+-- |
|
| 365 |
+2.14.2 |
|
| 366 |
+ |
| ... | ... |
@@ -15,19 +15,17 @@ |
| 15 | 15 |
|
| 16 | 16 |
grub_efi_install() |
| 17 | 17 |
{
|
| 18 |
- BOOT_PARTITION=/dev/mapper/`basename ${HDD}`p2
|
|
| 19 |
- mkdir -p $BUILDROOT/boot_temp/ |
|
| 20 |
- mount -t ext4 $BOOT_PARTITION $BUILDROOT/boot_temp/ |
|
| 21 |
- cp -rfa $BUILDROOT/boot/* $BUILDROOT/boot_temp/ |
|
| 22 |
- cp -r $SCRIPT_PATH/esp/ls1012afrwy_boot.scr $BUILDROOT/boot_temp/ |
|
| 23 |
- cp -rfa $BUILDROOT/boot_temp/vmlinuz-* $BUILDROOT/boot_temp/Image |
|
| 24 |
- gzip -k $BUILDROOT/boot_temp/Image |
|
| 25 |
- cp -rfa $BUILDROOT/boot_temp/dtb/fsl-ls1012a-frdm.dtb $BUILDROOT/boot_temp/fsl-ls1012a-frwy.dtb |
|
| 26 |
- sync |
|
| 27 |
- umount $BUILDROOT/boot_temp/ |
|
| 28 |
- rm -rf $BUILDROOT/boot_temp/ |
|
| 18 |
+ cp -r $SCRIPT_PATH/esp/ls1012afrwy_boot.scr $BUILDROOT/ |
|
| 19 |
+ mkdir -p $BUILDROOT/boot/esp/EFI/BOOT/ |
|
| 20 |
+ cp $SCRIPT_PATH/esp/bootaa64.efi $BUILDROOT/boot/esp/EFI/BOOT/ |
|
| 21 |
+ mkdir -p $BUILDROOT/boot/esp/boot/grub2 |
|
| 22 |
+ cat > $BUILDROOT/boot/esp/boot/grub2/grub.cfg << EOF |
|
| 23 |
+search -n -u ${BOOT_UUID} -s
|
|
| 24 |
+configfile ${BOOT_DIRECTORY}grub2/grub.cfg
|
|
| 25 |
+EOF |
|
| 29 | 26 |
} |
| 30 | 27 |
|
| 28 |
+ |
|
| 31 | 29 |
set -o errexit # exit if error...insurance ;) |
| 32 | 30 |
set -o nounset # exit if variable not initalized |
| 33 | 31 |
set +h # disable hashall |
| ... | ... |
@@ -55,19 +53,23 @@ fi |
| 55 | 55 |
# |
| 56 | 56 |
# Install grub2. |
| 57 | 57 |
# |
| 58 |
-BOOT_UUID=$(blkid -s UUID -o value $BOOT_PARTITION_PATH) |
|
| 58 |
+BOOT_UUID=$(blkid -s UUID -o value $ROOT_PARTITION_PATH) |
|
| 59 | 59 |
|
| 60 | 60 |
echo "$ROOT_PARTITION_PATH" |
| 61 | 61 |
echo "$BUILDROOT" |
| 62 | 62 |
|
| 63 |
+mkdir -p $BUILDROOT/boot/grub2/ |
|
| 64 |
+ln -sfv grub2 $BUILDROOT/boot/grub |
|
| 65 |
+ |
|
| 66 |
+ |
|
| 67 |
+grub_efi_install |
|
| 68 |
+ |
|
| 63 | 69 |
RFS_PARTITION=/dev/mapper/`basename ${HDD}`p2
|
| 64 | 70 |
#umount -f $BUILDROOT |
| 65 | 71 |
#mount -t ext4 $ROOT_PATITION_PATH $BUILDROOT |
| 66 | 72 |
|
| 67 |
-EXTRA_PARAMS="rootwait rw console=ttyS0,115200n8 console=tty0 cma=256M rootfs=/dev/mmcblk0p3" |
|
| 68 |
- |
|
| 73 |
+EXTRA_PARAMS="rootwait rw console=ttyS0,115200n8 console=tty0 cma=256M rootfs=/dev/mmcblk0p2" |
|
| 69 | 74 |
|
| 70 |
-mkdir -p $BUILDROOT/boot/grub2/ |
|
| 71 | 75 |
|
| 72 | 76 |
cat > $BUILDROOT/boot/grub2/grub.cfg << EOF |
| 73 | 77 |
# Begin /boot/grub2/grub.cfg |
| ... | ... |
@@ -101,7 +103,12 @@ EOF |
| 101 | 101 |
|
| 102 | 102 |
|
| 103 | 103 |
|
| 104 |
-mkdir $BUILDROOT/boot/grub |
|
| 105 |
-cp -rfa $BUILDROOT/boot/grub2/* $BUILDROOT/boot/grub/ |
|
| 104 |
+#mkdir $BUILDROOT/boot/grub |
|
| 105 |
+#cp -rfa $BUILDROOT/boot/grub2/* $BUILDROOT/boot/grub/ |
|
| 106 |
+ |
|
| 107 |
+#grub_efi_install |
|
| 108 |
+ |
|
| 109 |
+#Cleanup the workspace directory |
|
| 110 |
+rm -rf "$BUILDROOT"/tools |
|
| 111 |
+rm -rf "$BUILDROOT"/RPMS |
|
| 106 | 112 |
|
| 107 |
-grub_efi_install |