Commit 74bd5dbe authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'support-icssg-based-ethernet-on-am65x-sr1-0-devices'

Diogo Ivo says:

====================
Support ICSSG-based Ethernet on AM65x SR1.0 devices

This series extends the current ICSSG-based Ethernet driver to support
AM65x Silicon Revision 1.0 devices.

Notable differences between the Silicon Revisions are that there is
no TX core in SR1.0 with this being handled by the firmware, requiring
extra DMA channels to manage communication with the firmware (with the
firmware being different as well) and in the packet classifier.

The motivation behind it is that a significant number of Siemens
devices containing SR1.0 silicon have been deployed in the field
and need to be supported and updated to newer kernel versions
without losing functionality.

This series is based on TI's 5.10 SDK [1].

The fifth version of this patch series can be found in [2].

Compared to the last version of the patch set there are only changes in
patch 05/10, where the fields of a struct are now explicitly declared as
__le32 so that we can properly interpret them.

Both of the problems mentioned in v4 have been addressed by disabling
those functionalities, meaning that this driver currently only supports
one TX queue and does not support a 100Mbit/s half-duplex connection.
The removal of these features has been commented in the appropriate
locations in the code.

[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
[2]: https://lore.kernel.org/netdev/20240326110709.26165-1-diogo.ivo@siemens.com/
====================

Link: https://lore.kernel.org/r/20240403104821.283832-1-diogo.ivo@siemens.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 87c33315 e654b85a
Loading
Loading
Loading
Loading
+29 −6
Original line number Diff line number Diff line
@@ -13,14 +13,12 @@ description:
  Ethernet based on the Programmable Real-Time Unit and Industrial
  Communication Subsystem.

allOf:
  - $ref: /schemas/remoteproc/ti,pru-consumer.yaml#

properties:
  compatible:
    enum:
      - ti,am642-icssg-prueth      # for AM64x SoC family
      - ti,am654-icssg-prueth      # for AM65x SoC family
      - ti,am654-sr1-icssg-prueth  # for AM65x SoC family, SR1.0

  sram:
    $ref: /schemas/types.yaml#/definitions/phandle
@@ -28,9 +26,11 @@ properties:
      phandle to MSMC SRAM node

  dmas:
    maxItems: 10
    minItems: 10
    maxItems: 12

  dma-names:
    minItems: 10
    items:
      - const: tx0-0
      - const: tx0-1
@@ -42,6 +42,8 @@ properties:
      - const: tx1-3
      - const: rx0
      - const: rx1
      - const: rxmgm0
      - const: rxmgm1

  ti,mii-g-rt:
    $ref: /schemas/types.yaml#/definitions/phandle
@@ -132,6 +134,27 @@ required:
  - interrupts
  - interrupt-names

allOf:
  - $ref: /schemas/remoteproc/ti,pru-consumer.yaml#

  - if:
      properties:
        compatible:
          contains:
            const: ti,am654-sr1-icssg-prueth
    then:
      properties:
        dmas:
          minItems: 12
        dma-names:
          minItems: 12
    else:
      properties:
        dmas:
          maxItems: 10
        dma-names:
          maxItems: 10

unevaluatedProperties: false

examples:
+15 −0
Original line number Diff line number Diff line
@@ -198,6 +198,21 @@ config TI_ICSSG_PRUETH
	  to support the Ethernet operation. Currently, it supports Ethernet
	  with 1G and 100M link speed.

config TI_ICSSG_PRUETH_SR1
	tristate "TI Gigabit PRU SR1.0 Ethernet driver"
	select PHYLIB
	select TI_ICSS_IEP
	select TI_K3_CPPI_DESC_POOL
	depends on PRU_REMOTEPROC
	depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
	help
	  Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem.
	  This subsystem is available on the AM65 SR1.0 platform.

	  This driver requires firmware binaries which will run on the PRUs
	  to support the Ethernet operation. Currently, it supports Ethernet
	  with 1G, 100M and 10M link speed.

config TI_ICSS_IEP
	tristate "TI PRU ICSS IEP driver"
	depends on PTP_1588_CLOCK_OPTIONAL
+9 −0
Original line number Diff line number Diff line
@@ -33,10 +33,19 @@ obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o

obj-$(CONFIG_TI_ICSSG_PRUETH) += icssg-prueth.o
icssg-prueth-y := icssg/icssg_prueth.o \
		  icssg/icssg_common.o \
		  icssg/icssg_classifier.o \
		  icssg/icssg_queues.o \
		  icssg/icssg_config.o \
		  icssg/icssg_mii_cfg.o \
		  icssg/icssg_stats.o \
		  icssg/icssg_ethtool.o
obj-$(CONFIG_TI_ICSSG_PRUETH_SR1) += icssg-prueth-sr1.o
icssg-prueth-sr1-y := icssg/icssg_prueth_sr1.o \
		      icssg/icssg_common.o \
		      icssg/icssg_classifier.o \
		      icssg/icssg_config.o \
		      icssg/icssg_mii_cfg.o \
		      icssg/icssg_stats.o \
		      icssg/icssg_ethtool.o
obj-$(CONFIG_TI_ICSS_IEP) += icssg/icss_iep.o
+104 −9
Original line number Diff line number Diff line
@@ -274,6 +274,16 @@ static void rx_class_set_or(struct regmap *miig_rt, int slice, int n,
	regmap_write(miig_rt, offset, data);
}

static u32 rx_class_get_or(struct regmap *miig_rt, int slice, int n)
{
	u32 offset, val;

	offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN);
	regmap_read(miig_rt, offset, &val);

	return val;
}

void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac)
{
	regmap_write(miig_rt, MAC_INTERFACE_0, (u32)(mac[0] | mac[1] << 8 |
@@ -288,6 +298,26 @@ void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
	regmap_write(miig_rt, offs[slice].mac1, (u32)(mac[4] | mac[5] << 8));
}

static void icssg_class_ft1_add_mcast(struct regmap *miig_rt, int slice,
				      int slot, const u8 *addr, const u8 *mask)
{
	u32 val;
	int i;

	WARN(slot >= FT1_NUM_SLOTS, "invalid slot: %d\n", slot);

	rx_class_ft1_set_da(miig_rt, slice, slot, addr);
	rx_class_ft1_set_da_mask(miig_rt, slice, slot, mask);
	rx_class_ft1_cfg_set_type(miig_rt, slice, slot, FT1_CFG_TYPE_EQ);

	/* Enable the FT1 slot in OR enable for all classifiers */
	for (i = 0; i < ICSSG_NUM_CLASSIFIERS_IN_USE; i++) {
		val = rx_class_get_or(miig_rt, slice, i);
		val |= RX_CLASS_FT_FT1_MATCH(slot);
		rx_class_set_or(miig_rt, slice, i, val);
	}
}

/* disable all RX traffic */
void icssg_class_disable(struct regmap *miig_rt, int slice)
{
@@ -331,14 +361,18 @@ void icssg_class_disable(struct regmap *miig_rt, int slice)
	regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
}

void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti)
void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti,
			 bool is_sr1)
{
	int num_classifiers = is_sr1 ? ICSSG_NUM_CLASSIFIERS_IN_USE : 1;
	u32 data;
	int n;

	/* defaults */
	icssg_class_disable(miig_rt, slice);

	/* Setup Classifier */
	for (n = 0; n < num_classifiers; n++) {
		/* match on Broadcast or MAC_PRU address */
		data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;

@@ -346,15 +380,76 @@ void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti)
		if (allmulti)
			data |= RX_CLASS_FT_MC;

	rx_class_set_or(miig_rt, slice, 0, data);
		rx_class_set_or(miig_rt, slice, n, data);

		/* set CFG1 for OR_OR_AND for classifier */
	rx_class_sel_set_type(miig_rt, slice, 0, RX_CLASS_SEL_TYPE_OR_OR_AND);
		rx_class_sel_set_type(miig_rt, slice, n,
				      RX_CLASS_SEL_TYPE_OR_OR_AND);
	}

	/* clear CFG2 */
	regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
}

void icssg_class_promiscuous_sr1(struct regmap *miig_rt, int slice)
{
	u32 data, offset;
	int n;

	/* defaults */
	icssg_class_disable(miig_rt, slice);

	/* Setup Classifier */
	for (n = 0; n < ICSSG_NUM_CLASSIFIERS_IN_USE; n++) {
		/* set RAW_MASK to bypass filters */
		offset = RX_CLASS_GATES_N_REG(slice, n);
		regmap_read(miig_rt, offset, &data);
		data |= RX_CLASS_GATES_RAW_MASK;
		regmap_write(miig_rt, offset, data);
	}
}

void icssg_class_add_mcast_sr1(struct regmap *miig_rt, int slice,
			       struct net_device *ndev)
{
	u8 mask_addr[6] = { 0, 0, 0, 0, 0, 0xff };
	struct netdev_hw_addr *ha;
	int slot = 2;

	rx_class_ft1_set_start_len(miig_rt, slice, 0, 6);
	/* reserve first 2 slots for
	 *	1) 01-80-C2-00-00-XX Known Service Ethernet Multicast addresses
	 *	2) 01-00-5e-00-00-XX Local Network Control Block
	 *			      (224.0.0.0 - 224.0.0.255  (224.0.0/24))
	 */
	icssg_class_ft1_add_mcast(miig_rt, slice, 0,
				  eth_reserved_addr_base, mask_addr);
	icssg_class_ft1_add_mcast(miig_rt, slice, 1,
				  eth_ipv4_mcast_addr_base, mask_addr);
	mask_addr[5] = 0;
	netdev_for_each_mc_addr(ha, ndev) {
		/* skip addresses matching reserved slots */
		if (!memcmp(eth_reserved_addr_base, ha->addr, 5) ||
		    !memcmp(eth_ipv4_mcast_addr_base, ha->addr, 5)) {
			netdev_dbg(ndev, "mcast skip %pM\n", ha->addr);
			continue;
		}

		if (slot >= FT1_NUM_SLOTS) {
			netdev_dbg(ndev,
				   "can't add more than %d MC addresses, enabling allmulti\n",
				   FT1_NUM_SLOTS);
			icssg_class_default(miig_rt, slice, 1, true);
			break;
		}

		netdev_dbg(ndev, "mcast add %pM\n", ha->addr);
		icssg_class_ft1_add_mcast(miig_rt, slice, slot,
					  ha->addr, mask_addr);
		slot++;
	}
}

/* required for SAV check */
void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr)
{
+1221 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading