Commit bf136673 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qca8337-improvements'



Ansuel Smith says:

====================
Multiple improvement for qca8337 switch

This series is the final step of a long process of porting 80+ devices
to use the new qca8k driver instead of the hacky qca one based on never
merged swconfig platform.
Some background to justify all these additions.
QCA used a special binding to declare raw initval to set the swich. I
made a script to convert all these magic values and convert 80+ dts and
scan all the needed "unsupported regs". We find a baseline where we
manage to find the common and used regs so in theory hopefully we don't
have to add anymore things.
We discovered lots of things with this, especially about how differently
qca8327 works compared to qca8337.

In short, we found that qca8327 have some problem with suspend/resume for
their internal phy. It instead sets some dedicated regs that suspend the
phy without setting the standard bit. First 4 patch are to fix this.
There is also a patch about preferring master. This is directly from the
original driver and it seems to be needed to prevent some problem with
the pause frame.

Every ipq806x target sets the mac power sel and this specific reg
regulates the output voltage of the regulator. Without this some
instability can occur.

Some configuration (for some reason) swap mac6 with mac0. We add support
for this.
Also, we discovered that some device doesn't work at all with pll enabled
for sgmii line. In the original code this was based on the switch
revision. In later revision the pll regs were decided based on the switch
type (disabled for qca8327 and enabled for qca8337) but still some
device had that disabled in the initval regs.
Considering we found at least one qca8337 device that required pll
disabled to work (no traffic problem) we decided to introduce a binding
to enable pll and set it only with that.

Lastly, we add support for led open drain that require the power-on-sel
to set. Also, some device have only the power-on-sel set in the initval
so we add also support for that. This is needed for the correct function
of the switch leds.
Qca8327 have a special reg in the pws regs that set it to a reduced
48pin layout. This is needed or the switch doesn't work.

These are all the special configuration we find on all these devices that
are from various targets. Mostly ath79, ipq806x and bcm53xx.
Changes v7:
- Fix missing newline in yaml
- Handle error with wrong cpu port detected
- Move yaml commit as last to fix bot error

Changes v6:
- Convert Documentation to yaml
- Add extra check for cpu port and invalid phy mode
- Add co developed by tag to give credits to Matthew

Changes v5:
- Swap patch. Document first then implement.
- Fix some grammar error reported.
- Rework function. Remove phylink mac_config DT scan and move everything
  to dedicated function in probe.
- Introduce new logic for delay selection where is also supported with
  internal delay declared and rgmii set as phy mode
- Start working on ymal conversion. Will later post this in v6 when we
  finally take final decision about mac swap.

Changes v4:
- Fix typo in SGMII falling edge about using PHY id instead of
  switch id

Changes v3:
- Drop phy patches (proposed separateley)
- Drop special pwr binding. Rework to ipq806x specific
- Better describe compatible and add serial print on switch chip
- Drop mac exchange. Rework falling edge and move it to mac_config
- Add support for port 6 cpu port. Drop hardcoded cpu port to port0
- Improve port stability with sgmii. QCA source have intenal delay also
  for sgmii
- Add warning with pll enabled on wrong configuration

Changes v2:
- Reword Documentation patch to dt-bindings
- Propose first 2 phy patch to net
- Better describe and add hint on how to use all the new
  bindings
- Rework delay scan function and move to phylink mac_config
- Drop package48 wrong binding
- Introduce support for qca8328 switch
- Fix wrong binding name power-on-sel
- Return error on wrong config with led open drain and
  ignore-power-on-sel not set
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bacc8daf d291fbb8
Loading
Loading
Loading
Loading
+0 −215
Original line number Diff line number Diff line
* Qualcomm Atheros QCA8xxx switch family

Required properties:

- compatible: should be one of:
    "qca,qca8327"
    "qca,qca8334"
    "qca,qca8337"

- #size-cells: must be 0
- #address-cells: must be 1

Optional properties:

- reset-gpios: GPIO to be used to reset the whole device

Subnodes:

The integrated switch subnode should be specified according to the binding
described in dsa/dsa.txt. If the QCA8K switch is connect to a SoC's external
mdio-bus each subnode describing a port needs to have a valid phandle
referencing the internal PHY it is connected to. This is because there's no
N:N mapping of port and PHY id.
To declare the internal mdio-bus configuration, declare a mdio node in the
switch node and declare the phandle for the port referencing the internal
PHY is connected to. In this config a internal mdio-bus is registered and
the mdio MASTER is used as communication.

Don't use mixed external and internal mdio-bus configurations, as this is
not supported by the hardware.

The CPU port of this switch is always port 0.

A CPU port node has the following optional node:

- fixed-link            : Fixed-link subnode describing a link to a non-MDIO
                          managed entity. See
                          Documentation/devicetree/bindings/net/fixed-link.txt
                          for details.

For QCA8K the 'fixed-link' sub-node supports only the following properties:

- 'speed' (integer, mandatory), to indicate the link speed. Accepted
  values are 10, 100 and 1000
- 'full-duplex' (boolean, optional), to indicate that full duplex is
  used. When absent, half duplex is assumed.

Examples:

for the external mdio-bus configuration:

	&mdio0 {
		phy_port1: phy@0 {
			reg = <0>;
		};

		phy_port2: phy@1 {
			reg = <1>;
		};

		phy_port3: phy@2 {
			reg = <2>;
		};

		phy_port4: phy@3 {
			reg = <3>;
		};

		phy_port5: phy@4 {
			reg = <4>;
		};

		switch@10 {
			compatible = "qca,qca8337";
			#address-cells = <1>;
			#size-cells = <0>;

			reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
			reg = <0x10>;

			ports {
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 {
					reg = <0>;
					label = "cpu";
					ethernet = <&gmac1>;
					phy-mode = "rgmii";
					fixed-link {
						speed = 1000;
						full-duplex;
					};
				};

				port@1 {
					reg = <1>;
					label = "lan1";
					phy-handle = <&phy_port1>;
				};

				port@2 {
					reg = <2>;
					label = "lan2";
					phy-handle = <&phy_port2>;
				};

				port@3 {
					reg = <3>;
					label = "lan3";
					phy-handle = <&phy_port3>;
				};

				port@4 {
					reg = <4>;
					label = "lan4";
					phy-handle = <&phy_port4>;
				};

				port@5 {
					reg = <5>;
					label = "wan";
					phy-handle = <&phy_port5>;
				};
			};
		};
	};

for the internal master mdio-bus configuration:

	&mdio0 {
		switch@10 {
			compatible = "qca,qca8337";
			#address-cells = <1>;
			#size-cells = <0>;

			reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
			reg = <0x10>;

			ports {
				#address-cells = <1>;
				#size-cells = <0>;

				port@0 {
					reg = <0>;
					label = "cpu";
					ethernet = <&gmac1>;
					phy-mode = "rgmii";
					fixed-link {
						speed = 1000;
						full-duplex;
					};
				};

				port@1 {
					reg = <1>;
					label = "lan1";
					phy-mode = "internal";
					phy-handle = <&phy_port1>;
				};

				port@2 {
					reg = <2>;
					label = "lan2";
					phy-mode = "internal";
					phy-handle = <&phy_port2>;
				};

				port@3 {
					reg = <3>;
					label = "lan3";
					phy-mode = "internal";
					phy-handle = <&phy_port3>;
				};

				port@4 {
					reg = <4>;
					label = "lan4";
					phy-mode = "internal";
					phy-handle = <&phy_port4>;
				};

				port@5 {
					reg = <5>;
					label = "wan";
					phy-mode = "internal";
					phy-handle = <&phy_port5>;
				};
			};

			mdio {
				#address-cells = <1>;
				#size-cells = <0>;

				phy_port1: phy@0 {
					reg = <0>;
				};

				phy_port2: phy@1 {
					reg = <1>;
				};

				phy_port3: phy@2 {
					reg = <2>;
				};

				phy_port4: phy@3 {
					reg = <3>;
				};

				phy_port5: phy@4 {
					reg = <4>;
				};
			};
		};
	};
+362 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/dsa/qca8k.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Qualcomm Atheros QCA83xx switch family

maintainers:
  - John Crispin <john@phrozen.org>

description:
  If the QCA8K switch is connect to an SoC's external mdio-bus, each subnode
  describing a port needs to have a valid phandle referencing the internal PHY
  it is connected to. This is because there is no N:N mapping of port and PHY
  ID. To declare the internal mdio-bus configuration, declare an MDIO node in
  the switch node and declare the phandle for the port, referencing the internal
  PHY it is connected to. In this config, an internal mdio-bus is registered and
  the MDIO master is used for communication. Mixed external and internal
  mdio-bus configurations are not supported by the hardware.

properties:
  compatible:
    oneOf:
      - enum:
          - qca,qca8327
          - qca,qca8328
          - qca,qca8334
          - qca,qca8337
    description: |
      qca,qca8328: referenced as AR8328(N)-AK1(A/B) QFN 176 pin package
      qca,qca8327: referenced as AR8327(N)-AL1A DR-QFN 148 pin package
      qca,qca8334: referenced as QCA8334-AL3C QFN 88 pin package
      qca,qca8337: referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package

  reg:
    maxItems: 1

  reset-gpios:
    description:
      GPIO to be used to reset the whole device
    maxItems: 1

  qca,ignore-power-on-sel:
    $ref: /schemas/types.yaml#/definitions/flag
    description:
      Ignore power-on pin strapping to configure LED open-drain or EEPROM
      presence. This is needed for devices with incorrect configuration or when
      the OEM has decided not to use pin strapping and falls back to SW regs.

  qca,led-open-drain:
    $ref: /schemas/types.yaml#/definitions/flag
    description:
      Set LEDs to open-drain mode. This requires the qca,ignore-power-on-sel to
      be set, otherwise the driver will fail at probe. This is required if the
      OEM does not use pin strapping to set this mode and prefers to set it
      using SW regs. The pin strappings related to LED open-drain mode are
      B68 on the QCA832x and B49 on the QCA833x.

  mdio:
    type: object
    description: Qca8k switch have an internal mdio to access switch port.
                 If this is not present, the legacy mapping is used and the
                 internal mdio access is used.
                 With the legacy mapping the reg corresponding to the internal
                 mdio is the switch reg with an offset of -1.

    properties:
      '#address-cells':
        const: 1
      '#size-cells':
        const: 0

    patternProperties:
      "^(ethernet-)?phy@[0-4]$":
        type: object

        allOf:
          - $ref: "http://devicetree.org/schemas/net/mdio.yaml#"

        properties:
          reg:
            maxItems: 1

        required:
          - reg

patternProperties:
  "^(ethernet-)?ports$":
    type: object
    properties:
      '#address-cells':
        const: 1
      '#size-cells':
        const: 0

    patternProperties:
      "^(ethernet-)?port@[0-6]$":
        type: object
        description: Ethernet switch ports

        properties:
          reg:
            description: Port number

          label:
            description:
              Describes the label associated with this port, which will become
              the netdev name
            $ref: /schemas/types.yaml#/definitions/string

          link:
            description:
              Should be a list of phandles to other switch's DSA port. This
              port is used as the outgoing port towards the phandle ports. The
              full routing information must be given, not just the one hop
              routes to neighbouring switches
            $ref: /schemas/types.yaml#/definitions/phandle-array

          ethernet:
            description:
              Should be a phandle to a valid Ethernet device node.  This host
              device is what the switch port is connected to
            $ref: /schemas/types.yaml#/definitions/phandle

          phy-handle: true

          phy-mode: true

          fixed-link: true

          mac-address: true

          sfp: true

          qca,sgmii-rxclk-falling-edge:
            $ref: /schemas/types.yaml#/definitions/flag
            description:
              Set the receive clock phase to falling edge. Mostly commonly used on
              the QCA8327 with CPU port 0 set to SGMII.

          qca,sgmii-txclk-falling-edge:
            $ref: /schemas/types.yaml#/definitions/flag
            description:
              Set the transmit clock phase to falling edge.

          qca,sgmii-enable-pll:
            $ref: /schemas/types.yaml#/definitions/flag
            description:
              For SGMII CPU port, explicitly enable PLL, TX and RX chain along with
              Signal Detection. On the QCA8327 this should not be enabled, otherwise
              the SGMII port will not initialize. When used on the QCA8337, revision 3
              or greater, a warning will be displayed. When the CPU port is set to
              SGMII on the QCA8337, it is advised to set this unless a communication
              issue is observed.

        required:
          - reg

        additionalProperties: false

oneOf:
  - required:
      - ports
  - required:
      - ethernet-ports

required:
  - compatible
  - reg

additionalProperties: true

examples:
  - |
    #include <dt-bindings/gpio/gpio.h>

    mdio {
        #address-cells = <1>;
        #size-cells = <0>;

        external_phy_port1: ethernet-phy@0 {
            reg = <0>;
        };

        external_phy_port2: ethernet-phy@1 {
            reg = <1>;
        };

        external_phy_port3: ethernet-phy@2 {
            reg = <2>;
        };

        external_phy_port4: ethernet-phy@3 {
            reg = <3>;
        };

        external_phy_port5: ethernet-phy@4 {
            reg = <4>;
        };

        switch@10 {
            compatible = "qca,qca8337";
            #address-cells = <1>;
            #size-cells = <0>;
            reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
            reg = <0x10>;

            ports {
                #address-cells = <1>;
                #size-cells = <0>;

                port@0 {
                    reg = <0>;
                    label = "cpu";
                    ethernet = <&gmac1>;
                    phy-mode = "rgmii";

                    fixed-link {
                        speed = <1000>;
                        full-duplex;
                    };
                };

                port@1 {
                    reg = <1>;
                    label = "lan1";
                    phy-handle = <&external_phy_port1>;
                };

                port@2 {
                    reg = <2>;
                    label = "lan2";
                    phy-handle = <&external_phy_port2>;
                };

                port@3 {
                    reg = <3>;
                    label = "lan3";
                    phy-handle = <&external_phy_port3>;
                };

                port@4 {
                    reg = <4>;
                    label = "lan4";
                    phy-handle = <&external_phy_port4>;
                };

                port@5 {
                    reg = <5>;
                    label = "wan";
                    phy-handle = <&external_phy_port5>;
                };
            };
        };
    };
  - |
    #include <dt-bindings/gpio/gpio.h>

    mdio {
        #address-cells = <1>;
        #size-cells = <0>;

        switch@10 {
            compatible = "qca,qca8337";
            #address-cells = <1>;
            #size-cells = <0>;
            reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
            reg = <0x10>;

            ports {
                #address-cells = <1>;
                #size-cells = <0>;

                port@0 {
                    reg = <0>;
                    label = "cpu";
                    ethernet = <&gmac1>;
                    phy-mode = "rgmii";

                    fixed-link {
                        speed = <1000>;
                        full-duplex;
                    };
                };

                port@1 {
                    reg = <1>;
                    label = "lan1";
                    phy-mode = "internal";
                    phy-handle = <&internal_phy_port1>;
                };

                port@2 {
                    reg = <2>;
                    label = "lan2";
                    phy-mode = "internal";
                    phy-handle = <&internal_phy_port2>;
                };

                port@3 {
                    reg = <3>;
                    label = "lan3";
                    phy-mode = "internal";
                    phy-handle = <&internal_phy_port3>;
                };

                port@4 {
                    reg = <4>;
                    label = "lan4";
                    phy-mode = "internal";
                    phy-handle = <&internal_phy_port4>;
                };

                port@5 {
                    reg = <5>;
                    label = "wan";
                    phy-mode = "internal";
                    phy-handle = <&internal_phy_port5>;
                };

                port@6 {
                    reg = <0>;
                    label = "cpu";
                    ethernet = <&gmac1>;
                    phy-mode = "sgmii";

                    qca,sgmii-rxclk-falling-edge;

                    fixed-link {
                        speed = <1000>;
                        full-duplex;
                    };
                };
            };

            mdio {
                #address-cells = <1>;
                #size-cells = <0>;

                internal_phy_port1: ethernet-phy@0 {
                    reg = <0>;
                };

                internal_phy_port2: ethernet-phy@1 {
                    reg = <1>;
                };

                internal_phy_port3: ethernet-phy@2 {
                    reg = <2>;
                };

                internal_phy_port4: ethernet-phy@3 {
                    reg = <3>;
                };

                internal_phy_port5: ethernet-phy@4 {
                    reg = <4>;
                };
            };
        };
    };
+4 −1
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@ examples:
        switch@10 {
            compatible = "qca,qca8337";
            reg = <0x10>;

            ports {
              /* ... */
            };
        };
    };
+288 −77

File changed.

Preview size limit exceeded, changes collapsed.

+31 −4
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/gpio.h>

#define QCA8K_NUM_PORTS					7
#define QCA8K_NUM_CPU_PORTS				2
#define QCA8K_MAX_MTU					9000

#define PHY_ID_QCA8327					0x004dd034
@@ -24,8 +25,6 @@

#define QCA8K_NUM_FDB_RECORDS				2048

#define QCA8K_CPU_PORT					0

#define QCA8K_PORT_VID_DEF				1

/* Global control registers */
@@ -35,16 +34,26 @@
#define   QCA8K_MASK_CTRL_DEVICE_ID_MASK		GENMASK(15, 8)
#define   QCA8K_MASK_CTRL_DEVICE_ID(x)			((x) >> 8)
#define QCA8K_REG_PORT0_PAD_CTRL			0x004
#define   QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE	BIT(19)
#define   QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE	BIT(18)
#define QCA8K_REG_PORT5_PAD_CTRL			0x008
#define QCA8K_REG_PORT6_PAD_CTRL			0x00c
#define   QCA8K_PORT_PAD_RGMII_EN			BIT(26)
#define   QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK		GENMASK(23, 22)
#define   QCA8K_PORT_PAD_RGMII_TX_DELAY(x)		((x) << 22)
#define   QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK		GENMASK(21, 20)
#define   QCA8K_PORT_PAD_RGMII_RX_DELAY(x)		((x) << 20)
#define	  QCA8K_PORT_PAD_RGMII_TX_DELAY_EN		BIT(25)
#define   QCA8K_PORT_PAD_RGMII_RX_DELAY_EN		BIT(24)
#define   QCA8K_MAX_DELAY				3
#define   QCA8K_PORT_PAD_SGMII_EN			BIT(7)
#define QCA8K_REG_PWS					0x010
#define   QCA8K_PWS_POWER_ON_SEL			BIT(31)
/* This reg is only valid for QCA832x and toggle the package
 * type from 176 pin (by default) to 148 pin used on QCA8327
 */
#define   QCA8327_PWS_PACKAGE148_EN			BIT(30)
#define   QCA8K_PWS_LED_OPEN_EN_CSR			BIT(24)
#define   QCA8K_PWS_SERDES_AEN_DIS			BIT(7)
#define QCA8K_REG_MODULE_EN				0x030
#define   QCA8K_MODULE_EN_MIB				BIT(0)
@@ -100,6 +109,11 @@
#define   QCA8K_SGMII_MODE_CTRL_PHY			(1 << 22)
#define   QCA8K_SGMII_MODE_CTRL_MAC			(2 << 22)

/* MAC_PWR_SEL registers */
#define QCA8K_REG_MAC_PWR_SEL				0x0e4
#define   QCA8K_MAC_PWR_RGMII1_1_8V			BIT(18)
#define   QCA8K_MAC_PWR_RGMII0_1_8V			BIT(19)

/* EEE control registers */
#define QCA8K_REG_EEE_CTRL				0x100
#define  QCA8K_REG_EEE_CTRL_LPI_EN(_i)			((_i + 1) * 2)
@@ -248,14 +262,27 @@ struct ar8xxx_port_status {

struct qca8k_match_data {
	u8 id;
	bool reduced_package;
};

enum {
	QCA8K_CPU_PORT0,
	QCA8K_CPU_PORT6,
};

struct qca8k_ports_config {
	bool sgmii_rx_clk_falling_edge;
	bool sgmii_tx_clk_falling_edge;
	bool sgmii_enable_pll;
	u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
	u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
};

struct qca8k_priv {
	u8 switch_id;
	u8 switch_revision;
	u8 rgmii_tx_delay;
	u8 rgmii_rx_delay;
	bool legacy_phy_port_mapping;
	struct qca8k_ports_config ports_config;
	struct regmap *regmap;
	struct mii_bus *bus;
	struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];