Merge branch 'net-ethernet-ti-add-networking-support-for-k3-am65x-j721e-soc'
Grygorii Strashko says: ==================== net: ethernet: ti: add networking support for k3 am65x/j721e soc This v6 series adds basic networking support support TI K3 AM654x/J721E SoC which have integrated Gigabit Ethernet MAC (Media Access Controller) into device MCU domain and named MCU_CPSW0 (CPSW2G NUSS). Formally TRMs refer CPSW2G NUSS as two-port Gigabit Ethernet Switch subsystem with port 0 being the CPPI DMA host port and port 1 being the external Ethernet port, but for 1 external port device it's just Port 0 <-> ALE <-> Port 1 and it's rather device with HW filtering capabilities then actually switching device. It's expected to have similar devices, but with more external ports. The new Host port 0 Communications Port Programming Interface (CPPI5) is operating by TI AM654x/J721E NAVSS Unified DMA Peripheral Root Complex (UDMA-P) controller [1]. The CPSW2G contains below modules for which existing code is re-used: - MAC SL: cpsw_sl.c - Address Lookup Engine (ALE): cpsw_ale.c, basically compatible with K2 66AK2E/G - Management Data Input/Output interface (MDIO): davinci_mdio.c, fully compatible with TI AM3/4/5 devices Basic features supported by CPSW2G NUSS driver: - VLAN support, 802.1Q compliant, Auto add port VLAN for untagged frames on ingress, Auto VLAN removal on egress and auto pad to minimum frame size. - multicast filtering - promisc mode - TX multiq support in Round Robin or Fixed priority modes - RX checksum offload for non-fragmented IPv4/IPv6 TCP/UDP packets - TX checksum offload support for IPv4/IPv6 TCP/UDP packets (J721E only). Features under development: - Support for IEEE 1588 Clock Synchronization. The CPSW2G NUSS includes new version of Common Platform Time Sync (CPTS) - tc-mqprio: priority level Quality Of Service (QOS) support (802.1p) - tc-cbs: Support for Audio/Video Bridging (P802.1Qav/D6.0) HW shapers - tc-taprio: IEEE 802.1Qbv/D2.2 Enhancements for Scheduled Traffic - frame preemption: IEEE P902.3br/D2.0 Interspersing Express Traffic, 802.1Qbu - extended ALE features: classifier/policers, auto-aging Patches 1-6 are intended for netdev, Patches 7-11 are intended for K3 Platform tree and provided here for testing purposes. Changes in v6: - fixed comments from Rob Herring <robh@kernel.org> and added his Reviewed-by. - added Tested-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Changes in v5: - renamed files k3-udma-desc-pool.* k3-udma-desc-pool to k3-cppi-desc-pool.*, and API to k3_cppi_desc_pool_* as requested by Peter Ujfalusi <peter.ujfalusi@ti.com> - fixed copy-paste err in am65_cpsw_nuss_ndo_slave_set_rx_mode() which blocked recieving of mcast frames. - added Tested-by: Murali Karicheri <m-karicheri2@ti.com> Changes in v4: - fixed minor comments from Jakub Kicinski <kuba@kernel.org> - dependencies resolved: required phy-rmii-sel changes [2] queued for merge except one [3] which is included in this series with Kishon's ask. Changes in v3: - add ARM64 defconfig changes for testing purposes - fixed DT yaml definition - fixed comments from Jakub Kicinski <kuba@kernel.org> Changes in v2: - fixed DT yaml definition - fixed comments from David Miller v5: https://patchwork.ozlabs.org/cover/1258295/ v4: https://patchwork.ozlabs.org/cover/1256092/ v3: https://patchwork.ozlabs.org/cover/1254568/ v2: https://patchwork.ozlabs.org/cover/1250674/ v1: https://lwn.net/Articles/813087/ TRMs: AM654: http://www.ti.com/lit/ug/spruid7e/spruid7e.pdf J721E: http://www.ti.com/lit/ug/spruil1a/spruil1a.pdf Preliminary documentation can be found at: http://software-dl.ti.com/processor-sdk-linux/esd/docs/latest/linux/Foundational_Components/Kernel/Kernel_Drivers/Network/K3_CPSW2g.html [1] https://lwn.net/Articles/808030/ [2] https://lkml.org/lkml/2020/2/22/100 [3] https://lkml.org/lkml/2020/3/3/724 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a47ab26b9e
225
Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
Normal file
225
Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
Normal file
@ -0,0 +1,225 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/ti,k3-am654-cpsw-nuss.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: The TI AM654x/J721E SoC Gigabit Ethernet MAC (Media Access Controller) Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Grygorii Strashko <grygorii.strashko@ti.com>
|
||||
- Sekhar Nori <nsekhar@ti.com>
|
||||
|
||||
description:
|
||||
The TI AM654x/J721E SoC Gigabit Ethernet MAC (CPSW2G NUSS) has two ports
|
||||
(one external) and provides Ethernet packet communication for the device.
|
||||
CPSW2G NUSS features - the Reduced Gigabit Media Independent Interface (RGMII),
|
||||
Reduced Media Independent Interface (RMII), the Management Data
|
||||
Input/Output (MDIO) interface for physical layer device (PHY) management,
|
||||
new version of Common Platform Time Sync (CPTS), updated Address Lookup
|
||||
Engine (ALE).
|
||||
One external Ethernet port (port 1) with selectable RGMII/RMII interfaces and
|
||||
an internal Communications Port Programming Interface (CPPI5) (Host port 0).
|
||||
Host Port 0 CPPI Packet Streaming Interface interface supports 8 TX channels
|
||||
and one RX channels and operating by TI AM654x/J721E NAVSS Unified DMA
|
||||
Peripheral Root Complex (UDMA-P) controller.
|
||||
The CPSW2G NUSS is integrated into device MCU domain named MCU_CPSW0.
|
||||
|
||||
Additional features
|
||||
priority level Quality Of Service (QOS) support (802.1p)
|
||||
Support for Audio/Video Bridging (P802.1Qav/D6.0)
|
||||
Support for IEEE 1588 Clock Synchronization (2008 Annex D, Annex E and Annex F)
|
||||
Flow Control (802.3x) Support
|
||||
Time Sensitive Network Support
|
||||
IEEE P902.3br/D2.0 Interspersing Express Traffic
|
||||
IEEE 802.1Qbv/D2.2 Enhancements for Scheduled Traffic
|
||||
Configurable number of addresses plus VLANs
|
||||
Configurable number of classifier/policers
|
||||
VLAN support, 802.1Q compliant, Auto add port VLAN for untagged frames on
|
||||
ingress, Auto VLAN removal on egress and auto pad to minimum frame size.
|
||||
RX/TX csum offload
|
||||
|
||||
Specifications can be found at
|
||||
http://www.ti.com/lit/ug/spruid7e/spruid7e.pdf
|
||||
http://www.ti.com/lit/ug/spruil1a/spruil1a.pdf
|
||||
|
||||
properties:
|
||||
"#address-cells": true
|
||||
"#size-cells": true
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: ti,am654-cpsw-nuss
|
||||
- const: ti,j721e-cpsw-nuss
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description:
|
||||
The physical base address and size of full the CPSW2G NUSS IO range
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: cpsw_nuss
|
||||
|
||||
ranges: true
|
||||
|
||||
dma-coherent: true
|
||||
|
||||
clocks:
|
||||
description: CPSW2G NUSS functional clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: fck
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
maxItems: 9
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: tx0
|
||||
- const: tx1
|
||||
- const: tx2
|
||||
- const: tx3
|
||||
- const: tx4
|
||||
- const: tx5
|
||||
- const: tx6
|
||||
- const: tx7
|
||||
- const: rx
|
||||
|
||||
ethernet-ports:
|
||||
type: object
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
port@1:
|
||||
type: object
|
||||
description: CPSW2G NUSS external ports
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- const: 1
|
||||
description: CPSW port number
|
||||
|
||||
phys:
|
||||
maxItems: 1
|
||||
description: phandle on phy-gmii-sel PHY
|
||||
|
||||
label:
|
||||
description: label associated with this port
|
||||
|
||||
ti,mac-only:
|
||||
$ref: /schemas/types.yaml#definitions/flag
|
||||
description:
|
||||
Specifies the port works in mac-only mode.
|
||||
|
||||
ti,syscon-efuse:
|
||||
$ref: /schemas/types.yaml#definitions/phandle-array
|
||||
description:
|
||||
Phandle to the system control device node which provides access
|
||||
to efuse IO range with MAC addresses
|
||||
|
||||
required:
|
||||
- reg
|
||||
- phys
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^mdio@[0-9a-f]+$":
|
||||
type: object
|
||||
allOf:
|
||||
- $ref: "ti,davinci-mdio.yaml#"
|
||||
description:
|
||||
CPSW MDIO bus.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- ranges
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- dmas
|
||||
- dma-names
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/pinctrl/k3.h>
|
||||
#include <dt-bindings/soc/ti,sci_pm_domain.h>
|
||||
#include <dt-bindings/net/ti-dp83867.h>
|
||||
|
||||
mcu_cpsw: ethernet@46000000 {
|
||||
compatible = "ti,am654-cpsw-nuss";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
reg = <0x0 0x46000000 0x0 0x200000>;
|
||||
reg-names = "cpsw_nuss";
|
||||
ranges = <0x0 0x0 0x46000000 0x0 0x200000>;
|
||||
dma-coherent;
|
||||
clocks = <&k3_clks 5 10>;
|
||||
clock-names = "fck";
|
||||
power-domains = <&k3_pds 5 TI_SCI_PD_EXCLUSIVE>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
|
||||
|
||||
dmas = <&mcu_udmap 0xf000>,
|
||||
<&mcu_udmap 0xf001>,
|
||||
<&mcu_udmap 0xf002>,
|
||||
<&mcu_udmap 0xf003>,
|
||||
<&mcu_udmap 0xf004>,
|
||||
<&mcu_udmap 0xf005>,
|
||||
<&mcu_udmap 0xf006>,
|
||||
<&mcu_udmap 0xf007>,
|
||||
<&mcu_udmap 0x7000>;
|
||||
dma-names = "tx0", "tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
|
||||
"rx";
|
||||
|
||||
ethernet-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpsw_port1: port@1 {
|
||||
reg = <1>;
|
||||
ti,mac-only;
|
||||
label = "port1";
|
||||
ti,syscon-efuse = <&mcu_conf 0x200>;
|
||||
phys = <&phy_gmii_sel 1>;
|
||||
|
||||
phy-mode = "rgmii-rxid";
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
};
|
||||
|
||||
davinci_mdio: mdio@f00 {
|
||||
compatible = "ti,cpsw-mdio","ti,davinci_mdio";
|
||||
reg = <0x0 0xf00 0x0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&k3_clks 5 10>;
|
||||
clock-names = "fck";
|
||||
bus_freq = <1000000>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
|
||||
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
|
||||
};
|
||||
};
|
||||
};
|
@ -187,4 +187,53 @@
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
mcu_cpsw: ethernet@46000000 {
|
||||
compatible = "ti,am654-cpsw-nuss";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
reg = <0x0 0x46000000 0x0 0x200000>;
|
||||
reg-names = "cpsw_nuss";
|
||||
ranges = <0x0 0x0 0x0 0x46000000 0x0 0x200000>;
|
||||
dma-coherent;
|
||||
clocks = <&k3_clks 5 10>;
|
||||
clock-names = "fck";
|
||||
power-domains = <&k3_pds 5 TI_SCI_PD_EXCLUSIVE>;
|
||||
|
||||
dmas = <&mcu_udmap 0xf000>,
|
||||
<&mcu_udmap 0xf001>,
|
||||
<&mcu_udmap 0xf002>,
|
||||
<&mcu_udmap 0xf003>,
|
||||
<&mcu_udmap 0xf004>,
|
||||
<&mcu_udmap 0xf005>,
|
||||
<&mcu_udmap 0xf006>,
|
||||
<&mcu_udmap 0xf007>,
|
||||
<&mcu_udmap 0x7000>;
|
||||
dma-names = "tx0", "tx1", "tx2", "tx3",
|
||||
"tx4", "tx5", "tx6", "tx7",
|
||||
"rx";
|
||||
|
||||
ethernet-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpsw_port1: port@1 {
|
||||
reg = <1>;
|
||||
ti,mac-only;
|
||||
label = "port1";
|
||||
ti,syscon-efuse = <&mcu_conf 0x200>;
|
||||
phys = <&phy_gmii_sel 1>;
|
||||
};
|
||||
};
|
||||
|
||||
davinci_mdio: mdio@f00 {
|
||||
compatible = "ti,cpsw-mdio","ti,davinci_mdio";
|
||||
reg = <0x0 0xf00 0x0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&k3_clks 5 10>;
|
||||
clock-names = "fck";
|
||||
bus_freq = <1000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -30,6 +30,7 @@
|
||||
i2c3 = &main_i2c1;
|
||||
i2c4 = &main_i2c2;
|
||||
i2c5 = &main_i2c3;
|
||||
ethernet0 = &cpsw_port1;
|
||||
};
|
||||
|
||||
chosen { };
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "k3-am654.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/net/ti-dp83867.h>
|
||||
|
||||
/ {
|
||||
compatible = "ti,am654-evm", "ti,am654";
|
||||
@ -95,7 +96,30 @@
|
||||
wkup_pca554_default: wkup_pca554_default {
|
||||
pinctrl-single,pins = <
|
||||
AM65X_WKUP_IOPAD(0x0034, PIN_INPUT, 7) /* (T1) MCU_OSPI1_CLK.WKUP_GPIO0_25 */
|
||||
>;
|
||||
};
|
||||
|
||||
mcu_cpsw_pins_default: mcu_cpsw_pins_default {
|
||||
pinctrl-single,pins = <
|
||||
AM65X_WKUP_IOPAD(0x0058, PIN_OUTPUT, 0) /* (N4) MCU_RGMII1_TX_CTL */
|
||||
AM65X_WKUP_IOPAD(0x005c, PIN_INPUT, 0) /* (N5) MCU_RGMII1_RX_CTL */
|
||||
AM65X_WKUP_IOPAD(0x0060, PIN_OUTPUT, 0) /* (M2) MCU_RGMII1_TD3 */
|
||||
AM65X_WKUP_IOPAD(0x0064, PIN_OUTPUT, 0) /* (M3) MCU_RGMII1_TD2 */
|
||||
AM65X_WKUP_IOPAD(0x0068, PIN_OUTPUT, 0) /* (M4) MCU_RGMII1_TD1 */
|
||||
AM65X_WKUP_IOPAD(0x006c, PIN_OUTPUT, 0) /* (M5) MCU_RGMII1_TD0 */
|
||||
AM65X_WKUP_IOPAD(0x0078, PIN_INPUT, 0) /* (L2) MCU_RGMII1_RD3 */
|
||||
AM65X_WKUP_IOPAD(0x007c, PIN_INPUT, 0) /* (L5) MCU_RGMII1_RD2 */
|
||||
AM65X_WKUP_IOPAD(0x0080, PIN_INPUT, 0) /* (M6) MCU_RGMII1_RD1 */
|
||||
AM65X_WKUP_IOPAD(0x0084, PIN_INPUT, 0) /* (L6) MCU_RGMII1_RD0 */
|
||||
AM65X_WKUP_IOPAD(0x0070, PIN_INPUT, 0) /* (N1) MCU_RGMII1_TXC */
|
||||
AM65X_WKUP_IOPAD(0x0074, PIN_INPUT, 0) /* (M1) MCU_RGMII1_RXC */
|
||||
>;
|
||||
};
|
||||
|
||||
mcu_mdio_pins_default: mcu_mdio1_pins_default {
|
||||
pinctrl-single,pins = <
|
||||
AM65X_WKUP_IOPAD(0x008c, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */
|
||||
AM65X_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */
|
||||
>;
|
||||
};
|
||||
};
|
||||
@ -419,3 +443,21 @@
|
||||
data-lanes = <1 2>;
|
||||
};
|
||||
};
|
||||
|
||||
&mcu_cpsw {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
|
||||
};
|
||||
|
||||
&davinci_mdio {
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
|
||||
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
|
||||
};
|
||||
};
|
||||
|
||||
&cpsw_port1 {
|
||||
phy-mode = "rgmii-rxid";
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "k3-j721e-som-p0.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/net/ti-dp83867.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
@ -128,6 +129,30 @@
|
||||
J721E_WKUP_IOPAD(0x38, PIN_INPUT, 0) /* (A23) MCU_OSPI1_LBCLKO */
|
||||
>;
|
||||
};
|
||||
|
||||
mcu_cpsw_pins_default: mcu_cpsw_pins_default {
|
||||
pinctrl-single,pins = <
|
||||
J721E_WKUP_IOPAD(0x0058, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */
|
||||
J721E_WKUP_IOPAD(0x005c, PIN_INPUT, 0) /* MCU_RGMII1_RX_CTL */
|
||||
J721E_WKUP_IOPAD(0x0060, PIN_OUTPUT, 0) /* MCU_RGMII1_TD3 */
|
||||
J721E_WKUP_IOPAD(0x0064, PIN_OUTPUT, 0) /* MCU_RGMII1_TD2 */
|
||||
J721E_WKUP_IOPAD(0x0068, PIN_OUTPUT, 0) /* MCU_RGMII1_TD1 */
|
||||
J721E_WKUP_IOPAD(0x006c, PIN_OUTPUT, 0) /* MCU_RGMII1_TD0 */
|
||||
J721E_WKUP_IOPAD(0x0078, PIN_INPUT, 0) /* MCU_RGMII1_RD3 */
|
||||
J721E_WKUP_IOPAD(0x007c, PIN_INPUT, 0) /* MCU_RGMII1_RD2 */
|
||||
J721E_WKUP_IOPAD(0x0080, PIN_INPUT, 0) /* MCU_RGMII1_RD1 */
|
||||
J721E_WKUP_IOPAD(0x0084, PIN_INPUT, 0) /* MCU_RGMII1_RD0 */
|
||||
J721E_WKUP_IOPAD(0x0070, PIN_INPUT, 0) /* MCU_RGMII1_TXC */
|
||||
J721E_WKUP_IOPAD(0x0074, PIN_INPUT, 0) /* MCU_RGMII1_RXC */
|
||||
>;
|
||||
};
|
||||
|
||||
mcu_mdio_pins_default: mcu_mdio1_pins_default {
|
||||
pinctrl-single,pins = <
|
||||
J721E_WKUP_IOPAD(0x008c, PIN_OUTPUT, 0) /* MCU_MDIO0_MDC */
|
||||
J721E_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* MCU_MDIO0_MDIO */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&wkup_uart0 {
|
||||
@ -429,3 +454,21 @@
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
&mcu_cpsw {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
|
||||
};
|
||||
|
||||
&davinci_mdio {
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
|
||||
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
|
||||
};
|
||||
};
|
||||
|
||||
&cpsw_port1 {
|
||||
phy-mode = "rgmii-rxid";
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
@ -270,4 +270,53 @@
|
||||
ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
|
||||
};
|
||||
};
|
||||
|
||||
mcu_cpsw: ethernet@46000000 {
|
||||
compatible = "ti,j721e-cpsw-nuss";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
reg = <0x0 0x46000000 0x0 0x200000>;
|
||||
reg-names = "cpsw_nuss";
|
||||
ranges = <0x0 0x0 0x0 0x46000000 0x0 0x200000>;
|
||||
dma-coherent;
|
||||
clocks = <&k3_clks 18 22>;
|
||||
clock-names = "fck";
|
||||
power-domains = <&k3_pds 18 TI_SCI_PD_EXCLUSIVE>;
|
||||
|
||||
dmas = <&mcu_udmap 0xf000>,
|
||||
<&mcu_udmap 0xf001>,
|
||||
<&mcu_udmap 0xf002>,
|
||||
<&mcu_udmap 0xf003>,
|
||||
<&mcu_udmap 0xf004>,
|
||||
<&mcu_udmap 0xf005>,
|
||||
<&mcu_udmap 0xf006>,
|
||||
<&mcu_udmap 0xf007>,
|
||||
<&mcu_udmap 0x7000>;
|
||||
dma-names = "tx0", "tx1", "tx2", "tx3",
|
||||
"tx4", "tx5", "tx6", "tx7",
|
||||
"rx";
|
||||
|
||||
ethernet-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpsw_port1: port@1 {
|
||||
reg = <1>;
|
||||
ti,mac-only;
|
||||
label = "port1";
|
||||
ti,syscon-efuse = <&mcu_conf 0x200>;
|
||||
phys = <&phy_gmii_sel 1>;
|
||||
};
|
||||
};
|
||||
|
||||
davinci_mdio: mdio@f00 {
|
||||
compatible = "ti,cpsw-mdio","ti,davinci_mdio";
|
||||
reg = <0x0 0xf00 0x0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&k3_clks 18 22>;
|
||||
clock-names = "fck";
|
||||
bus_freq = <1000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -30,6 +30,7 @@
|
||||
serial9 = &main_uart7;
|
||||
serial10 = &main_uart8;
|
||||
serial11 = &main_uart9;
|
||||
ethernet0 = &cpsw_port1;
|
||||
};
|
||||
|
||||
chosen { };
|
||||
|
@ -283,6 +283,7 @@ CONFIG_SMSC911X=y
|
||||
CONFIG_SNI_AVE=y
|
||||
CONFIG_SNI_NETSEC=y
|
||||
CONFIG_STMMAC_ETH=m
|
||||
CONFIG_TI_K3_AM65_CPSW_NUSS=y
|
||||
CONFIG_MDIO_BUS_MUX_MMIOREG=y
|
||||
CONFIG_MARVELL_PHY=m
|
||||
CONFIG_MARVELL_10G_PHY=m
|
||||
@ -698,6 +699,8 @@ CONFIG_QCOM_HIDMA_MGMT=y
|
||||
CONFIG_QCOM_HIDMA=y
|
||||
CONFIG_RCAR_DMAC=y
|
||||
CONFIG_RENESAS_USB_DMAC=m
|
||||
CONFIG_TI_K3_UDMA=y
|
||||
CONFIG_TI_K3_UDMA_GLUE_LAYER=y
|
||||
CONFIG_VFIO=y
|
||||
CONFIG_VFIO_PCI=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
|
@ -6,7 +6,7 @@
|
||||
config NET_VENDOR_TI
|
||||
bool "Texas Instruments (TI) devices"
|
||||
default y
|
||||
depends on PCI || EISA || AR7 || ARCH_DAVINCI || ARCH_OMAP2PLUS || ARCH_KEYSTONE
|
||||
depends on PCI || EISA || AR7 || ARCH_DAVINCI || ARCH_OMAP2PLUS || ARCH_KEYSTONE || ARCH_K3
|
||||
---help---
|
||||
If you have a network (Ethernet) card belonging to this class, say Y.
|
||||
|
||||
@ -31,7 +31,7 @@ config TI_DAVINCI_EMAC
|
||||
|
||||
config TI_DAVINCI_MDIO
|
||||
tristate "TI DaVinci MDIO Support"
|
||||
depends on ARCH_DAVINCI || ARCH_OMAP2PLUS || ARCH_KEYSTONE || COMPILE_TEST
|
||||
depends on ARCH_DAVINCI || ARCH_OMAP2PLUS || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
|
||||
select PHYLIB
|
||||
---help---
|
||||
This driver supports TI's DaVinci MDIO module.
|
||||
@ -53,6 +53,7 @@ config TI_CPSW
|
||||
select MFD_SYSCON
|
||||
select PAGE_POOL
|
||||
select REGMAP
|
||||
imply PHY_TI_GMII_SEL
|
||||
---help---
|
||||
This driver supports TI's CPSW Ethernet Switch.
|
||||
|
||||
@ -94,6 +95,21 @@ config TI_CPTS_MOD
|
||||
imply PTP_1588_CLOCK
|
||||
default m
|
||||
|
||||
config TI_K3_AM65_CPSW_NUSS
|
||||
tristate "TI K3 AM654x/J721E CPSW Ethernet driver"
|
||||
depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
|
||||
select TI_DAVINCI_MDIO
|
||||
imply PHY_TI_GMII_SEL
|
||||
help
|
||||
This driver supports TI K3 AM654/J721E CPSW2G Ethernet SubSystem.
|
||||
The two-port Gigabit Ethernet MAC (MCU_CPSW0) subsystem provides
|
||||
Ethernet packet communication for the device: One Ethernet port
|
||||
(port 1) with selectable RGMII and RMII interfaces and an internal
|
||||
Communications Port Programming Interface (CPPI) port (port 0).
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called ti-am65-cpsw-nuss.
|
||||
|
||||
config TI_KEYSTONE_NETCP
|
||||
tristate "TI Keystone NETCP Core Support"
|
||||
select TI_DAVINCI_MDIO
|
||||
|
@ -23,3 +23,6 @@ obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o
|
||||
keystone_netcp-y := netcp_core.o cpsw_ale.o
|
||||
obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o
|
||||
keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o cpsw_ale.o
|
||||
|
||||
obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o
|
||||
ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o k3-cppi-desc-pool.o
|
||||
|
747
drivers/net/ethernet/ti/am65-cpsw-ethtool.c
Normal file
747
drivers/net/ethernet/ti/am65-cpsw-ethtool.c
Normal file
@ -0,0 +1,747 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver ethtool ops
|
||||
*
|
||||
* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "am65-cpsw-nuss.h"
|
||||
#include "cpsw_ale.h"
|
||||
|
||||
#define AM65_CPSW_REGDUMP_VER 0x1
|
||||
|
||||
enum {
|
||||
AM65_CPSW_REGDUMP_MOD_NUSS = 1,
|
||||
AM65_CPSW_REGDUMP_MOD_RGMII_STATUS = 2,
|
||||
AM65_CPSW_REGDUMP_MOD_MDIO = 3,
|
||||
AM65_CPSW_REGDUMP_MOD_CPSW = 4,
|
||||
AM65_CPSW_REGDUMP_MOD_CPSW_P0 = 5,
|
||||
AM65_CPSW_REGDUMP_MOD_CPSW_P1 = 6,
|
||||
AM65_CPSW_REGDUMP_MOD_CPSW_CPTS = 7,
|
||||
AM65_CPSW_REGDUMP_MOD_CPSW_ALE = 8,
|
||||
AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL = 9,
|
||||
AM65_CPSW_REGDUMP_MOD_LAST,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct am65_cpsw_regdump_hdr - regdump record header
|
||||
*
|
||||
* @module_id: CPSW module ID
|
||||
* @len: CPSW module registers space length in u32
|
||||
*/
|
||||
|
||||
struct am65_cpsw_regdump_hdr {
|
||||
u32 module_id;
|
||||
u32 len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct am65_cpsw_regdump_item - regdump module description
|
||||
*
|
||||
* @hdr: CPSW module header
|
||||
* @start_ofs: CPSW module registers start addr
|
||||
* @end_ofs: CPSW module registers end addr
|
||||
*
|
||||
* Registers dump provided in the format:
|
||||
* u32 : module ID
|
||||
* u32 : dump length
|
||||
* u32[..len]: registers values
|
||||
*/
|
||||
struct am65_cpsw_regdump_item {
|
||||
struct am65_cpsw_regdump_hdr hdr;
|
||||
u32 start_ofs;
|
||||
u32 end_ofs;
|
||||
};
|
||||
|
||||
#define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
|
||||
.hdr.module_id = (mod), \
|
||||
.hdr.len = (((u32 *)(end)) - ((u32 *)(start)) + 1) * sizeof(u32) * 2 + \
|
||||
sizeof(struct am65_cpsw_regdump_hdr), \
|
||||
.start_ofs = (start), \
|
||||
.end_ofs = end, \
|
||||
}
|
||||
|
||||
static const struct am65_cpsw_regdump_item am65_cpsw_regdump[] = {
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS, 0x0, 0x1c),
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS, 0x30, 0x4c),
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO, 0xf00, 0xffc),
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW, 0x20000, 0x2011c),
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0, 0x21000, 0x21320),
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1, 0x22000, 0x223a4),
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS,
|
||||
0x3d000, 0x3d048),
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE, 0x3e000, 0x3e13c),
|
||||
AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL, 0, 0),
|
||||
};
|
||||
|
||||
struct am65_cpsw_stats_regs {
|
||||
u32 rx_good_frames;
|
||||
u32 rx_broadcast_frames;
|
||||
u32 rx_multicast_frames;
|
||||
u32 rx_pause_frames; /* slave */
|
||||
u32 rx_crc_errors;
|
||||
u32 rx_align_code_errors; /* slave */
|
||||
u32 rx_oversized_frames;
|
||||
u32 rx_jabber_frames; /* slave */
|
||||
u32 rx_undersized_frames;
|
||||
u32 rx_fragments; /* slave */
|
||||
u32 ale_drop;
|
||||
u32 ale_overrun_drop;
|
||||
u32 rx_octets;
|
||||
u32 tx_good_frames;
|
||||
u32 tx_broadcast_frames;
|
||||
u32 tx_multicast_frames;
|
||||
u32 tx_pause_frames; /* slave */
|
||||
u32 tx_deferred_frames; /* slave */
|
||||
u32 tx_collision_frames; /* slave */
|
||||
u32 tx_single_coll_frames; /* slave */
|
||||
u32 tx_mult_coll_frames; /* slave */
|
||||
u32 tx_excessive_collisions; /* slave */
|
||||
u32 tx_late_collisions; /* slave */
|
||||
u32 rx_ipg_error; /* slave 10G only */
|
||||
u32 tx_carrier_sense_errors; /* slave */
|
||||
u32 tx_octets;
|
||||
u32 tx_64B_frames;
|
||||
u32 tx_65_to_127B_frames;
|
||||
u32 tx_128_to_255B_frames;
|
||||
u32 tx_256_to_511B_frames;
|
||||
u32 tx_512_to_1023B_frames;
|
||||
u32 tx_1024B_frames;
|
||||
u32 net_octets;
|
||||
u32 rx_bottom_fifo_drop;
|
||||
u32 rx_port_mask_drop;
|
||||
u32 rx_top_fifo_drop;
|
||||
u32 ale_rate_limit_drop;
|
||||
u32 ale_vid_ingress_drop;
|
||||
u32 ale_da_eq_sa_drop;
|
||||
u32 ale_block_drop; /* K3 */
|
||||
u32 ale_secure_drop; /* K3 */
|
||||
u32 ale_auth_drop; /* K3 */
|
||||
u32 ale_unknown_ucast;
|
||||
u32 ale_unknown_ucast_bytes;
|
||||
u32 ale_unknown_mcast;
|
||||
u32 ale_unknown_mcast_bytes;
|
||||
u32 ale_unknown_bcast;
|
||||
u32 ale_unknown_bcast_bytes;
|
||||
u32 ale_pol_match;
|
||||
u32 ale_pol_match_red;
|
||||
u32 ale_pol_match_yellow;
|
||||
u32 ale_mcast_sa_drop; /* K3 */
|
||||
u32 ale_dual_vlan_drop; /* K3 */
|
||||
u32 ale_len_err_drop; /* K3 */
|
||||
u32 ale_ip_next_hdr_drop; /* K3 */
|
||||
u32 ale_ipv4_frag_drop; /* K3 */
|
||||
u32 __rsvd_1[24];
|
||||
u32 iet_rx_assembly_err; /* K3 slave */
|
||||
u32 iet_rx_assembly_ok; /* K3 slave */
|
||||
u32 iet_rx_smd_err; /* K3 slave */
|
||||
u32 iet_rx_frag; /* K3 slave */
|
||||
u32 iet_tx_hold; /* K3 slave */
|
||||
u32 iet_tx_frag; /* K3 slave */
|
||||
u32 __rsvd_2[9];
|
||||
u32 tx_mem_protect_err;
|
||||
/* following NU only */
|
||||
u32 tx_pri0;
|
||||
u32 tx_pri1;
|
||||
u32 tx_pri2;
|
||||
u32 tx_pri3;
|
||||
u32 tx_pri4;
|
||||
u32 tx_pri5;
|
||||
u32 tx_pri6;
|
||||
u32 tx_pri7;
|
||||
u32 tx_pri0_bcnt;
|
||||
u32 tx_pri1_bcnt;
|
||||
u32 tx_pri2_bcnt;
|
||||
u32 tx_pri3_bcnt;
|
||||
u32 tx_pri4_bcnt;
|
||||
u32 tx_pri5_bcnt;
|
||||
u32 tx_pri6_bcnt;
|
||||
u32 tx_pri7_bcnt;
|
||||
u32 tx_pri0_drop;
|
||||
u32 tx_pri1_drop;
|
||||
u32 tx_pri2_drop;
|
||||
u32 tx_pri3_drop;
|
||||
u32 tx_pri4_drop;
|
||||
u32 tx_pri5_drop;
|
||||
u32 tx_pri6_drop;
|
||||
u32 tx_pri7_drop;
|
||||
u32 tx_pri0_drop_bcnt;
|
||||
u32 tx_pri1_drop_bcnt;
|
||||
u32 tx_pri2_drop_bcnt;
|
||||
u32 tx_pri3_drop_bcnt;
|
||||
u32 tx_pri4_drop_bcnt;
|
||||
u32 tx_pri5_drop_bcnt;
|
||||
u32 tx_pri6_drop_bcnt;
|
||||
u32 tx_pri7_drop_bcnt;
|
||||
};
|
||||
|
||||
struct am65_cpsw_ethtool_stat {
|
||||
char desc[ETH_GSTRING_LEN];
|
||||
int offset;
|
||||
};
|
||||
|
||||
#define AM65_CPSW_STATS(prefix, field) \
|
||||
{ \
|
||||
#prefix#field, \
|
||||
offsetof(struct am65_cpsw_stats_regs, field) \
|
||||
}
|
||||
|
||||
static const struct am65_cpsw_ethtool_stat am65_host_stats[] = {
|
||||
AM65_CPSW_STATS(p0_, rx_good_frames),
|
||||
AM65_CPSW_STATS(p0_, rx_broadcast_frames),
|
||||
AM65_CPSW_STATS(p0_, rx_multicast_frames),
|
||||
AM65_CPSW_STATS(p0_, rx_crc_errors),
|
||||
AM65_CPSW_STATS(p0_, rx_oversized_frames),
|
||||
AM65_CPSW_STATS(p0_, rx_undersized_frames),
|
||||
AM65_CPSW_STATS(p0_, ale_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_overrun_drop),
|
||||
AM65_CPSW_STATS(p0_, rx_octets),
|
||||
AM65_CPSW_STATS(p0_, tx_good_frames),
|
||||
AM65_CPSW_STATS(p0_, tx_broadcast_frames),
|
||||
AM65_CPSW_STATS(p0_, tx_multicast_frames),
|
||||
AM65_CPSW_STATS(p0_, tx_octets),
|
||||
AM65_CPSW_STATS(p0_, tx_64B_frames),
|
||||
AM65_CPSW_STATS(p0_, tx_65_to_127B_frames),
|
||||
AM65_CPSW_STATS(p0_, tx_128_to_255B_frames),
|
||||
AM65_CPSW_STATS(p0_, tx_256_to_511B_frames),
|
||||
AM65_CPSW_STATS(p0_, tx_512_to_1023B_frames),
|
||||
AM65_CPSW_STATS(p0_, tx_1024B_frames),
|
||||
AM65_CPSW_STATS(p0_, net_octets),
|
||||
AM65_CPSW_STATS(p0_, rx_bottom_fifo_drop),
|
||||
AM65_CPSW_STATS(p0_, rx_port_mask_drop),
|
||||
AM65_CPSW_STATS(p0_, rx_top_fifo_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_rate_limit_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_vid_ingress_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_da_eq_sa_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_block_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_secure_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_auth_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_unknown_ucast),
|
||||
AM65_CPSW_STATS(p0_, ale_unknown_ucast_bytes),
|
||||
AM65_CPSW_STATS(p0_, ale_unknown_mcast),
|
||||
AM65_CPSW_STATS(p0_, ale_unknown_mcast_bytes),
|
||||
AM65_CPSW_STATS(p0_, ale_unknown_bcast),
|
||||
AM65_CPSW_STATS(p0_, ale_unknown_bcast_bytes),
|
||||
AM65_CPSW_STATS(p0_, ale_pol_match),
|
||||
AM65_CPSW_STATS(p0_, ale_pol_match_red),
|
||||
AM65_CPSW_STATS(p0_, ale_pol_match_yellow),
|
||||
AM65_CPSW_STATS(p0_, ale_mcast_sa_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_dual_vlan_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_len_err_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_ip_next_hdr_drop),
|
||||
AM65_CPSW_STATS(p0_, ale_ipv4_frag_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_mem_protect_err),
|
||||
AM65_CPSW_STATS(p0_, tx_pri0),
|
||||
AM65_CPSW_STATS(p0_, tx_pri1),
|
||||
AM65_CPSW_STATS(p0_, tx_pri2),
|
||||
AM65_CPSW_STATS(p0_, tx_pri3),
|
||||
AM65_CPSW_STATS(p0_, tx_pri4),
|
||||
AM65_CPSW_STATS(p0_, tx_pri5),
|
||||
AM65_CPSW_STATS(p0_, tx_pri6),
|
||||
AM65_CPSW_STATS(p0_, tx_pri7),
|
||||
AM65_CPSW_STATS(p0_, tx_pri0_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri1_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri2_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri3_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri4_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri5_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri6_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri7_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri0_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_pri1_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_pri2_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_pri3_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_pri4_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_pri5_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_pri6_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_pri7_drop),
|
||||
AM65_CPSW_STATS(p0_, tx_pri0_drop_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri1_drop_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri2_drop_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri3_drop_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri4_drop_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri5_drop_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri6_drop_bcnt),
|
||||
AM65_CPSW_STATS(p0_, tx_pri7_drop_bcnt),
|
||||
};
|
||||
|
||||
static const struct am65_cpsw_ethtool_stat am65_slave_stats[] = {
|
||||
AM65_CPSW_STATS(, rx_good_frames),
|
||||
AM65_CPSW_STATS(, rx_broadcast_frames),
|
||||
AM65_CPSW_STATS(, rx_multicast_frames),
|
||||
AM65_CPSW_STATS(, rx_pause_frames),
|
||||
AM65_CPSW_STATS(, rx_crc_errors),
|
||||
AM65_CPSW_STATS(, rx_align_code_errors),
|
||||
AM65_CPSW_STATS(, rx_oversized_frames),
|
||||
AM65_CPSW_STATS(, rx_jabber_frames),
|
||||
AM65_CPSW_STATS(, rx_undersized_frames),
|
||||
AM65_CPSW_STATS(, rx_fragments),
|
||||
AM65_CPSW_STATS(, ale_drop),
|
||||
AM65_CPSW_STATS(, ale_overrun_drop),
|
||||
AM65_CPSW_STATS(, rx_octets),
|
||||
AM65_CPSW_STATS(, tx_good_frames),
|
||||
AM65_CPSW_STATS(, tx_broadcast_frames),
|
||||
AM65_CPSW_STATS(, tx_multicast_frames),
|
||||
AM65_CPSW_STATS(, tx_pause_frames),
|
||||
AM65_CPSW_STATS(, tx_deferred_frames),
|
||||
AM65_CPSW_STATS(, tx_collision_frames),
|
||||
AM65_CPSW_STATS(, tx_single_coll_frames),
|
||||
AM65_CPSW_STATS(, tx_mult_coll_frames),
|
||||
AM65_CPSW_STATS(, tx_excessive_collisions),
|
||||
AM65_CPSW_STATS(, tx_late_collisions),
|
||||
AM65_CPSW_STATS(, rx_ipg_error),
|
||||
AM65_CPSW_STATS(, tx_carrier_sense_errors),
|
||||
AM65_CPSW_STATS(, tx_octets),
|
||||
AM65_CPSW_STATS(, tx_64B_frames),
|
||||
AM65_CPSW_STATS(, tx_65_to_127B_frames),
|
||||
AM65_CPSW_STATS(, tx_128_to_255B_frames),
|
||||
AM65_CPSW_STATS(, tx_256_to_511B_frames),
|
||||
AM65_CPSW_STATS(, tx_512_to_1023B_frames),
|
||||
AM65_CPSW_STATS(, tx_1024B_frames),
|
||||
AM65_CPSW_STATS(, net_octets),
|
||||
AM65_CPSW_STATS(, rx_bottom_fifo_drop),
|
||||
AM65_CPSW_STATS(, rx_port_mask_drop),
|
||||
AM65_CPSW_STATS(, rx_top_fifo_drop),
|
||||
AM65_CPSW_STATS(, ale_rate_limit_drop),
|
||||
AM65_CPSW_STATS(, ale_vid_ingress_drop),
|
||||
AM65_CPSW_STATS(, ale_da_eq_sa_drop),
|
||||
AM65_CPSW_STATS(, ale_block_drop),
|
||||
AM65_CPSW_STATS(, ale_secure_drop),
|
||||
AM65_CPSW_STATS(, ale_auth_drop),
|
||||
AM65_CPSW_STATS(, ale_unknown_ucast),
|
||||
AM65_CPSW_STATS(, ale_unknown_ucast_bytes),
|
||||
AM65_CPSW_STATS(, ale_unknown_mcast),
|
||||
AM65_CPSW_STATS(, ale_unknown_mcast_bytes),
|
||||
AM65_CPSW_STATS(, ale_unknown_bcast),
|
||||
AM65_CPSW_STATS(, ale_unknown_bcast_bytes),
|
||||
AM65_CPSW_STATS(, ale_pol_match),
|
||||
AM65_CPSW_STATS(, ale_pol_match_red),
|
||||
AM65_CPSW_STATS(, ale_pol_match_yellow),
|
||||
AM65_CPSW_STATS(, ale_mcast_sa_drop),
|
||||
AM65_CPSW_STATS(, ale_dual_vlan_drop),
|
||||
AM65_CPSW_STATS(, ale_len_err_drop),
|
||||
AM65_CPSW_STATS(, ale_ip_next_hdr_drop),
|
||||
AM65_CPSW_STATS(, ale_ipv4_frag_drop),
|
||||
AM65_CPSW_STATS(, iet_rx_assembly_err),
|
||||
AM65_CPSW_STATS(, iet_rx_assembly_ok),
|
||||
AM65_CPSW_STATS(, iet_rx_smd_err),
|
||||
AM65_CPSW_STATS(, iet_rx_frag),
|
||||
AM65_CPSW_STATS(, iet_tx_hold),
|
||||
AM65_CPSW_STATS(, iet_tx_frag),
|
||||
AM65_CPSW_STATS(, tx_mem_protect_err),
|
||||
AM65_CPSW_STATS(, tx_pri0),
|
||||
AM65_CPSW_STATS(, tx_pri1),
|
||||
AM65_CPSW_STATS(, tx_pri2),
|
||||
AM65_CPSW_STATS(, tx_pri3),
|
||||
AM65_CPSW_STATS(, tx_pri4),
|
||||
AM65_CPSW_STATS(, tx_pri5),
|
||||
AM65_CPSW_STATS(, tx_pri6),
|
||||
AM65_CPSW_STATS(, tx_pri7),
|
||||
AM65_CPSW_STATS(, tx_pri0_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri1_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri2_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri3_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri4_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri5_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri6_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri7_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri0_drop),
|
||||
AM65_CPSW_STATS(, tx_pri1_drop),
|
||||
AM65_CPSW_STATS(, tx_pri2_drop),
|
||||
AM65_CPSW_STATS(, tx_pri3_drop),
|
||||
AM65_CPSW_STATS(, tx_pri4_drop),
|
||||
AM65_CPSW_STATS(, tx_pri5_drop),
|
||||
AM65_CPSW_STATS(, tx_pri6_drop),
|
||||
AM65_CPSW_STATS(, tx_pri7_drop),
|
||||
AM65_CPSW_STATS(, tx_pri0_drop_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri1_drop_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri2_drop_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri3_drop_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri4_drop_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri5_drop_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri6_drop_bcnt),
|
||||
AM65_CPSW_STATS(, tx_pri7_drop_bcnt),
|
||||
};
|
||||
|
||||
/* Ethtool priv_flags */
|
||||
static const char am65_cpsw_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
|
||||
#define AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN BIT(0)
|
||||
"p0-rx-ptype-rrobin",
|
||||
};
|
||||
|
||||
static int am65_cpsw_ethtool_op_begin(struct net_device *ndev)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_sync(common->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(common->dev, "ethtool begin failed %d\n", ret);
|
||||
pm_runtime_put_noidle(common->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void am65_cpsw_ethtool_op_complete(struct net_device *ndev)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_put(common->dev);
|
||||
if (ret < 0 && ret != -EBUSY)
|
||||
dev_err(common->dev, "ethtool complete failed %d\n", ret);
|
||||
}
|
||||
|
||||
static void am65_cpsw_get_drvinfo(struct net_device *ndev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
|
||||
strlcpy(info->driver, dev_driver_string(common->dev),
|
||||
sizeof(info->driver));
|
||||
strlcpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
|
||||
}
|
||||
|
||||
static u32 am65_cpsw_get_msglevel(struct net_device *ndev)
|
||||
{
|
||||
struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
|
||||
|
||||
return priv->msg_enable;
|
||||
}
|
||||
|
||||
static void am65_cpsw_set_msglevel(struct net_device *ndev, u32 value)
|
||||
{
|
||||
struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
|
||||
|
||||
priv->msg_enable = value;
|
||||
}
|
||||
|
||||
static void am65_cpsw_get_channels(struct net_device *ndev,
|
||||
struct ethtool_channels *ch)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
|
||||
ch->max_rx = AM65_CPSW_MAX_RX_QUEUES;
|
||||
ch->max_tx = AM65_CPSW_MAX_TX_QUEUES;
|
||||
ch->rx_count = AM65_CPSW_MAX_RX_QUEUES;
|
||||
ch->tx_count = common->tx_ch_num;
|
||||
}
|
||||
|
||||
static int am65_cpsw_set_channels(struct net_device *ndev,
|
||||
struct ethtool_channels *chs)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
|
||||
if (!chs->rx_count || !chs->tx_count)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if interface is up. Can change the num queues when
|
||||
* the interface is down.
|
||||
*/
|
||||
if (netif_running(ndev))
|
||||
return -EBUSY;
|
||||
|
||||
am65_cpsw_nuss_remove_tx_chns(common);
|
||||
|
||||
return am65_cpsw_nuss_update_tx_chns(common, chs->tx_count);
|
||||
}
|
||||
|
||||
static void am65_cpsw_get_ringparam(struct net_device *ndev,
|
||||
struct ethtool_ringparam *ering)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
|
||||
/* not supported */
|
||||
ering->tx_pending = common->tx_chns[0].descs_num;
|
||||
ering->rx_pending = common->rx_chns.descs_num;
|
||||
}
|
||||
|
||||
static void am65_cpsw_get_pauseparam(struct net_device *ndev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
pause->autoneg = AUTONEG_DISABLE;
|
||||
pause->rx_pause = salve->rx_pause ? true : false;
|
||||
pause->tx_pause = salve->tx_pause ? true : false;
|
||||
}
|
||||
|
||||
static int am65_cpsw_set_pauseparam(struct net_device *ndev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
if (!salve->phy)
|
||||
return -EINVAL;
|
||||
|
||||
if (!phy_validate_pause(salve->phy, pause))
|
||||
return -EINVAL;
|
||||
|
||||
salve->rx_pause = pause->rx_pause ? true : false;
|
||||
salve->tx_pause = pause->tx_pause ? true : false;
|
||||
|
||||
phy_set_asym_pause(salve->phy, salve->rx_pause, salve->tx_pause);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void am65_cpsw_get_wol(struct net_device *ndev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
wol->supported = 0;
|
||||
wol->wolopts = 0;
|
||||
|
||||
if (salve->phy)
|
||||
phy_ethtool_get_wol(salve->phy, wol);
|
||||
}
|
||||
|
||||
static int am65_cpsw_set_wol(struct net_device *ndev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
if (!salve->phy)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phy_ethtool_set_wol(salve->phy, wol);
|
||||
}
|
||||
|
||||
static int am65_cpsw_get_link_ksettings(struct net_device *ndev,
|
||||
struct ethtool_link_ksettings *ecmd)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
if (!salve->phy)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
phy_ethtool_ksettings_get(salve->phy, ecmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
am65_cpsw_set_link_ksettings(struct net_device *ndev,
|
||||
const struct ethtool_link_ksettings *ecmd)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phy_ethtool_ksettings_set(salve->phy, ecmd);
|
||||
}
|
||||
|
||||
static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phy_ethtool_get_eee(salve->phy, edata);
|
||||
}
|
||||
|
||||
static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phy_ethtool_set_eee(salve->phy, edata);
|
||||
}
|
||||
|
||||
static int am65_cpsw_nway_reset(struct net_device *ndev)
|
||||
{
|
||||
struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
|
||||
|
||||
if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phy_restart_aneg(salve->phy);
|
||||
}
|
||||
|
||||
static int am65_cpsw_get_regs_len(struct net_device *ndev)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
u32 i, regdump_len = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
|
||||
if (am65_cpsw_regdump[i].hdr.module_id ==
|
||||
AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
|
||||
regdump_len += sizeof(struct am65_cpsw_regdump_hdr);
|
||||
regdump_len += common->ale->params.ale_entries *
|
||||
ALE_ENTRY_WORDS * sizeof(u32);
|
||||
continue;
|
||||
}
|
||||
regdump_len += am65_cpsw_regdump[i].hdr.len;
|
||||
}
|
||||
|
||||
return regdump_len;
|
||||
}
|
||||
|
||||
static void am65_cpsw_get_regs(struct net_device *ndev,
|
||||
struct ethtool_regs *regs, void *p)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
u32 i, j, pos, *reg = p;
|
||||
|
||||
/* update CPSW IP version */
|
||||
regs->version = AM65_CPSW_REGDUMP_VER;
|
||||
|
||||
pos = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
|
||||
reg[pos++] = am65_cpsw_regdump[i].hdr.module_id;
|
||||
|
||||
if (am65_cpsw_regdump[i].hdr.module_id ==
|
||||
AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
|
||||
u32 ale_tbl_len = common->ale->params.ale_entries *
|
||||
ALE_ENTRY_WORDS * sizeof(u32) +
|
||||
sizeof(struct am65_cpsw_regdump_hdr);
|
||||
reg[pos++] = ale_tbl_len;
|
||||
cpsw_ale_dump(common->ale, ®[pos]);
|
||||
pos += ale_tbl_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
reg[pos++] = am65_cpsw_regdump[i].hdr.len;
|
||||
|
||||
j = am65_cpsw_regdump[i].start_ofs;
|
||||
do {
|
||||
reg[pos++] = j;
|
||||
reg[pos++] = readl_relaxed(common->ss_base + j);
|
||||
j += sizeof(u32);
|
||||
} while (j <= am65_cpsw_regdump[i].end_ofs);
|
||||
}
|
||||
}
|
||||
|
||||
static int am65_cpsw_get_sset_count(struct net_device *ndev, int sset)
|
||||
{
|
||||
switch (sset) {
|
||||
case ETH_SS_STATS:
|
||||
return ARRAY_SIZE(am65_host_stats) +
|
||||
ARRAY_SIZE(am65_slave_stats);
|
||||
case ETH_SS_PRIV_FLAGS:
|
||||
return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static void am65_cpsw_get_strings(struct net_device *ndev,
|
||||
u32 stringset, u8 *data)
|
||||
{
|
||||
const struct am65_cpsw_ethtool_stat *hw_stats;
|
||||
u32 i, num_stats;
|
||||
u8 *p = data;
|
||||
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
num_stats = ARRAY_SIZE(am65_host_stats);
|
||||
hw_stats = am65_host_stats;
|
||||
for (i = 0; i < num_stats; i++) {
|
||||
memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
|
||||
num_stats = ARRAY_SIZE(am65_slave_stats);
|
||||
hw_stats = am65_slave_stats;
|
||||
for (i = 0; i < num_stats; i++) {
|
||||
memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
break;
|
||||
case ETH_SS_PRIV_FLAGS:
|
||||
num_stats = ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
|
||||
|
||||
for (i = 0; i < num_stats; i++) {
|
||||
memcpy(p, am65_cpsw_ethtool_priv_flags[i],
|
||||
ETH_GSTRING_LEN);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
const struct am65_cpsw_ethtool_stat *hw_stats;
|
||||
struct am65_cpsw_host *host_p;
|
||||
struct am65_cpsw_port *port;
|
||||
u32 i, num_stats;
|
||||
|
||||
host_p = am65_common_get_host(common);
|
||||
port = am65_ndev_to_port(ndev);
|
||||
num_stats = ARRAY_SIZE(am65_host_stats);
|
||||
hw_stats = am65_host_stats;
|
||||
for (i = 0; i < num_stats; i++)
|
||||
*data++ = readl_relaxed(host_p->stat_base +
|
||||
hw_stats[i].offset);
|
||||
|
||||
num_stats = ARRAY_SIZE(am65_slave_stats);
|
||||
hw_stats = am65_slave_stats;
|
||||
for (i = 0; i < num_stats; i++)
|
||||
*data++ = readl_relaxed(port->stat_base +
|
||||
hw_stats[i].offset);
|
||||
}
|
||||
|
||||
static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
u32 priv_flags = 0;
|
||||
|
||||
if (common->pf_p0_rx_ptype_rrobin)
|
||||
priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
|
||||
|
||||
return priv_flags;
|
||||
}
|
||||
|
||||
static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
|
||||
{
|
||||
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
|
||||
|
||||
common->pf_p0_rx_ptype_rrobin =
|
||||
!!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
|
||||
am65_cpsw_nuss_set_p0_ptype(common);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
|
||||
.begin = am65_cpsw_ethtool_op_begin,
|
||||
.complete = am65_cpsw_ethtool_op_complete,
|
||||
.get_drvinfo = am65_cpsw_get_drvinfo,
|
||||
.get_msglevel = am65_cpsw_get_msglevel,
|
||||
.set_msglevel = am65_cpsw_set_msglevel,
|
||||
.get_channels = am65_cpsw_get_channels,
|
||||
.set_channels = am65_cpsw_set_channels,
|
||||
.get_ringparam = am65_cpsw_get_ringparam,
|
||||
.get_regs_len = am65_cpsw_get_regs_len,
|
||||
.get_regs = am65_cpsw_get_regs,
|
||||
.get_sset_count = am65_cpsw_get_sset_count,
|
||||
.get_strings = am65_cpsw_get_strings,
|
||||
.get_ethtool_stats = am65_cpsw_get_ethtool_stats,
|
||||
.get_ts_info = ethtool_op_get_ts_info,
|
||||
.get_priv_flags = am65_cpsw_get_ethtool_priv_flags,
|
||||
.set_priv_flags = am65_cpsw_set_ethtool_priv_flags,
|
||||
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_link_ksettings = am65_cpsw_get_link_ksettings,
|
||||
.set_link_ksettings = am65_cpsw_set_link_ksettings,
|
||||
.get_pauseparam = am65_cpsw_get_pauseparam,
|
||||
.set_pauseparam = am65_cpsw_set_pauseparam,
|
||||
.get_wol = am65_cpsw_get_wol,
|
||||
.set_wol = am65_cpsw_set_wol,
|
||||
.get_eee = am65_cpsw_get_eee,
|
||||
.set_eee = am65_cpsw_set_eee,
|
||||
.nway_reset = am65_cpsw_nway_reset,
|
||||
};
|
1965
drivers/net/ethernet/ti/am65-cpsw-nuss.c
Normal file
1965
drivers/net/ethernet/ti/am65-cpsw-nuss.c
Normal file
File diff suppressed because it is too large
Load Diff
142
drivers/net/ethernet/ti/am65-cpsw-nuss.h
Normal file
142
drivers/net/ethernet/ti/am65-cpsw-nuss.h
Normal file
@ -0,0 +1,142 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AM65_CPSW_NUSS_H_
|
||||
#define AM65_CPSW_NUSS_H_
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#define HOST_PORT_NUM 0
|
||||
|
||||
#define AM65_CPSW_MAX_TX_QUEUES 8
|
||||
#define AM65_CPSW_MAX_RX_QUEUES 1
|
||||
#define AM65_CPSW_MAX_RX_FLOWS 1
|
||||
|
||||
struct am65_cpsw_slave_data {
|
||||
bool mac_only;
|
||||
struct cpsw_sl *mac_sl;
|
||||
struct device_node *phy_node;
|
||||
struct phy_device *phy;
|
||||
phy_interface_t phy_if;
|
||||
struct phy *ifphy;
|
||||
bool rx_pause;
|
||||
bool tx_pause;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct am65_cpsw_port {
|
||||
struct am65_cpsw_common *common;
|
||||
struct net_device *ndev;
|
||||
const char *name;
|
||||
u32 port_id;
|
||||
void __iomem *port_base;
|
||||
void __iomem *stat_base;
|
||||
bool disabled;
|
||||
struct am65_cpsw_slave_data slave;
|
||||
};
|
||||
|
||||
struct am65_cpsw_host {
|
||||
struct am65_cpsw_common *common;
|
||||
void __iomem *port_base;
|
||||
void __iomem *stat_base;
|
||||
};
|
||||
|
||||
struct am65_cpsw_tx_chn {
|
||||
struct napi_struct napi_tx;
|
||||
struct am65_cpsw_common *common;
|
||||
struct k3_cppi_desc_pool *desc_pool;
|
||||
struct k3_udma_glue_tx_channel *tx_chn;
|
||||
int irq;
|
||||
u32 id;
|
||||
u32 descs_num;
|
||||
char tx_chn_name[128];
|
||||
};
|
||||
|
||||
struct am65_cpsw_rx_chn {
|
||||
struct device *dev;
|
||||
struct k3_cppi_desc_pool *desc_pool;
|
||||
struct k3_udma_glue_rx_channel *rx_chn;
|
||||
u32 descs_num;
|
||||
int irq;
|
||||
};
|
||||
|
||||
#define AM65_CPSW_QUIRK_I2027_NO_TX_CSUM BIT(0)
|
||||
|
||||
struct am65_cpsw_pdata {
|
||||
u32 quirks;
|
||||
};
|
||||
|
||||
struct am65_cpsw_common {
|
||||
struct device *dev;
|
||||
const struct am65_cpsw_pdata *pdata;
|
||||
|
||||
void __iomem *ss_base;
|
||||
void __iomem *cpsw_base;
|
||||
|
||||
u32 port_num;
|
||||
struct am65_cpsw_host host;
|
||||
struct am65_cpsw_port *ports;
|
||||
u32 disabled_ports_mask;
|
||||
|
||||
int usage_count; /* number of opened ports */
|
||||
struct cpsw_ale *ale;
|
||||
int tx_ch_num;
|
||||
u32 rx_flow_id_base;
|
||||
|
||||
struct am65_cpsw_tx_chn tx_chns[AM65_CPSW_MAX_TX_QUEUES];
|
||||
struct completion tdown_complete;
|
||||
atomic_t tdown_cnt;
|
||||
|
||||
struct am65_cpsw_rx_chn rx_chns;
|
||||
struct napi_struct napi_rx;
|
||||
|
||||
u32 nuss_ver;
|
||||
u32 cpsw_ver;
|
||||
|
||||
bool pf_p0_rx_ptype_rrobin;
|
||||
};
|
||||
|
||||
struct am65_cpsw_ndev_stats {
|
||||
u64 tx_packets;
|
||||
u64 tx_bytes;
|
||||
u64 rx_packets;
|
||||
u64 rx_bytes;
|
||||
struct u64_stats_sync syncp;
|
||||
};
|
||||
|
||||
struct am65_cpsw_ndev_priv {
|
||||
u32 msg_enable;
|
||||
struct am65_cpsw_port *port;
|
||||
struct am65_cpsw_ndev_stats __percpu *stats;
|
||||
};
|
||||
|
||||
#define am65_ndev_to_priv(ndev) \
|
||||
((struct am65_cpsw_ndev_priv *)netdev_priv(ndev))
|
||||
#define am65_ndev_to_port(ndev) (am65_ndev_to_priv(ndev)->port)
|
||||
#define am65_ndev_to_common(ndev) (am65_ndev_to_port(ndev)->common)
|
||||
#define am65_ndev_to_slave(ndev) (&am65_ndev_to_port(ndev)->slave)
|
||||
|
||||
#define am65_common_get_host(common) (&(common)->host)
|
||||
#define am65_common_get_port(common, id) (&(common)->ports[(id) - 1])
|
||||
|
||||
#define am65_cpsw_napi_to_common(pnapi) \
|
||||
container_of(pnapi, struct am65_cpsw_common, napi_rx)
|
||||
#define am65_cpsw_napi_to_tx_chn(pnapi) \
|
||||
container_of(pnapi, struct am65_cpsw_tx_chn, napi_tx)
|
||||
|
||||
#define AM65_CPSW_DRV_NAME "am65-cpsw-nuss"
|
||||
|
||||
#define AM65_CPSW_IS_CPSW2G(common) ((common)->port_num == 1)
|
||||
|
||||
extern const struct ethtool_ops am65_cpsw_ethtool_ops_slave;
|
||||
|
||||
void am65_cpsw_nuss_adjust_link(struct net_device *ndev);
|
||||
void am65_cpsw_nuss_set_p0_ptype(struct am65_cpsw_common *common);
|
||||
void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common);
|
||||
int am65_cpsw_nuss_update_tx_chns(struct am65_cpsw_common *common, int num_tx);
|
||||
|
||||
#endif /* AM65_CPSW_NUSS_H_ */
|
@ -44,6 +44,8 @@
|
||||
#define ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS 0x9C
|
||||
#define ALE_VLAN_MASK_MUX(reg) (0xc0 + (0x4 * (reg)))
|
||||
|
||||
#define AM65_CPSW_ALE_THREAD_DEF_REG 0x134
|
||||
|
||||
#define ALE_TABLE_WRITE BIT(31)
|
||||
|
||||
#define ALE_TYPE_FREE 0
|
||||
@ -122,6 +124,8 @@ DEFINE_ALE_FIELD(mcast, 40, 1)
|
||||
DEFINE_ALE_FIELD(vlan_unreg_mcast_idx, 20, 3)
|
||||
DEFINE_ALE_FIELD(vlan_reg_mcast_idx, 44, 3)
|
||||
|
||||
#define NU_VLAN_UNREG_MCAST_IDX 1
|
||||
|
||||
/* The MAC address field in the ALE entry cannot be macroized as above */
|
||||
static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
|
||||
{
|
||||
@ -455,6 +459,8 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,
|
||||
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
|
||||
ale->vlan_field_bits);
|
||||
} else {
|
||||
cpsw_ale_set_vlan_unreg_mcast_idx(ale_entry,
|
||||
NU_VLAN_UNREG_MCAST_IDX);
|
||||
cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);
|
||||
}
|
||||
cpsw_ale_set_vlan_member_list(ale_entry, port_mask,
|
||||
@ -775,6 +781,22 @@ static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
|
||||
.port_shift = 0,
|
||||
.bits = 1,
|
||||
},
|
||||
[ALE_PORT_MACONLY] = {
|
||||
.name = "mac_only_port_mode",
|
||||
.offset = ALE_PORTCTL,
|
||||
.port_offset = 4,
|
||||
.shift = 11,
|
||||
.port_shift = 0,
|
||||
.bits = 1,
|
||||
},
|
||||
[ALE_PORT_MACONLY_CAF] = {
|
||||
.name = "mac_only_port_caf",
|
||||
.offset = ALE_PORTCTL,
|
||||
.port_offset = 4,
|
||||
.shift = 13,
|
||||
.port_shift = 0,
|
||||
.bits = 1,
|
||||
},
|
||||
[ALE_PORT_MCAST_LIMIT] = {
|
||||
.name = "mcast_limit",
|
||||
.offset = ALE_PORTCTL,
|
||||
@ -823,6 +845,22 @@ static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
|
||||
.port_shift = 0,
|
||||
.bits = 6,
|
||||
},
|
||||
[ALE_DEFAULT_THREAD_ID] = {
|
||||
.name = "default_thread_id",
|
||||
.offset = AM65_CPSW_ALE_THREAD_DEF_REG,
|
||||
.port_offset = 0,
|
||||
.shift = 0,
|
||||
.port_shift = 0,
|
||||
.bits = 6,
|
||||
},
|
||||
[ALE_DEFAULT_THREAD_ENABLE] = {
|
||||
.name = "default_thread_id_enable",
|
||||
.offset = AM65_CPSW_ALE_THREAD_DEF_REG,
|
||||
.port_offset = 0,
|
||||
.shift = 15,
|
||||
.port_shift = 0,
|
||||
.bits = 1,
|
||||
},
|
||||
};
|
||||
|
||||
int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
|
||||
|
@ -62,8 +62,12 @@ enum cpsw_ale_control {
|
||||
ALE_PORT_UNKNOWN_MCAST_FLOOD,
|
||||
ALE_PORT_UNKNOWN_REG_MCAST_FLOOD,
|
||||
ALE_PORT_UNTAGGED_EGRESS,
|
||||
ALE_PORT_MACONLY,
|
||||
ALE_PORT_MACONLY_CAF,
|
||||
ALE_PORT_BCAST_LIMIT,
|
||||
ALE_PORT_MCAST_LIMIT,
|
||||
ALE_DEFAULT_THREAD_ID,
|
||||
ALE_DEFAULT_THREAD_ENABLE,
|
||||
ALE_NUM_CONTROLS,
|
||||
};
|
||||
|
||||
|
126
drivers/net/ethernet/ti/k3-cppi-desc-pool.c
Normal file
126
drivers/net/ethernet/ti/k3-cppi-desc-pool.c
Normal file
@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* TI K3 CPPI5 descriptors pool API
|
||||
*
|
||||
* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "k3-cppi-desc-pool.h"
|
||||
|
||||
struct k3_cppi_desc_pool {
|
||||
struct device *dev;
|
||||
dma_addr_t dma_addr;
|
||||
void *cpumem; /* dma_alloc map */
|
||||
size_t desc_size;
|
||||
size_t mem_size;
|
||||
size_t num_desc;
|
||||
struct gen_pool *gen_pool;
|
||||
};
|
||||
|
||||
void k3_cppi_desc_pool_destroy(struct k3_cppi_desc_pool *pool)
|
||||
{
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
WARN(gen_pool_size(pool->gen_pool) != gen_pool_avail(pool->gen_pool),
|
||||
"k3_knav_desc_pool size %zu != avail %zu",
|
||||
gen_pool_size(pool->gen_pool),
|
||||
gen_pool_avail(pool->gen_pool));
|
||||
if (pool->cpumem)
|
||||
dma_free_coherent(pool->dev, pool->mem_size, pool->cpumem,
|
||||
pool->dma_addr);
|
||||
|
||||
gen_pool_destroy(pool->gen_pool); /* frees pool->name */
|
||||
}
|
||||
|
||||
struct k3_cppi_desc_pool *
|
||||
k3_cppi_desc_pool_create_name(struct device *dev, size_t size,
|
||||
size_t desc_size,
|
||||
const char *name)
|
||||
{
|
||||
struct k3_cppi_desc_pool *pool;
|
||||
const char *pool_name = NULL;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
pool = devm_kzalloc(dev, sizeof(*pool), GFP_KERNEL);
|
||||
if (!pool)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
pool->dev = dev;
|
||||
pool->desc_size = roundup_pow_of_two(desc_size);
|
||||
pool->num_desc = size;
|
||||
pool->mem_size = pool->num_desc * pool->desc_size;
|
||||
|
||||
pool_name = kstrdup_const(name ? name : dev_name(pool->dev),
|
||||
GFP_KERNEL);
|
||||
if (!pool_name)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pool->gen_pool = gen_pool_create(ilog2(pool->desc_size), -1);
|
||||
if (IS_ERR(pool->gen_pool)) {
|
||||
ret = PTR_ERR(pool->gen_pool);
|
||||
dev_err(pool->dev, "pool create failed %d\n", ret);
|
||||
kfree_const(pool_name);
|
||||
goto gen_pool_create_fail;
|
||||
}
|
||||
|
||||
pool->gen_pool->name = pool_name;
|
||||
|
||||
pool->cpumem = dma_alloc_coherent(pool->dev, pool->mem_size,
|
||||
&pool->dma_addr, GFP_KERNEL);
|
||||
|
||||
if (!pool->cpumem)
|
||||
goto dma_alloc_fail;
|
||||
|
||||
ret = gen_pool_add_virt(pool->gen_pool, (unsigned long)pool->cpumem,
|
||||
(phys_addr_t)pool->dma_addr, pool->mem_size,
|
||||
-1);
|
||||
if (ret < 0) {
|
||||
dev_err(pool->dev, "pool add failed %d\n", ret);
|
||||
goto gen_pool_add_virt_fail;
|
||||
}
|
||||
|
||||
return pool;
|
||||
|
||||
gen_pool_add_virt_fail:
|
||||
dma_free_coherent(pool->dev, pool->mem_size, pool->cpumem,
|
||||
pool->dma_addr);
|
||||
dma_alloc_fail:
|
||||
gen_pool_destroy(pool->gen_pool); /* frees pool->name */
|
||||
gen_pool_create_fail:
|
||||
devm_kfree(pool->dev, pool);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
dma_addr_t k3_cppi_desc_pool_virt2dma(struct k3_cppi_desc_pool *pool,
|
||||
void *addr)
|
||||
{
|
||||
return addr ? pool->dma_addr + (addr - pool->cpumem) : 0;
|
||||
}
|
||||
|
||||
void *k3_cppi_desc_pool_dma2virt(struct k3_cppi_desc_pool *pool, dma_addr_t dma)
|
||||
{
|
||||
return dma ? pool->cpumem + (dma - pool->dma_addr) : NULL;
|
||||
}
|
||||
|
||||
void *k3_cppi_desc_pool_alloc(struct k3_cppi_desc_pool *pool)
|
||||
{
|
||||
return (void *)gen_pool_alloc(pool->gen_pool, pool->desc_size);
|
||||
}
|
||||
|
||||
void k3_cppi_desc_pool_free(struct k3_cppi_desc_pool *pool, void *addr)
|
||||
{
|
||||
gen_pool_free(pool->gen_pool, (unsigned long)addr, pool->desc_size);
|
||||
}
|
||||
|
||||
size_t k3_cppi_desc_pool_avail(struct k3_cppi_desc_pool *pool)
|
||||
{
|
||||
return gen_pool_avail(pool->gen_pool) / pool->desc_size;
|
||||
}
|
30
drivers/net/ethernet/ti/k3-cppi-desc-pool.h
Normal file
30
drivers/net/ethernet/ti/k3-cppi-desc-pool.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* TI K3 CPPI5 descriptors pool
|
||||
*
|
||||
* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
|
||||
*/
|
||||
|
||||
#ifndef K3_CPPI_DESC_POOL_H_
|
||||
#define K3_CPPI_DESC_POOL_H_
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct k3_cppi_desc_pool;
|
||||
|
||||
void k3_cppi_desc_pool_destroy(struct k3_cppi_desc_pool *pool);
|
||||
struct k3_cppi_desc_pool *
|
||||
k3_cppi_desc_pool_create_name(struct device *dev, size_t size,
|
||||
size_t desc_size,
|
||||
const char *name);
|
||||
#define k3_cppi_desc_pool_create(dev, size, desc_size) \
|
||||
k3_cppi_desc_pool_create_name(dev, size, desc_size, NULL)
|
||||
dma_addr_t
|
||||
k3_cppi_desc_pool_virt2dma(struct k3_cppi_desc_pool *pool, void *addr);
|
||||
void *
|
||||
k3_cppi_desc_pool_dma2virt(struct k3_cppi_desc_pool *pool, dma_addr_t dma);
|
||||
void *k3_cppi_desc_pool_alloc(struct k3_cppi_desc_pool *pool);
|
||||
void k3_cppi_desc_pool_free(struct k3_cppi_desc_pool *pool, void *addr);
|
||||
size_t k3_cppi_desc_pool_avail(struct k3_cppi_desc_pool *pool);
|
||||
|
||||
#endif /* K3_CPPI_DESC_POOL_H_ */
|
@ -106,11 +106,8 @@ config TWL4030_USB
|
||||
|
||||
config PHY_TI_GMII_SEL
|
||||
tristate
|
||||
default y if TI_CPSW=y || TI_CPSW_SWITCHDEV=y
|
||||
depends on TI_CPSW || TI_CPSW_SWITCHDEV || COMPILE_TEST
|
||||
select GENERIC_PHY
|
||||
select REGMAP
|
||||
default m
|
||||
help
|
||||
This driver supports configuring of the TI CPSW Port mode depending on
|
||||
the Ethernet PHY connected to the CPSW Port.
|
||||
|
Loading…
Reference in New Issue
Block a user