mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00

Refreshed patches for qualcommb/ipq95xx by running make target/linux/refresh after creating a .config containing: CONFIG_TARGET_qualcommbe=y CONFIG_TARGET_qualcommbe_ipq95xx=y CONFIG_TARGET_qualcommbe_ipq95xx_DEVICE_qcom_rdp433=y Signed-off-by: John Audia <therealgraysky@proton.me> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
1040 lines
29 KiB
Diff
1040 lines
29 KiB
Diff
From 028ed86f08a4fdf25213af5f5afd63b30fb7b029 Mon Sep 17 00:00:00 2001
|
|
From: Lei Wei <quic_leiwei@quicinc.com>
|
|
Date: Thu, 29 Feb 2024 16:59:53 +0800
|
|
Subject: [PATCH 32/50] net: ethernet: qualcomm: Add phylink support for PPE
|
|
MAC ports
|
|
|
|
Add MAC initialization and phylink functions for PPE MAC ports.
|
|
|
|
Change-Id: I39dcba671732392bcfa2e734473fd083989bfbec
|
|
Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
|
|
---
|
|
drivers/net/ethernet/qualcomm/Kconfig | 3 +
|
|
drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +-
|
|
drivers/net/ethernet/qualcomm/ppe/ppe.c | 9 +
|
|
drivers/net/ethernet/qualcomm/ppe/ppe.h | 2 +
|
|
drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 728 +++++++++++++++++++
|
|
drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 76 ++
|
|
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 123 ++++
|
|
7 files changed, 942 insertions(+), 1 deletion(-)
|
|
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_port.c
|
|
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_port.h
|
|
|
|
--- a/drivers/net/ethernet/qualcomm/Kconfig
|
|
+++ b/drivers/net/ethernet/qualcomm/Kconfig
|
|
@@ -66,6 +66,9 @@ config QCOM_PPE
|
|
depends on HAS_IOMEM && OF
|
|
depends on COMMON_CLK
|
|
select REGMAP_MMIO
|
|
+ select PHYLINK
|
|
+ select PCS_QCOM_IPQ_UNIPHY
|
|
+ select SFP
|
|
help
|
|
This driver supports the Qualcomm Technologies, Inc. packet
|
|
process engine (PPE) available with IPQ SoC. The PPE houses
|
|
--- a/drivers/net/ethernet/qualcomm/ppe/Makefile
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
|
|
@@ -4,4 +4,4 @@
|
|
#
|
|
|
|
obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
|
|
-qcom-ppe-objs := ppe.o ppe_config.o ppe_api.o ppe_debugfs.o
|
|
+qcom-ppe-objs := ppe.o ppe_config.o ppe_api.o ppe_debugfs.o ppe_port.o
|
|
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
|
|
@@ -17,6 +17,7 @@
|
|
#include "ppe.h"
|
|
#include "ppe_config.h"
|
|
#include "ppe_debugfs.h"
|
|
+#include "ppe_port.h"
|
|
|
|
#define PPE_PORT_MAX 8
|
|
#define PPE_CLK_RATE 353000000
|
|
@@ -207,6 +208,11 @@ static int qcom_ppe_probe(struct platfor
|
|
if (ret)
|
|
return dev_err_probe(dev, ret, "PPE HW config failed\n");
|
|
|
|
+ ret = ppe_port_mac_init(ppe_dev);
|
|
+ if (ret)
|
|
+ return dev_err_probe(dev, ret,
|
|
+ "PPE Port MAC initialization failed\n");
|
|
+
|
|
ppe_debugfs_setup(ppe_dev);
|
|
platform_set_drvdata(pdev, ppe_dev);
|
|
|
|
@@ -219,6 +225,9 @@ static void qcom_ppe_remove(struct platf
|
|
|
|
ppe_dev = platform_get_drvdata(pdev);
|
|
ppe_debugfs_teardown(ppe_dev);
|
|
+ ppe_port_mac_deinit(ppe_dev);
|
|
+
|
|
+ platform_set_drvdata(pdev, NULL);
|
|
}
|
|
|
|
static const struct of_device_id qcom_ppe_of_match[] = {
|
|
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.h
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h
|
|
@@ -20,6 +20,7 @@ struct dentry;
|
|
* @clk_rate: PPE clock rate.
|
|
* @num_ports: Number of PPE ports.
|
|
* @debugfs_root: PPE debug root entry.
|
|
+ * @ports: PPE MAC ports.
|
|
* @num_icc_paths: Number of interconnect paths.
|
|
* @icc_paths: Interconnect path array.
|
|
*
|
|
@@ -33,6 +34,7 @@ struct ppe_device {
|
|
unsigned long clk_rate;
|
|
unsigned int num_ports;
|
|
struct dentry *debugfs_root;
|
|
+ struct ppe_ports *ports;
|
|
unsigned int num_icc_paths;
|
|
struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths);
|
|
};
|
|
--- /dev/null
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
|
|
@@ -0,0 +1,728 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-only
|
|
+/*
|
|
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ */
|
|
+
|
|
+/* PPE Port MAC initialization and PPE port MAC functions. */
|
|
+
|
|
+#include <linux/clk.h>
|
|
+#include <linux/of_net.h>
|
|
+#include <linux/pcs/pcs-qcom-ipq-uniphy.h>
|
|
+#include <linux/phylink.h>
|
|
+#include <linux/reset.h>
|
|
+#include <linux/regmap.h>
|
|
+#include <linux/rtnetlink.h>
|
|
+
|
|
+#include "ppe.h"
|
|
+#include "ppe_port.h"
|
|
+#include "ppe_regs.h"
|
|
+
|
|
+/* PPE MAC max frame size which including 4bytes FCS */
|
|
+#define PPE_PORT_MAC_MAX_FRAME_SIZE 0x3000
|
|
+
|
|
+/* PPE BM port start for PPE MAC ports */
|
|
+#define PPE_BM_PORT_MAC_START 7
|
|
+
|
|
+/* PPE port clock and reset name */
|
|
+static const char * const ppe_port_clk_rst_name[] = {
|
|
+ [PPE_PORT_CLK_RST_MAC] = "port_mac",
|
|
+ [PPE_PORT_CLK_RST_RX] = "port_rx",
|
|
+ [PPE_PORT_CLK_RST_TX] = "port_tx",
|
|
+};
|
|
+
|
|
+/* PPE port and MAC reset */
|
|
+static int ppe_port_mac_reset(struct ppe_port *ppe_port)
|
|
+{
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ int ret;
|
|
+
|
|
+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+
|
|
+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_RX]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+
|
|
+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_TX]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+
|
|
+ /* 150ms delay is required by hardware to reset PPE port and MAC */
|
|
+ msleep(150);
|
|
+
|
|
+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+
|
|
+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_RX]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+
|
|
+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_TX]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+
|
|
+ return ret;
|
|
+
|
|
+error:
|
|
+ dev_err(ppe_dev->dev, "%s: port %d reset fail %d\n",
|
|
+ __func__, ppe_port->port_id, ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* PPE port MAC configuration for phylink */
|
|
+static void ppe_port_mac_config(struct phylink_config *config,
|
|
+ unsigned int mode,
|
|
+ const struct phylink_link_state *state)
|
|
+{
|
|
+ struct ppe_port *ppe_port = container_of(config, struct ppe_port,
|
|
+ phylink_config);
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ int port = ppe_port->port_id;
|
|
+ enum ppe_mac_type mac_type;
|
|
+ u32 val, mask;
|
|
+ int ret;
|
|
+
|
|
+ switch (state->interface) {
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
+ case PHY_INTERFACE_MODE_USXGMII:
|
|
+ case PHY_INTERFACE_MODE_10GBASER:
|
|
+ case PHY_INTERFACE_MODE_10G_QXGMII:
|
|
+ mac_type = PPE_MAC_TYPE_XGMAC;
|
|
+ break;
|
|
+ case PHY_INTERFACE_MODE_QSGMII:
|
|
+ case PHY_INTERFACE_MODE_PSGMII:
|
|
+ case PHY_INTERFACE_MODE_SGMII:
|
|
+ case PHY_INTERFACE_MODE_1000BASEX:
|
|
+ mac_type = PPE_MAC_TYPE_GMAC;
|
|
+ break;
|
|
+ default:
|
|
+ dev_err(ppe_dev->dev, "%s: Unsupport interface %s\n",
|
|
+ __func__, phy_modes(state->interface));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* Reset Port MAC for GMAC */
|
|
+ if (mac_type == PPE_MAC_TYPE_GMAC) {
|
|
+ ret = ppe_port_mac_reset(ppe_port);
|
|
+ if (ret)
|
|
+ goto err_mac_config;
|
|
+ }
|
|
+
|
|
+ /* Port mux to select GMAC or XGMAC */
|
|
+ mask = PPE_PORT_SEL_XGMAC(port);
|
|
+ val = mac_type == PPE_MAC_TYPE_GMAC ? 0 : mask;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap,
|
|
+ PPE_PORT_MUX_CTRL_ADDR,
|
|
+ mask, val);
|
|
+ if (ret)
|
|
+ goto err_mac_config;
|
|
+
|
|
+ ppe_port->mac_type = mac_type;
|
|
+
|
|
+ return;
|
|
+
|
|
+err_mac_config:
|
|
+ dev_err(ppe_dev->dev, "%s: port %d MAC config fail %d\n",
|
|
+ __func__, port, ret);
|
|
+}
|
|
+
|
|
+/* PPE port GMAC link up configuration */
|
|
+static int ppe_port_gmac_link_up(struct ppe_port *ppe_port, int speed,
|
|
+ int duplex, bool tx_pause, bool rx_pause)
|
|
+{
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ int ret, port = ppe_port->port_id;
|
|
+ u32 reg, val;
|
|
+
|
|
+ /* Set GMAC speed */
|
|
+ switch (speed) {
|
|
+ case SPEED_1000:
|
|
+ val = GMAC_SPEED_1000;
|
|
+ break;
|
|
+ case SPEED_100:
|
|
+ val = GMAC_SPEED_100;
|
|
+ break;
|
|
+ case SPEED_10:
|
|
+ val = GMAC_SPEED_10;
|
|
+ break;
|
|
+ default:
|
|
+ dev_err(ppe_dev->dev, "%s: Invalid GMAC speed %s\n",
|
|
+ __func__, phy_speed_to_str(speed));
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ reg = PPE_PORT_GMAC_ADDR(port);
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_SPEED_ADDR,
|
|
+ GMAC_SPEED_M, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* Set duplex, flow control and enable GMAC */
|
|
+ val = GMAC_TRXEN;
|
|
+ if (duplex == DUPLEX_FULL)
|
|
+ val |= GMAC_DUPLEX_FULL;
|
|
+ if (tx_pause)
|
|
+ val |= GMAC_TXFCEN;
|
|
+ if (rx_pause)
|
|
+ val |= GMAC_RXFCEN;
|
|
+
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_ENABLE_ADDR,
|
|
+ GMAC_ENABLE_ALL, val);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* PPE port XGMAC link up configuration */
|
|
+static int ppe_port_xgmac_link_up(struct ppe_port *ppe_port,
|
|
+ phy_interface_t interface,
|
|
+ int speed, int duplex,
|
|
+ bool tx_pause, bool rx_pause)
|
|
+{
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ int ret, port = ppe_port->port_id;
|
|
+ u32 reg, val;
|
|
+
|
|
+ /* Set XGMAC TX speed and enable TX */
|
|
+ switch (speed) {
|
|
+ case SPEED_10000:
|
|
+ if (interface == PHY_INTERFACE_MODE_USXGMII)
|
|
+ val = XGMAC_SPEED_10000_USXGMII;
|
|
+ else
|
|
+ val = XGMAC_SPEED_10000;
|
|
+ break;
|
|
+ case SPEED_5000:
|
|
+ val = XGMAC_SPEED_5000;
|
|
+ break;
|
|
+ case SPEED_2500:
|
|
+ if (interface == PHY_INTERFACE_MODE_USXGMII ||
|
|
+ interface == PHY_INTERFACE_MODE_10G_QXGMII)
|
|
+ val = XGMAC_SPEED_2500_USXGMII;
|
|
+ else
|
|
+ val = XGMAC_SPEED_2500;
|
|
+ break;
|
|
+ case SPEED_1000:
|
|
+ val = XGMAC_SPEED_1000;
|
|
+ break;
|
|
+ case SPEED_100:
|
|
+ val = XGMAC_SPEED_100;
|
|
+ break;
|
|
+ case SPEED_10:
|
|
+ val = XGMAC_SPEED_10;
|
|
+ break;
|
|
+ default:
|
|
+ dev_err(ppe_dev->dev, "%s: Invalid XGMAC speed %s\n",
|
|
+ __func__, phy_speed_to_str(speed));
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ reg = PPE_PORT_XGMAC_ADDR(port);
|
|
+ val |= XGMAC_TXEN;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_CONFIG_ADDR,
|
|
+ XGMAC_SPEED_M | XGMAC_TXEN, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* Set XGMAC TX flow control */
|
|
+ val = FIELD_PREP(XGMAC_PAUSE_TIME_M, FIELD_MAX(XGMAC_PAUSE_TIME_M));
|
|
+ val |= tx_pause ? XGMAC_TXFCEN : 0;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_FLOW_CTRL_ADDR,
|
|
+ XGMAC_PAUSE_TIME_M | XGMAC_TXFCEN, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* Set XGMAC RX flow control */
|
|
+ val = rx_pause ? XGMAC_RXFCEN : 0;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_FLOW_CTRL_ADDR,
|
|
+ XGMAC_RXFCEN, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* Enable XGMAC RX*/
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_CONFIG_ADDR,
|
|
+ XGMAC_RXEN, XGMAC_RXEN);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* PPE port MAC link up configuration for phylink */
|
|
+static void ppe_port_mac_link_up(struct phylink_config *config,
|
|
+ struct phy_device *phy,
|
|
+ unsigned int mode,
|
|
+ phy_interface_t interface,
|
|
+ int speed, int duplex,
|
|
+ bool tx_pause, bool rx_pause)
|
|
+{
|
|
+ struct ppe_port *ppe_port = container_of(config, struct ppe_port,
|
|
+ phylink_config);
|
|
+ enum ppe_mac_type mac_type = ppe_port->mac_type;
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ int ret, port = ppe_port->port_id;
|
|
+ u32 reg, val;
|
|
+
|
|
+ if (mac_type == PPE_MAC_TYPE_GMAC)
|
|
+ ret = ppe_port_gmac_link_up(ppe_port,
|
|
+ speed, duplex, tx_pause, rx_pause);
|
|
+ else
|
|
+ ret = ppe_port_xgmac_link_up(ppe_port, interface,
|
|
+ speed, duplex, tx_pause, rx_pause);
|
|
+ if (ret)
|
|
+ goto err_port_mac_link_up;
|
|
+
|
|
+ /* Set PPE port BM flow control */
|
|
+ reg = PPE_BM_PORT_FC_MODE_ADDR +
|
|
+ PPE_BM_PORT_FC_MODE_INC * (port + PPE_BM_PORT_MAC_START);
|
|
+ val = tx_pause ? PPE_BM_PORT_FC_MODE_EN : 0;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg,
|
|
+ PPE_BM_PORT_FC_MODE_EN, val);
|
|
+ if (ret)
|
|
+ goto err_port_mac_link_up;
|
|
+
|
|
+ /* Enable PPE port TX */
|
|
+ reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg,
|
|
+ PPE_PORT_BRIDGE_TXMAC_EN,
|
|
+ PPE_PORT_BRIDGE_TXMAC_EN);
|
|
+ if (ret)
|
|
+ goto err_port_mac_link_up;
|
|
+
|
|
+ return;
|
|
+
|
|
+err_port_mac_link_up:
|
|
+ dev_err(ppe_dev->dev, "%s: port %d link up fail %d\n",
|
|
+ __func__, port, ret);
|
|
+}
|
|
+
|
|
+/* PPE port MAC link down configuration for phylink */
|
|
+static void ppe_port_mac_link_down(struct phylink_config *config,
|
|
+ unsigned int mode,
|
|
+ phy_interface_t interface)
|
|
+{
|
|
+ struct ppe_port *ppe_port = container_of(config, struct ppe_port,
|
|
+ phylink_config);
|
|
+ enum ppe_mac_type mac_type = ppe_port->mac_type;
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ int ret, port = ppe_port->port_id;
|
|
+ u32 reg;
|
|
+
|
|
+ /* Disable PPE port TX */
|
|
+ reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg,
|
|
+ PPE_PORT_BRIDGE_TXMAC_EN, 0);
|
|
+ if (ret)
|
|
+ goto err_port_mac_link_down;
|
|
+
|
|
+ /* Disable PPE MAC */
|
|
+ if (mac_type == PPE_MAC_TYPE_GMAC) {
|
|
+ reg = PPE_PORT_GMAC_ADDR(port) + GMAC_ENABLE_ADDR;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg, GMAC_TRXEN, 0);
|
|
+ if (ret)
|
|
+ goto err_port_mac_link_down;
|
|
+ } else {
|
|
+ reg = PPE_PORT_XGMAC_ADDR(port);
|
|
+ ret = regmap_update_bits(ppe_dev->regmap,
|
|
+ reg + XGMAC_RX_CONFIG_ADDR,
|
|
+ XGMAC_RXEN, 0);
|
|
+ if (ret)
|
|
+ goto err_port_mac_link_down;
|
|
+
|
|
+ ret = regmap_update_bits(ppe_dev->regmap,
|
|
+ reg + XGMAC_TX_CONFIG_ADDR,
|
|
+ XGMAC_TXEN, 0);
|
|
+ if (ret)
|
|
+ goto err_port_mac_link_down;
|
|
+ }
|
|
+
|
|
+ return;
|
|
+
|
|
+err_port_mac_link_down:
|
|
+ dev_err(ppe_dev->dev, "%s: port %d link down fail %d\n",
|
|
+ __func__, port, ret);
|
|
+}
|
|
+
|
|
+/* PPE port MAC PCS selection for phylink */
|
|
+static
|
|
+struct phylink_pcs *ppe_port_mac_select_pcs(struct phylink_config *config,
|
|
+ phy_interface_t interface)
|
|
+{
|
|
+ struct ppe_port *ppe_port = container_of(config, struct ppe_port,
|
|
+ phylink_config);
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ int ret, port = ppe_port->port_id;
|
|
+ u32 val;
|
|
+
|
|
+ /* PPE port5 can connects with PCS0 or PCS1. In PSGMII
|
|
+ * mode, it selects PCS0; otherwise, it selects PCS1.
|
|
+ */
|
|
+ if (port == 5) {
|
|
+ val = interface == PHY_INTERFACE_MODE_PSGMII ?
|
|
+ 0 : PPE_PORT5_SEL_PCS1;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap,
|
|
+ PPE_PORT_MUX_CTRL_ADDR,
|
|
+ PPE_PORT5_SEL_PCS1, val);
|
|
+ if (ret) {
|
|
+ dev_err(ppe_dev->dev, "%s: port5 select PCS fail %d\n",
|
|
+ __func__, ret);
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ppe_port->pcs;
|
|
+}
|
|
+
|
|
+static const struct phylink_mac_ops ppe_phylink_ops = {
|
|
+ .mac_config = ppe_port_mac_config,
|
|
+ .mac_link_up = ppe_port_mac_link_up,
|
|
+ .mac_link_down = ppe_port_mac_link_down,
|
|
+ .mac_select_pcs = ppe_port_mac_select_pcs,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * ppe_port_phylink_setup() - Set phylink instance for the given PPE port
|
|
+ * @ppe_port: PPE port
|
|
+ * @netdev: Netdevice
|
|
+ *
|
|
+ * Description: Wrapper function to help setup phylink for the PPE port
|
|
+ * specified by @ppe_port and associated with the net device @netdev.
|
|
+ *
|
|
+ * Return: 0 upon success or a negative error upon failure.
|
|
+ */
|
|
+int ppe_port_phylink_setup(struct ppe_port *ppe_port, struct net_device *netdev)
|
|
+{
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ struct device_node *pcs_node;
|
|
+ int ret;
|
|
+
|
|
+ /* Create PCS */
|
|
+ pcs_node = of_parse_phandle(ppe_port->np, "pcs-handle", 0);
|
|
+ if (!pcs_node)
|
|
+ return -ENODEV;
|
|
+
|
|
+ ppe_port->pcs = ipq_unipcs_create(pcs_node);
|
|
+ of_node_put(pcs_node);
|
|
+ if (IS_ERR(ppe_port->pcs)) {
|
|
+ dev_err(ppe_dev->dev, "%s: port %d failed to create PCS\n",
|
|
+ __func__, ppe_port->port_id);
|
|
+ return PTR_ERR(ppe_port->pcs);
|
|
+ }
|
|
+
|
|
+ /* Port phylink capability */
|
|
+ ppe_port->phylink_config.dev = &netdev->dev;
|
|
+ ppe_port->phylink_config.type = PHYLINK_NETDEV;
|
|
+ ppe_port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE |
|
|
+ MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 |
|
|
+ MAC_2500FD | MAC_5000FD | MAC_10000FD;
|
|
+ __set_bit(PHY_INTERFACE_MODE_QSGMII,
|
|
+ ppe_port->phylink_config.supported_interfaces);
|
|
+ __set_bit(PHY_INTERFACE_MODE_PSGMII,
|
|
+ ppe_port->phylink_config.supported_interfaces);
|
|
+ __set_bit(PHY_INTERFACE_MODE_SGMII,
|
|
+ ppe_port->phylink_config.supported_interfaces);
|
|
+ __set_bit(PHY_INTERFACE_MODE_1000BASEX,
|
|
+ ppe_port->phylink_config.supported_interfaces);
|
|
+ __set_bit(PHY_INTERFACE_MODE_2500BASEX,
|
|
+ ppe_port->phylink_config.supported_interfaces);
|
|
+ __set_bit(PHY_INTERFACE_MODE_USXGMII,
|
|
+ ppe_port->phylink_config.supported_interfaces);
|
|
+ __set_bit(PHY_INTERFACE_MODE_10GBASER,
|
|
+ ppe_port->phylink_config.supported_interfaces);
|
|
+ __set_bit(PHY_INTERFACE_MODE_10G_QXGMII,
|
|
+ ppe_port->phylink_config.supported_interfaces);
|
|
+
|
|
+ /* Create phylink */
|
|
+ ppe_port->phylink = phylink_create(&ppe_port->phylink_config,
|
|
+ of_fwnode_handle(ppe_port->np),
|
|
+ ppe_port->interface,
|
|
+ &ppe_phylink_ops);
|
|
+ if (IS_ERR(ppe_port->phylink)) {
|
|
+ dev_err(ppe_dev->dev, "%s: port %d failed to create phylink\n",
|
|
+ __func__, ppe_port->port_id);
|
|
+ ret = PTR_ERR(ppe_port->phylink);
|
|
+ goto err_free_pcs;
|
|
+ }
|
|
+
|
|
+ /* Connect phylink */
|
|
+ ret = phylink_of_phy_connect(ppe_port->phylink, ppe_port->np, 0);
|
|
+ if (ret) {
|
|
+ dev_err(ppe_dev->dev, "%s: port %d failed to connect phylink\n",
|
|
+ __func__, ppe_port->port_id);
|
|
+ goto err_free_phylink;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_free_phylink:
|
|
+ phylink_destroy(ppe_port->phylink);
|
|
+ ppe_port->phylink = NULL;
|
|
+err_free_pcs:
|
|
+ ipq_unipcs_destroy(ppe_port->pcs);
|
|
+ ppe_port->pcs = NULL;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * ppe_port_phylink_destroy() - Destroy phylink instance for the given PPE port
|
|
+ * @ppe_port: PPE port
|
|
+ *
|
|
+ * Description: Wrapper function to help destroy phylink for the PPE port
|
|
+ * specified by @ppe_port.
|
|
+ */
|
|
+void ppe_port_phylink_destroy(struct ppe_port *ppe_port)
|
|
+{
|
|
+ /* Destroy phylink */
|
|
+ if (ppe_port->phylink) {
|
|
+ rtnl_lock();
|
|
+ phylink_disconnect_phy(ppe_port->phylink);
|
|
+ rtnl_unlock();
|
|
+ phylink_destroy(ppe_port->phylink);
|
|
+ ppe_port->phylink = NULL;
|
|
+ }
|
|
+
|
|
+ /* Destroy PCS */
|
|
+ if (ppe_port->pcs) {
|
|
+ ipq_unipcs_destroy(ppe_port->pcs);
|
|
+ ppe_port->pcs = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* PPE port clock initialization */
|
|
+static int ppe_port_clock_init(struct ppe_port *ppe_port)
|
|
+{
|
|
+ struct device_node *port_node = ppe_port->np;
|
|
+ struct reset_control *rstc;
|
|
+ struct clk *clk;
|
|
+ int i, j, ret;
|
|
+
|
|
+ for (i = 0; i < PPE_PORT_CLK_RST_MAX; i++) {
|
|
+ /* Get PPE port resets which will be used to reset PPE
|
|
+ * port and MAC.
|
|
+ */
|
|
+ rstc = of_reset_control_get_exclusive(port_node,
|
|
+ ppe_port_clk_rst_name[i]);
|
|
+ if (IS_ERR(rstc)) {
|
|
+ ret = PTR_ERR(rstc);
|
|
+ goto err_rst;
|
|
+ }
|
|
+
|
|
+ clk = of_clk_get_by_name(port_node, ppe_port_clk_rst_name[i]);
|
|
+ if (IS_ERR(clk)) {
|
|
+ ret = PTR_ERR(clk);
|
|
+ goto err_clk_get;
|
|
+ }
|
|
+
|
|
+ ret = clk_prepare_enable(clk);
|
|
+ if (ret)
|
|
+ goto err_clk_en;
|
|
+
|
|
+ ppe_port->clks[i] = clk;
|
|
+ ppe_port->rstcs[i] = rstc;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_clk_en:
|
|
+ clk_put(clk);
|
|
+err_clk_get:
|
|
+ reset_control_put(rstc);
|
|
+err_rst:
|
|
+ for (j = 0; j < i; j++) {
|
|
+ clk_disable_unprepare(ppe_port->clks[j]);
|
|
+ clk_put(ppe_port->clks[j]);
|
|
+ reset_control_put(ppe_port->rstcs[j]);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* PPE port clock deinitialization */
|
|
+static void ppe_port_clock_deinit(struct ppe_port *ppe_port)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < PPE_PORT_CLK_RST_MAX; i++) {
|
|
+ clk_disable_unprepare(ppe_port->clks[i]);
|
|
+ clk_put(ppe_port->clks[i]);
|
|
+ reset_control_put(ppe_port->rstcs[i]);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* PPE port MAC hardware init configuration */
|
|
+static int ppe_port_mac_hw_init(struct ppe_port *ppe_port)
|
|
+{
|
|
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
|
|
+ int ret, port = ppe_port->port_id;
|
|
+ u32 reg, val;
|
|
+
|
|
+ /* GMAC RX and TX are initialized as disabled */
|
|
+ reg = PPE_PORT_GMAC_ADDR(port);
|
|
+ ret = regmap_update_bits(ppe_dev->regmap,
|
|
+ reg + GMAC_ENABLE_ADDR, GMAC_TRXEN, 0);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* GMAC max frame size configuration */
|
|
+ val = FIELD_PREP(GMAC_JUMBO_SIZE_M, PPE_PORT_MAC_MAX_FRAME_SIZE);
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_JUMBO_SIZE_ADDR,
|
|
+ GMAC_JUMBO_SIZE_M, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ val = FIELD_PREP(GMAC_MAXFRAME_SIZE_M, PPE_PORT_MAC_MAX_FRAME_SIZE);
|
|
+ val |= FIELD_PREP(GMAC_TX_THD_M, 0x1);
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_CTRL_ADDR,
|
|
+ GMAC_CTRL_MASK, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ val = FIELD_PREP(GMAC_HIGH_IPG_M, 0xc);
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_DBG_CTRL_ADDR,
|
|
+ GMAC_HIGH_IPG_M, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* Enable and reset GMAC MIB counters and set as read clear
|
|
+ * mode, the GMAC MIB counters will be cleared after reading.
|
|
+ */
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR,
|
|
+ GMAC_MIB_CTRL_MASK, GMAC_MIB_CTRL_MASK);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR,
|
|
+ GMAC_MIB_RST, 0);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* XGMAC RX and TX disabled and max frame size configuration */
|
|
+ reg = PPE_PORT_XGMAC_ADDR(port);
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_CONFIG_ADDR,
|
|
+ XGMAC_TXEN | XGMAC_JD, XGMAC_JD);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ val = FIELD_PREP(XGMAC_GPSL_M, PPE_PORT_MAC_MAX_FRAME_SIZE);
|
|
+ val |= XGMAC_GPSLEN;
|
|
+ val |= XGMAC_CST;
|
|
+ val |= XGMAC_ACS;
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_CONFIG_ADDR,
|
|
+ XGMAC_RX_CONFIG_MASK, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_WD_TIMEOUT_ADDR,
|
|
+ XGMAC_WD_TIMEOUT_MASK, XGMAC_WD_TIMEOUT_VAL);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_PKT_FILTER_ADDR,
|
|
+ XGMAC_PKT_FILTER_MASK, XGMAC_PKT_FILTER_VAL);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* Enable and reset XGMAC MIB counters */
|
|
+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_MMC_CTRL_ADDR,
|
|
+ XGMAC_MCF | XGMAC_CNTRST, XGMAC_CNTRST);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * ppe_port_mac_init() - Initialization of PPE ports for the PPE device
|
|
+ * @ppe_dev: PPE device
|
|
+ *
|
|
+ * Description: Initialize the PPE MAC ports on the PPE device specified
|
|
+ * by @ppe_dev.
|
|
+ *
|
|
+ * Return: 0 upon success or a negative error upon failure.
|
|
+ */
|
|
+int ppe_port_mac_init(struct ppe_device *ppe_dev)
|
|
+{
|
|
+ struct device_node *ports_node, *port_node;
|
|
+ int port, num, ret, j, i = 0;
|
|
+ struct ppe_ports *ppe_ports;
|
|
+ phy_interface_t phy_mode;
|
|
+
|
|
+ ports_node = of_get_child_by_name(ppe_dev->dev->of_node,
|
|
+ "ethernet-ports");
|
|
+ if (!ports_node) {
|
|
+ dev_err(ppe_dev->dev, "Failed to get ports node\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ num = of_get_available_child_count(ports_node);
|
|
+
|
|
+ ppe_ports = devm_kzalloc(ppe_dev->dev,
|
|
+ struct_size(ppe_ports, port, num),
|
|
+ GFP_KERNEL);
|
|
+ if (!ppe_ports) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_ports_node;
|
|
+ }
|
|
+
|
|
+ ppe_dev->ports = ppe_ports;
|
|
+ ppe_ports->num = num;
|
|
+
|
|
+ for_each_available_child_of_node(ports_node, port_node) {
|
|
+ ret = of_property_read_u32(port_node, "reg", &port);
|
|
+ if (ret) {
|
|
+ dev_err(ppe_dev->dev, "Failed to get port id\n");
|
|
+ goto err_port_node;
|
|
+ }
|
|
+
|
|
+ ret = of_get_phy_mode(port_node, &phy_mode);
|
|
+ if (ret) {
|
|
+ dev_err(ppe_dev->dev, "Failed to get phy mode\n");
|
|
+ goto err_port_node;
|
|
+ }
|
|
+
|
|
+ ppe_ports->port[i].ppe_dev = ppe_dev;
|
|
+ ppe_ports->port[i].port_id = port;
|
|
+ ppe_ports->port[i].np = port_node;
|
|
+ ppe_ports->port[i].interface = phy_mode;
|
|
+
|
|
+ ret = ppe_port_clock_init(&ppe_ports->port[i]);
|
|
+ if (ret) {
|
|
+ dev_err(ppe_dev->dev, "Failed to initialize port clocks\n");
|
|
+ goto err_port_clk;
|
|
+ }
|
|
+
|
|
+ ret = ppe_port_mac_hw_init(&ppe_ports->port[i]);
|
|
+ if (ret) {
|
|
+ dev_err(ppe_dev->dev, "Failed to initialize MAC hardware\n");
|
|
+ goto err_port_node;
|
|
+ }
|
|
+
|
|
+ i++;
|
|
+ }
|
|
+
|
|
+ of_node_put(ports_node);
|
|
+ return 0;
|
|
+
|
|
+err_port_clk:
|
|
+ for (j = 0; j < i; j++)
|
|
+ ppe_port_clock_deinit(&ppe_ports->port[j]);
|
|
+err_port_node:
|
|
+ of_node_put(port_node);
|
|
+err_ports_node:
|
|
+ of_node_put(ports_node);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * ppe_port_mac_deinit() - Deinitialization of PPE ports for the PPE device
|
|
+ * @ppe_dev: PPE device
|
|
+ *
|
|
+ * Description: Deinitialize the PPE MAC ports on the PPE device specified
|
|
+ * by @ppe_dev.
|
|
+ */
|
|
+void ppe_port_mac_deinit(struct ppe_device *ppe_dev)
|
|
+{
|
|
+ struct ppe_port *ppe_port;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ppe_dev->ports->num; i++) {
|
|
+ ppe_port = &ppe_dev->ports->port[i];
|
|
+ ppe_port_clock_deinit(ppe_port);
|
|
+ }
|
|
+}
|
|
--- /dev/null
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h
|
|
@@ -0,0 +1,76 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0-only
|
|
+ *
|
|
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __PPE_PORT_H__
|
|
+#define __PPE_PORT_H__
|
|
+
|
|
+#include <linux/phylink.h>
|
|
+
|
|
+/**
|
|
+ * enum ppe_port_clk_rst_type - PPE port clock and reset ID type
|
|
+ * @PPE_PORT_CLK_RST_MAC: The clock and reset ID for port MAC
|
|
+ * @PPE_PORT_CLK_RST_RX: The clock and reset ID for port receive path
|
|
+ * @PPE_PORT_CLK_RST_TX: The clock and reset for port transmit path
|
|
+ * @PPE_PORT_CLK_RST_MAX: The maximum of port clock and reset
|
|
+ */
|
|
+enum ppe_port_clk_rst_type {
|
|
+ PPE_PORT_CLK_RST_MAC,
|
|
+ PPE_PORT_CLK_RST_RX,
|
|
+ PPE_PORT_CLK_RST_TX,
|
|
+ PPE_PORT_CLK_RST_MAX,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum ppe_mac_type - PPE MAC type
|
|
+ * @PPE_MAC_TYPE_GMAC: GMAC type
|
|
+ * @PPE_MAC_TYPE_XGMAC: XGMAC type
|
|
+ */
|
|
+enum ppe_mac_type {
|
|
+ PPE_MAC_TYPE_GMAC,
|
|
+ PPE_MAC_TYPE_XGMAC,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct ppe_port - Private data for each PPE port
|
|
+ * @phylink: Linux phylink instance
|
|
+ * @phylink_config: Linux phylink configurations
|
|
+ * @pcs: Linux phylink PCS instance
|
|
+ * @np: Port device tree node
|
|
+ * @ppe_dev: Back pointer to PPE device private data
|
|
+ * @interface: Port interface mode
|
|
+ * @mac_type: Port MAC type, GMAC or XGMAC
|
|
+ * @port_id: Port ID
|
|
+ * @clks: Port clocks
|
|
+ * @rstcs: Port resets
|
|
+ */
|
|
+struct ppe_port {
|
|
+ struct phylink *phylink;
|
|
+ struct phylink_config phylink_config;
|
|
+ struct phylink_pcs *pcs;
|
|
+ struct device_node *np;
|
|
+ struct ppe_device *ppe_dev;
|
|
+ phy_interface_t interface;
|
|
+ enum ppe_mac_type mac_type;
|
|
+ int port_id;
|
|
+ struct clk *clks[PPE_PORT_CLK_RST_MAX];
|
|
+ struct reset_control *rstcs[PPE_PORT_CLK_RST_MAX];
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct ppe_ports - Array of PPE ports
|
|
+ * @num: Number of PPE ports
|
|
+ * @port: Each PPE port private data
|
|
+ */
|
|
+struct ppe_ports {
|
|
+ unsigned int num;
|
|
+ struct ppe_port port[] __counted_by(num);
|
|
+};
|
|
+
|
|
+int ppe_port_mac_init(struct ppe_device *ppe_dev);
|
|
+void ppe_port_mac_deinit(struct ppe_device *ppe_dev);
|
|
+int ppe_port_phylink_setup(struct ppe_port *ppe_port,
|
|
+ struct net_device *netdev);
|
|
+void ppe_port_phylink_destroy(struct ppe_port *ppe_port);
|
|
+#endif
|
|
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
|
@@ -7,6 +7,17 @@
|
|
#ifndef __PPE_REGS_H__
|
|
#define __PPE_REGS_H__
|
|
|
|
+/* PPE port mux select control register */
|
|
+#define PPE_PORT_MUX_CTRL_ADDR 0x10
|
|
+#define PPE_PORT6_SEL_XGMAC BIT(13)
|
|
+#define PPE_PORT5_SEL_XGMAC BIT(12)
|
|
+#define PPE_PORT4_SEL_XGMAC BIT(11)
|
|
+#define PPE_PORT3_SEL_XGMAC BIT(10)
|
|
+#define PPE_PORT2_SEL_XGMAC BIT(9)
|
|
+#define PPE_PORT1_SEL_XGMAC BIT(8)
|
|
+#define PPE_PORT5_SEL_PCS1 BIT(4)
|
|
+#define PPE_PORT_SEL_XGMAC(x) (BIT(8) << ((x) - 1))
|
|
+
|
|
/* There are 15 BM ports and 4 BM groups supported by PPE,
|
|
* BM port (0-7) is matched to EDMA port 0, BM port (8-13) is matched
|
|
* to PPE physical port 1-6, BM port 14 is matched to EIP.
|
|
@@ -545,4 +556,116 @@
|
|
#define PPE_ENQ_OPR_TBL_INC 0x10
|
|
#define PPE_ENQ_OPR_TBL_ENQ_DISABLE BIT(0)
|
|
|
|
+/* PPE GMAC and XGMAC register base address */
|
|
+#define PPE_PORT_GMAC_ADDR(x) (0x001000 + ((x) - 1) * 0x200)
|
|
+#define PPE_PORT_XGMAC_ADDR(x) (0x500000 + ((x) - 1) * 0x4000)
|
|
+
|
|
+/* GMAC enable register */
|
|
+#define GMAC_ENABLE_ADDR 0x0
|
|
+#define GMAC_TXFCEN BIT(6)
|
|
+#define GMAC_RXFCEN BIT(5)
|
|
+#define GMAC_DUPLEX_FULL BIT(4)
|
|
+#define GMAC_TXEN BIT(1)
|
|
+#define GMAC_RXEN BIT(0)
|
|
+
|
|
+#define GMAC_TRXEN \
|
|
+ (GMAC_TXEN | GMAC_RXEN)
|
|
+#define GMAC_ENABLE_ALL \
|
|
+ (GMAC_TXFCEN | GMAC_RXFCEN | GMAC_DUPLEX_FULL | GMAC_TXEN | GMAC_RXEN)
|
|
+
|
|
+/* GMAC speed register */
|
|
+#define GMAC_SPEED_ADDR 0x4
|
|
+#define GMAC_SPEED_M GENMASK(1, 0)
|
|
+#define GMAC_SPEED_10 0
|
|
+#define GMAC_SPEED_100 1
|
|
+#define GMAC_SPEED_1000 2
|
|
+
|
|
+/* GMAC control register */
|
|
+#define GMAC_CTRL_ADDR 0x18
|
|
+#define GMAC_TX_THD_M GENMASK(27, 24)
|
|
+#define GMAC_MAXFRAME_SIZE_M GENMASK(21, 8)
|
|
+#define GMAC_CRS_SEL BIT(6)
|
|
+
|
|
+#define GMAC_CTRL_MASK \
|
|
+ (GMAC_TX_THD_M | GMAC_MAXFRAME_SIZE_M | GMAC_CRS_SEL)
|
|
+
|
|
+/* GMAC debug control register */
|
|
+#define GMAC_DBG_CTRL_ADDR 0x1c
|
|
+#define GMAC_HIGH_IPG_M GENMASK(15, 8)
|
|
+
|
|
+/* GMAC jumbo size register */
|
|
+#define GMAC_JUMBO_SIZE_ADDR 0x30
|
|
+#define GMAC_JUMBO_SIZE_M GENMASK(13, 0)
|
|
+
|
|
+/* GMAC MIB control register */
|
|
+#define GMAC_MIB_CTRL_ADDR 0x34
|
|
+#define GMAC_MIB_RD_CLR BIT(2)
|
|
+#define GMAC_MIB_RST BIT(1)
|
|
+#define GMAC_MIB_EN BIT(0)
|
|
+
|
|
+#define GMAC_MIB_CTRL_MASK \
|
|
+ (GMAC_MIB_RD_CLR | GMAC_MIB_RST | GMAC_MIB_EN)
|
|
+
|
|
+/* XGMAC TX configuration register */
|
|
+#define XGMAC_TX_CONFIG_ADDR 0x0
|
|
+#define XGMAC_SPEED_M GENMASK(31, 29)
|
|
+#define XGMAC_SPEED_10000_USXGMII FIELD_PREP(XGMAC_SPEED_M, 4)
|
|
+#define XGMAC_SPEED_10000 FIELD_PREP(XGMAC_SPEED_M, 0)
|
|
+#define XGMAC_SPEED_5000 FIELD_PREP(XGMAC_SPEED_M, 5)
|
|
+#define XGMAC_SPEED_2500_USXGMII FIELD_PREP(XGMAC_SPEED_M, 6)
|
|
+#define XGMAC_SPEED_2500 FIELD_PREP(XGMAC_SPEED_M, 2)
|
|
+#define XGMAC_SPEED_1000 FIELD_PREP(XGMAC_SPEED_M, 3)
|
|
+#define XGMAC_SPEED_100 XGMAC_SPEED_1000
|
|
+#define XGMAC_SPEED_10 XGMAC_SPEED_1000
|
|
+#define XGMAC_JD BIT(16)
|
|
+#define XGMAC_TXEN BIT(0)
|
|
+
|
|
+/* XGMAC RX configuration register */
|
|
+#define XGMAC_RX_CONFIG_ADDR 0x4
|
|
+#define XGMAC_GPSL_M GENMASK(29, 16)
|
|
+#define XGMAC_WD BIT(7)
|
|
+#define XGMAC_GPSLEN BIT(6)
|
|
+#define XGMAC_CST BIT(2)
|
|
+#define XGMAC_ACS BIT(1)
|
|
+#define XGMAC_RXEN BIT(0)
|
|
+
|
|
+#define XGMAC_RX_CONFIG_MASK \
|
|
+ (XGMAC_GPSL_M | XGMAC_WD | XGMAC_GPSLEN | XGMAC_CST | \
|
|
+ XGMAC_ACS | XGMAC_RXEN)
|
|
+
|
|
+/* XGMAC packet filter register */
|
|
+#define XGMAC_PKT_FILTER_ADDR 0x8
|
|
+#define XGMAC_RA BIT(31)
|
|
+#define XGMAC_PCF_M GENMASK(7, 6)
|
|
+#define XGMAC_PR BIT(0)
|
|
+
|
|
+#define XGMAC_PKT_FILTER_MASK \
|
|
+ (XGMAC_RA | XGMAC_PCF_M | XGMAC_PR)
|
|
+#define XGMAC_PKT_FILTER_VAL \
|
|
+ (XGMAC_RA | XGMAC_PR | FIELD_PREP(XGMAC_PCF_M, 0x2))
|
|
+
|
|
+/* XGMAC watchdog timeout register */
|
|
+#define XGMAC_WD_TIMEOUT_ADDR 0xc
|
|
+#define XGMAC_PWE BIT(8)
|
|
+#define XGMAC_WTO_M GENMASK(3, 0)
|
|
+
|
|
+#define XGMAC_WD_TIMEOUT_MASK \
|
|
+ (XGMAC_PWE | XGMAC_WTO_M)
|
|
+#define XGMAC_WD_TIMEOUT_VAL \
|
|
+ (XGMAC_PWE | FIELD_PREP(XGMAC_WTO_M, 0xb))
|
|
+
|
|
+/* XGMAC TX flow control register */
|
|
+#define XGMAC_TX_FLOW_CTRL_ADDR 0x70
|
|
+#define XGMAC_PAUSE_TIME_M GENMASK(31, 16)
|
|
+#define XGMAC_TXFCEN BIT(1)
|
|
+
|
|
+/* XGMAC RX flow control register */
|
|
+#define XGMAC_RX_FLOW_CTRL_ADDR 0x90
|
|
+#define XGMAC_RXFCEN BIT(0)
|
|
+
|
|
+/* XGMAC management counters control register */
|
|
+#define XGMAC_MMC_CTRL_ADDR 0x800
|
|
+#define XGMAC_MCF BIT(3)
|
|
+#define XGMAC_CNTRST BIT(0)
|
|
+
|
|
#endif
|