git: 5d884fc07662 - main - dpaa: Split FMan port driver into distinct TX/RX
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 25 Aug 2026 03:04:35 UTC
The branch main has been updated by jhibbits:
URL: https://cgit.FreeBSD.org/src/commit/?id=5d884fc07662760a2090928e98e51dc8162389a3
commit 5d884fc07662760a2090928e98e51dc8162389a3
Author: Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2026-08-13 15:40:49 +0000
Commit: Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2026-08-25 03:03:08 +0000
dpaa: Split FMan port driver into distinct TX/RX
There are several port functions that are only for one type or the
other, so they don't make sense to be together. Splitting these up also
simplifies adding support for the Offline/Host Command ports.
---
sys/conf/files.powerpc | 2 +
sys/dev/dpaa/fman_port.c | 648 ++-----------------------------------------
sys/dev/dpaa/fman_port_rx.c | 398 ++++++++++++++++++++++++++
sys/dev/dpaa/fman_port_tx.c | 347 +++++++++++++++++++++++
sys/dev/dpaa/fman_port_var.h | 85 ++++++
5 files changed, 850 insertions(+), 630 deletions(-)
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 3623a8f15424..06b189b95edb 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -100,6 +100,8 @@ dev/dpaa/fman_keygen.c optional dpaa
dev/dpaa/fman_mdio.c optional dpaa fdt
dev/dpaa/fman_port_if.m optional dpaa
dev/dpaa/fman_port.c optional dpaa
+dev/dpaa/fman_port_rx.c optional dpaa
+dev/dpaa/fman_port_tx.c optional dpaa
dev/dpaa/fman_xmdio.c optional dpaa fdt mdio miibus
dev/dpaa/dpaa_common.c optional dpaa
dev/dpaa/if_dtsec.c optional dpaa
diff --git a/sys/dev/dpaa/fman_port.c b/sys/dev/dpaa/fman_port.c
index 833be542055e..24ed4ed3ba79 100644
--- a/sys/dev/dpaa/fman_port.c
+++ b/sys/dev/dpaa/fman_port.c
@@ -2,270 +2,61 @@
* Copyright (c) 2026 Justin Hibbits
*
* SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Shared bits of the FMan port drivers.
*/
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
+
#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
+
#include "fman.h"
-#include "fman_parser.h"
#include "fman_port.h"
+#include "fman_port_var.h"
#include "fman_if.h"
-#include "fman_port_if.h"
-
-struct fman_port_rsrc {
- uint32_t num;
- uint32_t extra;
-};
-
-#define MAX_BM_POOLS 64
-struct fman_port_softc {
- device_t sc_dev;
- struct resource *sc_mem;
- int sc_port_id;
- int sc_port_speed;
- int sc_port_type;
-
- int sc_revision_major;
- int sc_revision_minor;
-
- int sc_max_frame_length;
- int sc_bm_max_pools;
- int sc_max_port_fifo_size;
- int sc_qman_channel_id;
-
- int sc_deq_byte_count;
- int sc_deq_high_priority;
- int sc_tx_deq_pipeline_depth;
-
- int sc_default_fqid;
- int sc_err_fqid;
- int pcd_base_fqid;
- int pcd_fqs_count;
-
- int sc_max_ext_portals;
- int sc_max_sub_portals;
-
- struct fman_port_rsrc sc_open_dmas;
- struct fman_port_rsrc sc_tasks;
- struct fman_port_rsrc sc_fifo_bufs;
-
- struct fman_port_buffer_pool sc_bpools[FMAN_PORT_MAX_POOLS];
-};
-
-#define TX_10G_PORT_BASE 0x30
-#define RX_10G_PORT_BASE 0x10
-
-#define FMAN_PORT_TYPE_TX 0
-#define FMAN_PORT_TYPE_RX 1
-
-#define PORT_RX 0x01
-#define PORT_TX 0x02
-#define PORT_V3 0x04
-
-#define FMBM_RCFG 0x000
-#define BMI_PORT_CFG_EN 0x80000000
-#define FMBM_RST 0x004
-#define FMBM_RDA 0x008
-#define RDA_WOPT 0x00100000
-#define FMBM_RFP 0x00c
-#define FMBM_RFED 0x010
-#define BMI_RX_FRAME_END_CUT_SHIFT 16
-#define FMBM_RICP 0x014 /* Counts are units of 16 bytes */
-#define RICP_ICEOF_M 0x001f0000
-#define RICP_ICEOF_S 16
-#define RICP_ICIOF_M 0x00000f00
-#define RICP_ICIOF_S 8
-#define RICP_ICSZ_S 0x0000001f
-#define FMBM_RIM 0x018
-#define FMBM_REBM 0x01c
-#define REBM_BSM_M 0x01ff0000
-#define REBM_BSM_S 16
-#define REBM_BEM_M 0x000001ff
-#define FMBM_RFNE 0x020
-#define FMBM_RFCA 0x024
-#define RFCA_OR 0x80000000
-#define RFCA_COLOR 0x0c000000
-#define RFCA_SYNC 0x03000000
-#define RFCA_SYNC_REQ 0x02000000
-#define RFCA_MR 0x003f0000
-#define RFCA_MR_DEF 0x003c0000
-#define FMBM_RFPNE 0x028
-#define FMBM_RETH 0x038
-#define RETH_ETHE 0x80000000 /* Excessive Threshold Enable */
-#define FMBM_RFQID 0x060
-#define FMBM_REFQID 0x064
-#define FMBM_RFSDM 0x068
-#define FMBM_RFSEM 0x06c
-#define FMBM_RFENE 0x070
-#define FMBM_REBMPI(i) (0x100 + (4 * (i)))
-#define REBMPI_VAL 0x80000000
-#define REBMPI_ACE 0x40000000
-#define REBMPI_BPID_S 16
-#define FMBM_RSTC 0x0200
-#define RSTC_EN 0x80000000
-
-#define FMBM_TCFG 0x000
-#define FMBM_TST 0x004
-#define FMBM_TDA 0x008
-#define FMBM_TFP 0x00c
-#define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12
-#define FMBM_TFED 0x010
-#define FMBM_TICP 0x014
-#define TICP_ICEOF_M 0x001f0000
-#define TICP_ICEOF_S 16
-#define TICP_ICIOF_M 0x00000f00
-#define TICP_ICIOF_S 8
-#define TICP_ICSZ_S 0x0000001f
-#define FMBM_TFDNE 0x018
-#define FMBM_TFCA 0x01c
-#define TFCA_MR_DEF 0
-#define TFCA_ATTR_ORDER 0x80000000
-#define FMBM_TCFQID 0x020
-#define FMBM_TEFQID 0x024
-#define FMBM_TFENE 0x028
-#define FMBM_TFNE 0x070
-#define TFNE_EBD 0x80000000
-
-#define FMQM_PNC 0x400
-#define PNC_EN 0x80000000
-#define PNC_STEN 0x80000000
-#define FMQM_PNS 0x404
-#define PNS_DEQ_FD_BSY 0x20000000
-#define FMQM_PNEN 0x41c
-#define FMQM_PNDN 0x42c
-#define FMQM_PNDC 0x430
-#define QMI_DEQ_CFG_PRI 0x80000000
-#define QMI_DEQ_CFG_TYPE1 0x10000000
-#define QMI_DEQ_CFG_TYPE2 0x20000000
-#define QMI_DEQ_CFG_TYPE3 0x30000000
-#define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000
-#define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000
-#define QMI_DEQ_CFG_SP_MASK 0xf
-#define QMI_DEQ_CFG_SP_SHIFT 20
-
-#define HWP_PCAC 0xbf8
-#define HWP_PCAC_PSTOP 0x00000001
-#define HWP_HXS_PCAC_PSTAT 0x00000100
-#define HWP_HXS_SSA(x) (0x800 + x * 2 * sizeof(uint32_t))
-#define HWP_HXS_LCV(x) (0x800 + (x * 2 + 1) * sizeof(uint32_t))
-#define HWP_HXS_TCP 0xA
-#define HWP_HXS_UDP 0xB
-#define HXS_SH_PAD_REM 0x80000000
-#define HWP_HXS_COUNT 16
-
-#define PORT_MAX_FRAME_LENGTH 9600
-#define BMI_RX_ERR (FM_FD_ERR_DMA | FM_FD_ERR_FPE | \
- FM_FD_ERR_FSE | FM_FD_ERR_DIS | \
- FM_FD_ERR_EOF | FM_FD_ERR_NSS | \
- FM_FD_ERR_KSO | FM_FD_ERR_IPP | \
- FM_FD_ERR_PTE | FM_FD_ERR_PHE | \
- FM_FD_ERR_BLE)
-
-/* Default configurations */
-#define DEFAULT_RX_CUT_END_BYTES 4
-
-static struct ofw_compat_data compats[] = {
- { "fsl,fman-v2-port-rx", PORT_RX },
- { "fsl,fman-v2-port-tx", PORT_TX },
- { "fsl,fman-v3-port-rx", PORT_V3 | PORT_RX },
- { "fsl,fman-v3-port-tx", PORT_V3 | PORT_TX },
- { NULL, 0 }
-};
-
-static int
-fman_port_probe(device_t dev)
-{
- if (ofw_bus_search_compatible(dev, compats)->ocd_str == NULL)
- return (ENXIO);
-
- device_set_desc(dev, "FMan port");
-
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-fman_port_attach(device_t dev)
+int
+fman_port_attach_common(device_t dev, struct fman_port_softc *sc,
+ int port_speed)
{
- struct fman_port_softc *sc;
phandle_t node;
pcell_t cell;
- uintptr_t compat_data =
- ofw_bus_search_compatible(dev, compats)->ocd_data;
- int port_speed = 1000;
- int port_type;
- sc = device_get_softc(dev);
sc->sc_dev = dev;
node = ofw_bus_get_node(dev);
if (OF_getencprop(node, "cell-index", &cell, sizeof(cell)) < 0) {
- device_printf(dev, "No cell-index property");
+ device_printf(dev, "No cell-index property\n");
return (ENXIO);
}
-
sc->sc_port_id = cell;
sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0,
RF_ACTIVE | RF_SHAREABLE);
-
if (sc->sc_mem == NULL) {
- device_printf(dev, "failed to allocate MMIO");
+ device_printf(dev, "failed to allocate MMIO\n");
return (ENXIO);
}
FMAN_GET_REVISION(device_get_parent(dev),
&sc->sc_revision_major, &sc->sc_revision_minor);
- if ((compat_data & PORT_TX) == PORT_TX)
- port_type = FMAN_PORT_TYPE_TX;
- else
- port_type = FMAN_PORT_TYPE_RX;
-
- if ((compat_data & PORT_V3) == PORT_V3) {
- if (OF_hasprop(node, "fsl,fman-10g-port"))
- port_speed = 10000;
- } else {
- if ((compat_data & PORT_TX) &&
- sc->sc_port_id > TX_10G_PORT_BASE)
- port_speed = 10000;
- else if ((compat_data & PORT_RX) &&
- sc->sc_port_id > RX_10G_PORT_BASE)
- port_speed = 10000;
- }
-
- if (sc->sc_port_speed == 10000) {
- sc->sc_deq_high_priority = true;
- sc->sc_deq_byte_count = 0x1400;
- } else {
- sc->sc_deq_high_priority = false;
- sc->sc_deq_byte_count = 0x0400;
- }
-
- sc->sc_port_type = port_type;
sc->sc_port_speed = port_speed;
-
sc->sc_bm_max_pools = MAX_BM_POOLS;
sc->sc_max_frame_length = PORT_MAX_FRAME_LENGTH;
- if (port_type == FMAN_PORT_TYPE_TX)
- sc->sc_qman_channel_id =
- FMAN_GET_QMAN_CHANNEL_ID(device_get_parent(dev),
- sc->sc_port_id);
-
- OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
+ OF_device_register_xref(OF_xref_from_node(node), dev);
return (0);
}
-static int
-fman_port_detach(device_t dev)
+int
+fman_port_detach_common(device_t dev, struct fman_port_softc *sc)
{
- struct fman_port_softc *sc = device_get_softc(dev);
if (sc->sc_mem != NULL)
bus_release_resource(dev, sc->sc_mem);
@@ -273,16 +64,17 @@ fman_port_detach(device_t dev)
return (0);
}
-static int
-fman_port_config(device_t dev, struct fman_port_params *params)
+void
+fman_port_config_common(struct fman_port_softc *sc,
+ struct fman_port_params *params)
{
- struct fman_port_softc *sc = device_get_softc(dev);
sc->sc_default_fqid = params->dflt_fqid;
sc->sc_err_fqid = params->err_fqid;
sc->sc_max_port_fifo_size =
- FMAN_GET_BMI_MAX_FIFO_SIZE(device_get_parent(dev));
+ FMAN_GET_BMI_MAX_FIFO_SIZE(device_get_parent(sc->sc_dev));
+
switch (sc->sc_revision_major) {
case 2:
case 3:
@@ -294,377 +86,6 @@ fman_port_config(device_t dev, struct fman_port_params *params)
sc->sc_max_sub_portals = 16;
break;
}
- if (sc->sc_revision_major >= 6 &&
- sc->sc_port_type == FMAN_PORT_TYPE_TX && sc->sc_port_speed == 1000)
- /* Errata A005127 workaround */
- bus_write_4(sc->sc_mem, FMBM_TFP, 0x00001013);
-
- sc->sc_tasks.extra = 0;
-
- switch (sc->sc_port_speed) {
- case 10000:
- if (sc->sc_revision_major < 6) {
- sc->sc_tasks.num = 16;
- if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
- sc->sc_tasks.extra = 8;
- } else
- sc->sc_tasks.num = 14;
- break;
- case 1000:
- if (sc->sc_revision_major >= 6)
- sc->sc_tasks.num = 4;
- else {
- sc->sc_tasks.num = 3;
- if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
- sc->sc_tasks.extra = 2;
- }
- break;
- default:
- sc->sc_tasks.num = 0;
- break;
- }
-
- /* Open DMAs */
- if (sc->sc_revision_major >= 6) {
- sc->sc_open_dmas.extra = 0;
- if (sc->sc_port_speed == 10000) {
- if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
- sc->sc_open_dmas.num = 12;
- else
- sc->sc_open_dmas.num = 8;
- } else {
- if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
- sc->sc_open_dmas.num = 3;
- else
- sc->sc_open_dmas.num = 2;
- }
- } else {
- if (sc->sc_port_speed == 10000) {
- sc->sc_open_dmas.num = 8;
- sc->sc_open_dmas.num = 8;
- } else {
- sc->sc_open_dmas.num = 1;
- sc->sc_open_dmas.extra = 1;
- }
- }
-
- /* FIFO bufs */
- if (sc->sc_revision_major >= 6) {
- if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
- if (sc->sc_port_speed == 10000)
- sc->sc_fifo_bufs.num = 64;
- else
- sc->sc_fifo_bufs.num = 50;
- else
- if (sc->sc_port_speed == 10000)
- sc->sc_fifo_bufs.num = 96;
- else
- sc->sc_fifo_bufs.num = 50;
- } else {
- if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
- if (sc->sc_port_speed == 10000)
- sc->sc_fifo_bufs.num = 48;
- else
- sc->sc_fifo_bufs.num = 44;
- else
- if (sc->sc_port_speed == 10000)
- sc->sc_fifo_bufs.num = 48;
- else
- sc->sc_fifo_bufs.num = 45;
- }
-
- sc->sc_fifo_bufs.extra = 0;
- sc->sc_fifo_bufs.num *= FMAN_BMI_FIFO_UNITS;
-
- if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
- for (int i = 0; i < params->rx_params.num_pools; i++)
- sc->sc_bpools[i] = params->rx_params.bpools[i];
-
- /* TODO: buf_margins? See fman_sp_build_buffer_struct */
-
- return (0);
-}
-
-static int
-fman_port_init_bmi_rx(struct fman_port_softc *sc)
-{
- uint32_t reg;
-
- /* TODO: Sort the buffer pool list. */
- /* TODO: Backup pools */
- /* TODO: Depletion mode */
- for (int i = 0; i < FMAN_PORT_MAX_POOLS; i++) {
- /* Initialize the external pool info */
- if (sc->sc_bpools[i].size != 0) {
- bus_write_4(sc->sc_mem, FMBM_REBMPI(i),
- REBMPI_VAL | REBMPI_ACE |
- (sc->sc_bpools[i].bpid << REBMPI_BPID_S) |
- sc->sc_bpools[i].size);
- } else
- /* Mark invalid if zero */
- bus_write_4(sc->sc_mem, FMBM_REBMPI(i), 0);
- }
-
- bus_write_4(sc->sc_mem, FMBM_RDA, RDA_WOPT);
-
- bus_write_4(sc->sc_mem, FMBM_RFCA,
- RFCA_OR | RFCA_SYNC_REQ | RFCA_MR_DEF);
-
- bus_write_4(sc->sc_mem, FMBM_RFPNE,
- NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME);
- bus_write_4(sc->sc_mem, FMBM_RFENE,
- NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
-
- bus_write_4(sc->sc_mem, FMBM_RFQID, sc->sc_default_fqid);
- bus_write_4(sc->sc_mem, FMBM_REFQID, sc->sc_err_fqid);
-
- if (sc->sc_revision_major < 6)
- bus_write_4(sc->sc_mem, FMBM_RETH, RETH_ETHE);
-
- /* Errata A006320 makes CFED field bad */
- if (sc->sc_revision_major == 6 && (sc->sc_revision_minor == 0))
- /* These are under errata A006320 */;
- else
- bus_write_4(sc->sc_mem, FMBM_RFED,
- DEFAULT_RX_CUT_END_BYTES << BMI_RX_FRAME_END_CUT_SHIFT);
-
- /* Insert internal context ahead of the frame */
- reg = sizeof(struct fman_internal_context) << REBM_BSM_S;
- bus_write_4(sc->sc_mem, FMBM_REBM, reg);
- reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << RICP_ICIOF_S;
- reg |= howmany(sizeof(struct fman_internal_context), 0x10);
- bus_write_4(sc->sc_mem, FMBM_RICP, reg);
-
- bus_write_4(sc->sc_mem, FMBM_RFNE, NIA_ENG_HWP);
- bus_write_4(sc->sc_mem, FMBM_RFSDM, FM_FD_ERR_DIS);
- bus_write_4(sc->sc_mem, FMBM_RFSEM, BMI_RX_ERR & ~FM_FD_ERR_DIS);
-
- return (0);
-}
-
-static int
-fman_port_init_bmi_tx(struct fman_port_softc *sc)
-{
- uint32_t reg;
- int depth;
-
- bus_write_4(sc->sc_mem, FMBM_TCFG, 0);
- bus_write_4(sc->sc_mem, FMBM_TDA, 0);
- bus_write_4(sc->sc_mem, FMBM_TFED, 0);
- if (sc->sc_port_speed == 10000)
- depth = 4;
- else if (sc->sc_revision_major >= 6)
- depth = 2;
- else
- depth = 1;
- sc->sc_tx_deq_pipeline_depth = depth;
- reg = ((depth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT) | 0x13;
- bus_write_4(sc->sc_mem, FMBM_TFP, reg);
-
- /* Default color: green */
- bus_write_4(sc->sc_mem, FMBM_TFCA,
- TFCA_MR_DEF | TFCA_ATTR_ORDER);
-
- bus_write_4(sc->sc_mem, FMBM_TFDNE, NIA_ENG_QMI_DEQ);
- bus_write_4(sc->sc_mem, FMBM_TFENE,
- NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
-
- /* Insert internal context ahead of the frame */
- reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << TICP_ICIOF_S;
- reg |= howmany(sizeof(struct fman_internal_context), 0x10);
- bus_write_4(sc->sc_mem, FMBM_TICP, reg);
-
- if (sc->sc_revision_major >= 6)
- bus_write_4(sc->sc_mem, FMBM_TFNE,
- (sc->sc_default_fqid == 0 ? TFNE_EBD : 0) |
- NIA_BMI_AC_FETCH_ALLFRAME);
- bus_write_4(sc->sc_mem, FMBM_TCFQID, sc->sc_default_fqid);
- bus_write_4(sc->sc_mem, FMBM_TEFQID, sc->sc_err_fqid);
-
- return (0);
-}
-
-static int
-fman_port_init_hwp(struct fman_port_softc *sc)
-{
- int i;
-
- /* Stop the parser so we can initialize it for our uses */
- bus_write_4(sc->sc_mem, HWP_PCAC, HWP_PCAC_PSTOP);
-
- for (i = 0; i < 100 &&
- (bus_read_4(sc->sc_mem, HWP_PCAC) & HWP_HXS_PCAC_PSTAT) != 0; i++) {
- DELAY(10);
- }
- if (i == 100) {
- device_printf(sc->sc_dev, "Timeout stopping HW parser\n");
- return (ENXIO);
- }
-
- /* set the parser examination config */
- for (i = 0; i < HWP_HXS_COUNT; i++) {
- bus_write_4(sc->sc_mem, HWP_HXS_SSA(i), 0);
- bus_write_4(sc->sc_mem, HWP_HXS_LCV(i), 0xffffffff);
- }
- bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_TCP), HXS_SH_PAD_REM);
- bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_UDP), HXS_SH_PAD_REM);
-
- /* Re-enable the parser */
- bus_write_4(sc->sc_mem, HWP_PCAC, 0);
-
- return (0);
-}
-
-static int
-fman_port_init_qmi(struct fman_port_softc *sc)
-{
- uint32_t reg;
-
- if (sc->sc_port_type == FMAN_PORT_TYPE_RX) {
- bus_write_4(sc->sc_mem, FMQM_PNEN,
- NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
- return (0);
- }
-
- /* TX port */
- bus_write_4(sc->sc_mem, FMQM_PNDN,
- NIA_ENG_BMI | NIA_BMI_AC_TX);
- /* TX port */
- bus_write_4(sc->sc_mem, FMQM_PNEN,
- NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
-
- reg = 0;
-
- if (sc->sc_deq_high_priority)
- reg |= QMI_DEQ_CFG_PRI;
-
- reg |= QMI_DEQ_CFG_TYPE1;
- reg |= QMI_DEQ_CFG_PREFETCH_FULL;
- reg |= (sc->sc_qman_channel_id & QMI_DEQ_CFG_SP_MASK) << QMI_DEQ_CFG_SP_SHIFT;
- reg |= sc->sc_deq_byte_count;
- bus_write_4(sc->sc_mem, FMQM_PNDC, reg);
-
- return (0);
-}
-
-static int
-fman_port_init(device_t dev)
-{
- struct fman_port_init_params params;
- struct fman_port_softc *sc = device_get_softc(dev);
- int err;
-
- if (sc->sc_port_type == FMAN_PORT_TYPE_RX) {
- /* Set up RX buffers and fifo */
- }
- params.port_id = sc->sc_port_id;
- params.is_rx_port = (sc->sc_port_type == FMAN_PORT_TYPE_RX);
- params.num_tasks = sc->sc_tasks.num;
- params.extra_tasks = sc->sc_tasks.extra;
- params.open_dmas = sc->sc_open_dmas.num;
- params.extra_dmas = sc->sc_open_dmas.extra;
- params.fifo_size = sc->sc_fifo_bufs.num;
- params.extra_fifo_size = sc->sc_fifo_bufs.extra;
- params.max_frame_length = sc->sc_max_frame_length;
- params.deq_pipeline_size = sc->sc_tx_deq_pipeline_depth;
-
- /* TODO: verify_size_of_fifo() from Linux driver */
- err = FMAN_SET_PORT_PARAMS(device_get_parent(dev), ¶ms);
-
- if (err != 0)
- return (err);
-
- if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
- err = fman_port_init_bmi_tx(sc);
- else {
- err = fman_port_init_bmi_rx(sc);
- if (err == 0)
- fman_port_init_hwp(sc);
- }
-
- if (err != 0)
- return (err);
-
- err = fman_port_init_qmi(sc);
-
- /* TODO: keygen here */
-
- return (err);
-}
-
-static int
-fman_port_disable(device_t dev)
-{
- struct fman_port_softc *sc;
- uint32_t reg;
- int count;
-
- sc = device_get_softc(dev);
-
- switch (sc->sc_port_type) {
- case FMAN_PORT_TYPE_TX:
- reg = bus_read_4(sc->sc_mem, FMQM_PNC);
- bus_write_4(sc->sc_mem, FMQM_PNC, reg & ~PNC_EN);
- for (count = 0; count < 100; count++) {
- DELAY(10);
- reg = bus_read_4(sc->sc_mem, FMQM_PNS);
- if (!(reg & PNS_DEQ_FD_BSY))
- break;
- }
- if (count == 100)
- device_printf(sc->sc_dev, "Timeout stopping QMI\n");
- reg = bus_read_4(sc->sc_mem, FMBM_TCFG);
- bus_write_4(sc->sc_mem, FMBM_TCFG, reg & ~BMI_PORT_CFG_EN);
- for (count = 0; count < 100; count++) {
- DELAY(10);
- reg = bus_read_4(sc->sc_mem, FMBM_TST);
- if (!(reg & PNS_DEQ_FD_BSY))
- break;
- }
- if (count == 100)
- device_printf(sc->sc_dev, "Timeout stopping BMI");
- break;
- case FMAN_PORT_TYPE_RX:
- reg = bus_read_4(sc->sc_mem, FMBM_RCFG);
- bus_write_4(sc->sc_mem, FMBM_RCFG, reg & ~BMI_PORT_CFG_EN);
- for (count = 0; count < 100; count++) {
- DELAY(10);
- reg = bus_read_4(sc->sc_mem, FMBM_RST);
- if (!(reg & PNS_DEQ_FD_BSY))
- break;
- }
- if (count == 100)
- device_printf(sc->sc_dev, "Timeout stopping BMI");
- break;
- }
-
- return (0);
-}
-
-static int
-fman_port_enable(device_t dev)
-{
- struct fman_port_softc *sc;
- uint32_t reg;
-
- sc = device_get_softc(dev);
- switch (sc->sc_port_type) {
- case FMAN_PORT_TYPE_TX:
- reg = bus_read_4(sc->sc_mem, FMQM_PNC);
- bus_write_4(sc->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN);
- reg = bus_read_4(sc->sc_mem, FMBM_TCFG);
- bus_write_4(sc->sc_mem, FMBM_TCFG, reg | BMI_PORT_CFG_EN);
- break;
- case FMAN_PORT_TYPE_RX:
- reg = bus_read_4(sc->sc_mem, FMQM_PNC);
- bus_write_4(sc->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN);
- reg = bus_read_4(sc->sc_mem, FMBM_RCFG);
- bus_write_4(sc->sc_mem, FMBM_RCFG, reg | BMI_PORT_CFG_EN);
- bus_write_4(sc->sc_mem, FMBM_RSTC, RSTC_EN);
- break;
- }
-
- return (0);
}
int
@@ -674,36 +95,3 @@ fman_port_get_id(device_t dev)
return (sc->sc_port_id);
}
-
-/*
- * Runtime toggle for whether the praser sends frames to KeyGen (HWK)
- * or straight to BMI-enqueue. Called by dpaa_eth after successfully
- * binding a KG scheme to this port -- flipping this without a bound scheme
- * drops all Rx traffic on the port.
- */
-void
-fman_port_rx_use_kg(device_t dev, bool enable)
-{
- struct fman_port_softc *sc = device_get_softc(dev);
-
- bus_write_4(sc->sc_mem, FMBM_RFPNE,
- enable ? NIA_ENG_HWK : (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
-}
-
-static device_method_t fman_port_methods[] = {
- DEVMETHOD(device_probe, fman_port_probe),
- DEVMETHOD(device_attach, fman_port_attach),
- DEVMETHOD(device_detach, fman_port_detach),
-
- DEVMETHOD(fman_port_config, fman_port_config),
- DEVMETHOD(fman_port_init, fman_port_init),
- DEVMETHOD(fman_port_enable, fman_port_enable),
- DEVMETHOD(fman_port_disable, fman_port_disable),
-
- DEVMETHOD_END
-};
-
-DEFINE_CLASS_0(fman_port, fman_port_driver, fman_port_methods,
- sizeof(struct fman_port_softc));
-EARLY_DRIVER_MODULE(fman_port, fman, fman_port_driver, 0, 0,
- BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
diff --git a/sys/dev/dpaa/fman_port_rx.c b/sys/dev/dpaa/fman_port_rx.c
new file mode 100644
index 000000000000..5499e5e1599d
--- /dev/null
+++ b/sys/dev/dpaa/fman_port_rx.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * FMan RX port driver.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <machine/bus.h>
+
+#include "fman.h"
+#include "fman_parser.h"
+#include "fman_port.h"
+#include "fman_port_var.h"
+#include "fman_if.h"
+#include "fman_port_if.h"
+
+#define RX_10G_PORT_BASE 0x10
+
+/* BMI Rx registers. */
+#define FMBM_RCFG 0x000
+#define FMBM_RST 0x004
+#define FMBM_RDA 0x008
+#define RDA_WOPT 0x00100000
+#define FMBM_RFP 0x00c
+#define FMBM_RFED 0x010
+#define BMI_RX_FRAME_END_CUT_SHIFT 16
+#define FMBM_RICP 0x014 /* Counts are units of 16 bytes */
+#define RICP_ICEOF_M 0x001f0000
+#define RICP_ICEOF_S 16
+#define RICP_ICIOF_M 0x00000f00
+#define RICP_ICIOF_S 8
+#define RICP_ICSZ_S 0x0000001f
+#define FMBM_RIM 0x018
+#define FMBM_REBM 0x01c
+#define REBM_BSM_M 0x01ff0000
+#define REBM_BSM_S 16
+#define REBM_BEM_M 0x000001ff
+#define FMBM_RFNE 0x020
+#define FMBM_RFCA 0x024
+#define RFCA_OR 0x80000000
+#define RFCA_COLOR 0x0c000000
+#define RFCA_SYNC 0x03000000
+#define RFCA_SYNC_REQ 0x02000000
+#define RFCA_MR 0x003f0000
+#define RFCA_MR_DEF 0x003c0000
+#define FMBM_RFPNE 0x028
+#define FMBM_RETH 0x038
+#define RETH_ETHE 0x80000000 /* Excessive Threshold Enable */
+#define FMBM_RFQID 0x060
+#define FMBM_REFQID 0x064
+#define FMBM_RFSDM 0x068
+#define FMBM_RFSEM 0x06c
+#define FMBM_RFENE 0x070
+#define FMBM_REBMPI(i) (0x100 + (4 * (i)))
+#define REBMPI_VAL 0x80000000
+#define REBMPI_ACE 0x40000000
+#define REBMPI_BPID_S 16
+#define FMBM_RSTC 0x0200
+#define RSTC_EN 0x80000000
+
+/* Hardware Parser (HWP). */
+#define HWP_PCAC 0xbf8
+#define HWP_PCAC_PSTOP 0x00000001
+#define HWP_HXS_PCAC_PSTAT 0x00000100
+#define HWP_HXS_SSA(x) (0x800 + x * 2 * sizeof(uint32_t))
+#define HWP_HXS_LCV(x) (0x800 + (x * 2 + 1) * sizeof(uint32_t))
+#define HWP_HXS_TCP 0xA
+#define HWP_HXS_UDP 0xB
+#define HXS_SH_PAD_REM 0x80000000
+#define HWP_HXS_COUNT 16
+
+#define BMI_RX_ERR (FM_FD_ERR_DMA | FM_FD_ERR_FPE | \
+ FM_FD_ERR_FSE | FM_FD_ERR_DIS | \
+ FM_FD_ERR_EOF | FM_FD_ERR_NSS | \
+ FM_FD_ERR_KSO | FM_FD_ERR_IPP | \
+ FM_FD_ERR_PTE | FM_FD_ERR_PHE | \
+ FM_FD_ERR_BLE)
+
+#define DEFAULT_RX_CUT_END_BYTES 4
+
+struct fman_port_rx_softc {
+ struct fman_port_softc sc_base;
+ struct fman_port_buffer_pool sc_bpools[FMAN_PORT_MAX_POOLS];
+};
+
+static struct ofw_compat_data rx_compats[] = {
+ { "fsl,fman-v2-port-rx", 0 },
+ { "fsl,fman-v3-port-rx", PORT_V3 },
+ { NULL, 0 }
+};
+
+static int
+fman_port_rx_probe(device_t dev)
+{
+
+ if (ofw_bus_search_compatible(dev, rx_compats)->ocd_str == NULL)
+ return (ENXIO);
+
+ device_set_desc(dev, "FMan RX port");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+fman_port_rx_attach(device_t dev)
+{
+ struct fman_port_rx_softc *sc;
+ uintptr_t compat_data;
+ int port_speed;
+
+ sc = device_get_softc(dev);
+ compat_data = ofw_bus_search_compatible(dev, rx_compats)->ocd_data;
+
+ port_speed = 1000;
+ if ((compat_data & PORT_V3) == PORT_V3) {
+ if (OF_hasprop(ofw_bus_get_node(dev), "fsl,fman-10g-port"))
+ port_speed = 10000;
+ } else {
+ int cell = 0;
+ OF_getencprop(ofw_bus_get_node(dev), "cell-index", &cell,
+ sizeof(cell));
+ if (cell > RX_10G_PORT_BASE)
+ port_speed = 10000;
+ }
+
+ return (fman_port_attach_common(dev, &sc->sc_base, port_speed));
+}
+
+static int
+fman_port_rx_detach(device_t dev)
+{
+ struct fman_port_rx_softc *sc = device_get_softc(dev);
+
+ return (fman_port_detach_common(dev, &sc->sc_base));
+}
+
+static int
+fman_port_rx_config(device_t dev, struct fman_port_params *params)
+{
+ struct fman_port_rx_softc *sc = device_get_softc(dev);
+ struct fman_port_softc *base = &sc->sc_base;
+
+ fman_port_config_common(base, params);
+
+ base->sc_tasks.extra = 0;
+ switch (base->sc_port_speed) {
+ case 10000:
+ if (base->sc_revision_major < 6) {
+ base->sc_tasks.num = 16;
+ base->sc_tasks.extra = 8;
+ } else
+ base->sc_tasks.num = 14;
+ break;
+ case 1000:
+ if (base->sc_revision_major >= 6)
+ base->sc_tasks.num = 4;
+ else {
+ base->sc_tasks.num = 3;
+ base->sc_tasks.extra = 2;
+ }
+ break;
+ default:
+ base->sc_tasks.num = 0;
+ break;
+ }
+
+ if (base->sc_revision_major >= 6) {
+ base->sc_open_dmas.extra = 0;
+ base->sc_open_dmas.num =
+ (base->sc_port_speed == 10000) ? 8 : 2;
+ } else if (base->sc_port_speed == 10000) {
+ base->sc_open_dmas.num = 8;
+ base->sc_open_dmas.extra = 8;
+ } else {
+ base->sc_open_dmas.num = 1;
+ base->sc_open_dmas.extra = 1;
+ }
+
+ if (base->sc_revision_major >= 6)
+ base->sc_fifo_bufs.num =
+ (base->sc_port_speed == 10000) ? 96 : 50;
+ else
+ base->sc_fifo_bufs.num =
+ (base->sc_port_speed == 10000) ? 48 : 45;
+ base->sc_fifo_bufs.extra = 0;
+ base->sc_fifo_bufs.num *= FMAN_BMI_FIFO_UNITS;
+
+ for (int i = 0; i < params->rx_params.num_pools; i++)
+ sc->sc_bpools[i] = params->rx_params.bpools[i];
+
+ /* TODO: buf_margins? See fman_sp_build_buffer_struct */
+ return (0);
+}
+
+static int
+fman_port_rx_init_bmi(struct fman_port_rx_softc *sc)
+{
+ struct fman_port_softc *base = &sc->sc_base;
+ uint32_t reg;
+
+ /* TODO: Sort the buffer pool list. */
+ /* TODO: Backup pools */
+ /* TODO: Depletion mode */
+ for (int i = 0; i < FMAN_PORT_MAX_POOLS; i++) {
+ if (sc->sc_bpools[i].size != 0) {
+ bus_write_4(base->sc_mem, FMBM_REBMPI(i),
+ REBMPI_VAL | REBMPI_ACE |
+ (sc->sc_bpools[i].bpid << REBMPI_BPID_S) |
+ sc->sc_bpools[i].size);
+ } else
+ bus_write_4(base->sc_mem, FMBM_REBMPI(i), 0);
+ }
+
*** 622 LINES SKIPPED ***